-
Notifications
You must be signed in to change notification settings - Fork 23
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
feat: policy, template, and schema parsing #72
Conversation
d230441
to
c6f2eec
Compare
@@ -41,7 +54,8 @@ public Policy( | |||
throw new NullPointerException("Failed to construct policy from null string"); | |||
} | |||
if (policyID == null) { | |||
throw new NullPointerException("Failed to construct policy with null ID"); | |||
policyID = "policy" + idCounter; | |||
idCounter += 1; |
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 this could cause duplicate IDs if we construct Policy
objects from multiple threads. I guess we could:
- document this and leave it as-is
- use an
AtomicInteger
for the counter (presumably the overhead here isn't massive) - allow
null
policy IDs in this class – I think the Rust library's constructors now takeOption
s for policy IDs
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.
AtomicInteger seems like a good choice, will do that
public static boolean validateTemplateLinkedPolicy(Policy p, EntityUID principal, EntityUID resource) { | ||
try { | ||
return validateTemplateLinkedPolicyJni(p.policySrc, principal, resource); | ||
} catch (Exception e) { |
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.
Do we want to swallow every exception here? Internal exceptions might not mean an invalid policy.
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.
What else could they mean? Bear in mind that the principal, resource, and policy have already been parsed by the library so they're valid
I guess they could manually build a Policy
object from something invalid. I could consider re-parsing the policy this function takes, or making the rust-side change i mentioned below
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'm more thinking of exceptions that don't arise from the policy parsing calls specifically. For example, if we have a bug in our JNI code, perhaps that would surface as an exception from the JVM that we would want to bubble up. Possibly worrying too much here, but if we have a base class for our exceptions sitting around (InternalException
?) then it might make sense to use that.
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 im convinced to make it throw
* and EntityIdentifier.parse), then this should only fail because the slots in the template don't match the instantiations | ||
* (barring JNI failures). | ||
* @param p Policy object constructed from a valid template. Best if built from Policy.parsePolicyTemplate | ||
* @param principal EntityUid to put into the principal slot. Leave null if there's no principal slot |
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 probably not as idiomatic for Java, but I strongly prefer Optional
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.
Optional is not really a fit though, we need to surface why it failed if it fails. We have two choices that offer library ergonomics that are reasonable to java programmers:
- Just throw exceptions
- Use a library that implements an either monad, or implement it ourselves
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.
Sorry, I should have been more clear. I'd prefer that the principal
and resource
be Optional<EntityUID>
instead of using null
when there's no slot. I agree we should throw an exception on failure, not return an Optional<boolean>
.
CedarJavaFFI/src/objects.rs
Outdated
let basename_str = String::from(jstr_basename); | ||
let mut full_type_name: Vec<String> = jstr_list_to_rust_vec(env, &namespace)?; | ||
full_type_name.push(basename_str); | ||
let fulll_ns_str: String = full_type_name.join("::"); |
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.
let fulll_ns_str: String = full_type_name.join("::"); | |
let full_ns_str: String = full_type_name.join("::"); |
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 may also want to validate that none of the strings in namespace
contain ::
.
CedarJavaFFI/src/objects.rs
Outdated
let basename_str = String::from(jstr_basename); | ||
let mut full_type_name: Vec<String> = jstr_list_to_rust_vec(env, &namespace)?; | ||
full_type_name.push(basename_str); | ||
let fulll_ns_str: String = full_type_name.join("::"); |
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.
let fulll_ns_str: String = full_type_name.join("::"); | |
let full_ns_str: String = full_type_name.join("::"); |
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.
Same comment about checking for ::
's
@@ -36,7 +36,8 @@ public class EntityTypeNameTests { | |||
"else", | |||
"in", | |||
"like", | |||
"has" | |||
"has", | |||
"is" |
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.
luckily enough i ran into a test failure from this lol
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.
While it is nice that it will "eventually" catch the issue, but I really don't like non-determinism in CI. Created issue here: #73
* and EntityIdentifier.parse), then this should only fail because the slots in the template don't match the instantiations | ||
* (barring JNI failures). | ||
* @param p Policy object constructed from a valid template. Best if built from Policy.parsePolicyTemplate | ||
* @param principal EntityUid to put into the principal slot. Leave null if there's no principal slot |
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.
Sorry, I should have been more clear. I'd prefer that the principal
and resource
be Optional<EntityUID>
instead of using null
when there's no slot. I agree we should throw an exception on failure, not return an Optional<boolean>
.
@@ -36,7 +36,8 @@ public class EntityTypeNameTests { | |||
"else", | |||
"in", | |||
"like", | |||
"has" | |||
"has", | |||
"is" |
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.
While it is nice that it will "eventually" catch the issue, but I really don't like non-determinism in CI. Created issue here: #73
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.
Not a Java expert, but the new functionality looks good to me.
cedar-policy = { version = "3.0", path = "../cedar/cedar-policy" } # Need latest version from github | ||
cedar-policy = { version = "3.0", path = "../../cedar/cedar-policy" } # Need latest version from github |
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.
The README in CedarJavaFFI says that it should be ../cedar
, so you should either update this toml file or the README.
let jstr_basename = env.get_string(&basename)?; | ||
let basename_str = String::from(jstr_basename); | ||
let mut full_type_name: Vec<String> = jstr_list_to_rust_vec(env, &namespace_components)?; | ||
full_type_name.push(basename_str); | ||
let has_namespace_component_with_colon = full_type_name.iter().any(|s| s.contains("::")); | ||
if has_namespace_component_with_colon { | ||
return Err("components of the type name cannot contain colons".into()); | ||
} | ||
let full_ns_str: String = full_type_name.join("::"); | ||
let type_name: EntityTypeName = full_ns_str.parse()?; |
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 looks like the same code as L42-51. Might be nice to centralize this logic in case we end up changing handling in the future.
Co-authored-by: Victor Moreno <[email protected]>
Co-authored-by: Victor Moreno <[email protected]>
Issue #, if available:
n/a
Description of changes:
JEntityTypeName
andJEntityId
. The old code did not allow construction of an invalid id, but it did allow construction of an invalidJEntityTypeName
. I changed it so it fails at construction time if it's invalid.get_rust_repr
.