Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update TinyTodo to use templates #82

Merged
merged 11 commits into from
Jan 1, 2024
Merged

Update TinyTodo to use templates #82

merged 11 commits into from
Jan 1, 2024

Conversation

mwhicks1
Copy link
Contributor

Description of changes: Updated TinyTodo to use templates, rather than groups in attributes.

My plan is to make this a new directory, or a feature flag, rather than change the code. But I submit it as a PR this way so you can easily see the diffs.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

// Construct policy ID; assumes no policy in the set has it already
let target_eid = target_euid.id();
let list_eid = list_euid.id();
let pid = PolicyId::from_str(&format!("{pid_prefix}[{target_eid}][{list_eid}]"))?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use a UUID here

Copy link
Contributor Author

@mwhicks1 mwhicks1 Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is. The list ID is under the app's control, so the last part of the ID is always [N] where N is a number. The first part always reader[ or editor[. The stuff in the middle is always the target user or team's ID with a trailing ]. Is this reasoning flawed? If not, IDs are sure to be an injective function of the three inputs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a comment that makes this clear.

@mwhicks1 mwhicks1 marked this pull request as ready for review December 21, 2023 15:12
tinytodo/TUTORIAL_TEMPLATE.md Show resolved Hide resolved
```
The first line tries to authorize the request; for our example, it checks that `User::"andrew"` can perform `Action::"EditShare"` on resource `List::"0"`. The `is_authorized` call returns `Ok()` because *policy 1* evaluates to `true`, since `List::"0".owner == User::"andrew"` (see Figure 3 in the original tutorial). The call to `get_list` then retrieves the native `List` object for `List::"0"` from `self.entities`, our `EntityStore`. The next call `get_user_or_team_mut` gets the `User` or `Team` to share the list with, which in this case is `Team::"interns"`. If either call fails then the target objects don't exist in the entity store and an error is sent back.

Next, we construct the name of the template we will link: if `r.role` is `Reader`, as in our example, the template ID is `reader-template`. Now we construct the entity UIDs to link `?principal` and `?resource` against, and store them in `env`, a hashmap. Then we call the function `linked_policy_id` (not shown) to construct the policy ID from the sharing role, the target user/team, and the list. This function is injective, so we can be sure no two linked policies will have the same ID. In the case of our example, a policy ID is `reader[interns][0]`. Finally, we link the policy into the policy store.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is injective, so we can be sure no two linked policies will have the same ID.

This feels like a bit of a flaw in our template linking API. This shouldn't be the callers responsibility.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it should not be a requirement, but it currently is.

As a concrete suggestion: How about adding an API that constructs the instance policy ID based on the template's ID and the IDs of its linked-in parameters, perhaps with some additional string prefix provided by the caller? E.g.,

templateID = reader
?principal = User::"Alice"
?resource = Photo::"vacation.jpg"
prefix = photo

yields linked policy ID

photo|reader|User::"Alice"|Photo::"vacation.jpg"

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After writing this up as an issue, I'm not sure if it's better than the status quo: cedar-policy/cedar#547

Some(_) => {
// found template in new policy set
match p.template_links() {
None => error!("Error when reloading policies: Template with no matching links"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this set err = true;?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an internal error, which should never happen. I.e., you should not have template_id() return Some(...) but then have template_links() return None. I'll change this to use expect and produce a panic! if it ever happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought: We could change the Policy::template_links() API to return both the linked values and the template ID, together in an Option. Then we wouldn't need multiple calls. You could just call template_links() as a way to test whether a policy is template-linked, and if it is to return Some(tid,links). That would simplify a bunch of logic here, and avoid the need for app code to assume the Cedar-internal invariant.

It would be changing the API, but we haven't released the PolicySet::template_links() API yet, so it won't be a breaking change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cedar-policy/cedar#548 -- I'm of a mixed mind about whether doing this is worth it.

tinytodo/src/context.rs Outdated Show resolved Hide resolved
tinytodo/src/context.rs Show resolved Hide resolved
@mwhicks1 mwhicks1 merged commit ac889c4 into main Jan 1, 2024
5 checks passed
@john-h-kastner-aws john-h-kastner-aws deleted the templates branch January 10, 2024 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants