u/Paul-E0

▲ 5 r/rust

People using Cedar policies, how are you managing them?

I'm exploring policy languages for authorization in my application. I took a look at Cedar, and it seems like a good fit because it written in Rust and has first class support for the language, but programatically creating and managing policies seems awkward. This has been a stumbling block for me and I'm curious how people are using cedar policies.

Most of the documentation provides examples of policies that are written out in human readable formats, like this

permit(
  principal == User::"alice",
  action == Action::"update",
  resource == Photo::"VacationPhoto94.jpg"
);

These examples make sense if users are writing your policies and managing a text file of policies. But in most system's I've built, the nobody is writing out authorization policies in text. Usually you have a UI over your authorization core and your users are adding and removing permissions for users and groups of users via the UI. In this situation the text based policy approach becomes awkward and it seems like the preferred (only?) API for policy creation and management.

Looking at the examples, it doesn't seem like there is a "native" alternative to string based approach. The official tindytodo example has code like this:

lazy_static! {
    pub static ref APPLICATION_TINY_TODO: EntityUid = r#"Application::"TinyTodo""#.parse().unwrap();
    static ref ACTION_EDIT_SHARE: EntityUid = r#"Action::"EditShare""#.parse().unwrap();
    static ref ACTION_UPDATE_TASK: EntityUid = r#"Action::"UpdateTask""#.parse().unwrap();
    static ref ACTION_CREATE_TASK: EntityUid = r#"Action::"CreateTask""#.parse().unwrap();
    static ref ACTION_DELETE_TASK: EntityUid = r#"Action::"DeleteTask""#.parse().unwrap();
    static ref ACTION_GET_LISTS: EntityUid = r#"Action::"GetLists""#.parse().unwrap();
    static ref ACTION_GET_LIST: EntityUid = r#"Action::"GetList""#.parse().unwrap();
    static ref ACTION_CREATE_LIST: EntityUid = r#"Action::"CreateList""#.parse().unwrap();
    static ref ACTION_UPDATE_LIST: EntityUid = r#"Action::"UpdateList""#.parse().unwrap();
    static ref ACTION_DELETE_LIST: EntityUid = r#"Action::"DeleteList""#.parse().unwrap();
}

It seems like suggested way of creating policies is by constructing policy strings, it doesn't seem like there is a Rust "native" API. In my own attempts at using cedar I've ended up doing something similar to what you see in the examples, using strings to define my actors, actions, and entities. This doesn't feel right.

And then when policies are created, its not clear how you should manage them. The docs indicate you could have users x objects policies:

> For example, if you have 10 users and 10 resource types, that could mean 100 policies. This is expected and correct

If a Alice removes Bob's access to one of her documents, how should the application find this policy in the pile of json/string policies? In practice this has involved iterating every single policy, with a lot of string parsing and string equality checks, which feels wrong in Rust.

The way cedar expects you to use it does not feel idiomatic. It feels like there is a missing layer/library over cedar policies for programmatic usage, eg one where your actions are enums, but I don't know if I am "holding it wrong".

reddit.com
u/Paul-E0 — 10 hours ago