-
Notifications
You must be signed in to change notification settings - Fork 107
support hasTag() and getTag() in the validator #1218
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
Conversation
Signed-off-by: Craig Disselkoen <[email protected]>
Signed-off-by: Craig Disselkoen <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor comments
Signed-off-by: Craig Disselkoen <[email protected]>
Signed-off-by: Craig Disselkoen <[email protected]>
Signed-off-by: Craig Disselkoen <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, but I think there might be a bug in tag_types
for the AnyEntity
case (so permissive validation only)
ContainsAnyAll, | ||
/// While computing the type of a `.getTag()` operation | ||
#[error("tag types for a `.getTag()` operation")] | ||
GetTag, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a test covering this variant. Probably would need to use the permissive validation mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this -- caught a case where we were actually throwing the new internal invariant violation error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, added a test permissive_tags
that caught one bug in permissive validation of tags, but doesn't actually exercise this case. I'm not as familiar with the validation algorithm -- any help on how I can construct a legal expression e
of arbitrary LUB type? (You can see in the new test that if-then-else is not legal for constructing arbitrary LUBs, even in permissive mode)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't it? I see an error message I see tag types for a `.getTag()` operation must have compatible types
as the expected error message for a test case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess if you want a test case where this error might be raised but isn't you could do something with record type tags. So, entity A tags { foo : Long };
and entity B tags { foo : Long, bar: Long}
) { | ||
Ok(ty) => ty, | ||
Err(e) => { | ||
type_errors.push(ValidationError::incompatible_types( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit different from how the same situation is handled for an attribute access. IIRC, in that case we would call the access unsafe instead of complaining about the LUB directly. Not sure which ultimately gives the better user experience, but it'd be nice if these similar cases were handled in the same way.
expect_err( | ||
src, | ||
&miette::Report::new(error), | ||
&ExpectedErrorMessageBuilder::error(r#"for policy `0`, unable to guarantee safety of access to tag `"foo"` on entity type `Blank`"#) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expected this to be a NoTagsAllowed
error, but the message looks like a UnsafeTagAccess
. Is that correct? Should we have another test for NoTagsAllowed
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's correct. Compare that the same policy with a has
check does validate (see test immediately below), so suggesting the has
check is a valid suggestion. I think that NoTagsAllowed
is actually unreachable, because it's only thrown when you do have a capability but the entity type doesn't support tags, and I don't think there's a way to have a capability when the entity type doesn't support tags, because the .hasTag
operation would be typed false
and prevent typechecking of the branch where you would have had the capability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.
Suggesting a has
check when that has
would always be false
isn't ideal and we could probably add another flag to the error to catch it (left a similar common on the action
error message).
EntityRecordKind::AnyEntity => Ok(self | ||
.schema | ||
.entity_types() | ||
.filter_map(|(_, vety)| vety.tag_type()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might not work. IIRC, AnyEntity
could include actions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate what's wrong here? I assume that AnyEntity
means a LUB of all entities in the schema, and regardless of whether that includes actions or not, this function is documented to ignore any entity types that do not have tags (which will include all actions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I think the code is correct overall. I guess I'm still confused about what exactly this function is supposed to compute. Does it just need to be a super set of the possible tags types for all types in kind
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's very possible the spec (in the comments) for this function is wrong. It's used to determine the type of a .getTag()
expression. Hard to think through the correct behavior of e.getTag(expr)
when e
is some LUB that contains some entities that do and some entities that do not have tags, or contains entities with different tag types. Maybe the former case should just be an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could soundly type e.getTag(expr)
for an e
without tags as ⊥
(as long as we have the appropriate capability), so from that perspective it doesn't impact the tag LUB so we can just ignore it which looks like what you're doing here.
That's not quite how entity attribute are handled atm. IIRC (haven't tested) e.attr
when an entity type in e
doesn't not have the attribute is an error even when there's an appropriate capability.
Signed-off-by: Craig Disselkoen <[email protected]> Co-authored-by: John Kastner <[email protected]>
…sed (#1213) Signed-off-by: Craig Disselkoen <[email protected]>
Signed-off-by: Craig Disselkoen <[email protected]>
Signed-off-by: Craig Disselkoen <[email protected]>
src, | ||
&miette::Report::new(error), | ||
&ExpectedErrorMessageBuilder::error(r#"for policy `0`, unable to guarantee safety of access to tag `"foo"`"#) | ||
.help(r#"try testing for the tag's presence with `.hasTag("foo") && ..`"#) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Room for specializing this error message. Technically it'll fix the error, but leave you with a warning.
Signed-off-by: Craig Disselkoen <[email protected]>
Signed-off-by: Craig Disselkoen <[email protected]>
Signed-off-by: Craig Disselkoen <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks good IMO. Maybe there's more discussion to be had about the exact behavior in permissive validation, but that's experimental (and so is this PR, so doubly experimental) and the current behavior should be sound, so I'm happy with it
Merging per the above comment. |
Signed-off-by: Craig Disselkoen <[email protected]> Co-authored-by: John Kastner <[email protected]> Co-authored-by: Kesha Hietala <[email protected]>
Description of changes
Support
.hasTag()
and.getTag()
(RFC 82) in the validator.Issue #, if available
RFC 82
Checklist for requesting a review
The change in this PR is (choose one, and delete the other options):
cedar-policy
(e.g., addition of a new API).I confirm that this PR (choose one, and delete the other options):
I confirm that
cedar-spec
(choose one, and delete the other options):cedar-spec
, and how you have tested that your updates are correct.)