generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 135
Open
Labels
bugSomething isn't working. This is as high priority issue.Something isn't working. This is as high priority issue.
Description
Before opening, please confirm:
- I have searched for duplicate or closed issues.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
Describe the bug
Using Cedar 4.9.1, When you attempt to serialize a residual that contains an error() node to JSON, you get an error "Failed to serialize residual to JSON: error is not a valid function".
The program below makes an is_authorized_partial that results in a residual with an error node because the resource in question has no assignedTo property. It produces the following output :
Decision: None
Residual policy (cedar text): permit(
principal,
action,
resource
) when {
(((context.commonConditionals) has mfa) && false) && (error())
};
ERROR: Failed to serialize residual to JSON: `error` is not a valid function
Policy ID: policy0
Cedar text: permit(
principal,
action,
resource
) when {
(((context.commonConditionals) has mfa) && false) && (error())
};
We should still be able to serialize that residual to JSON and evaluate it in the calling program, since at the end of the day the condition resolves to false and there isn't actually an error.
Discussed on the Cedar slack, thread here: https://cedar-policy.slack.com/archives/C070BAB44FP/p1772647162731879
Reproduction steps
use cedar_policy::{
Entities, EntityUid, PartialEntities, PartialEntityUid, PartialRequest, PolicySet, Schema,
Validator,
};
const SCHEMA_CEDAR: &str = r#"
entity User = {
name: String,
};
entity Account = {
name: String,
assignedTo?: User,
};
type MFAConditional = {
met: Bool,
};
type CommonConditionals = {
mfa?: MFAConditional,
};
action RevealCredentials appliesTo {
principal: [User],
resource: [Account],
context: {
commonConditionals: CommonConditionals,
},
};
"#;
// A policy with a "has" guarding access to assignedTo
const POLICY: &str = r#"permit (
principal is User,
action == Action::"RevealCredentials",
resource is Account
)
when { context.commonConditionals has mfa && resource has assignedTo && resource.assignedTo == principal };"#;
// Note that there's no `assignedTo` on the account's attrs
const ENTITIES_JSON: &str = r#"[
{
"uid": {
"type": "User",
"id": "user1"
},
"parents": [],
"attrs": {
"name": "testuser"
},
"tags": {}
},
{
"uid": {
"type": "Account",
"id": "account1"
},
"parents": [],
"attrs": {
"name": "sharedaccount1"
},
"tags": {}
}
]"#;
fn main() {
// Parse schema from Cedar human-readable format
let (schema, _warnings) =
Schema::from_cedarschema_str(SCHEMA_CEDAR).expect("Failed to parse schema");
// Parse and validate policy
let policy_set: PolicySet = POLICY.parse().expect("Failed to parse policy");
let validator = Validator::new(schema.clone());
let validation_result =
validator.validate(&policy_set, cedar_policy::ValidationMode::default());
assert!(
validation_result.validation_passed(),
"Policy validation failed: {:?}",
validation_result.validation_errors().collect::<Vec<_>>()
);
// Parse entities
let entities =
Entities::from_json_str(ENTITIES_JSON, Some(&schema)).expect("Failed to parse entities");
let partial_entities = PartialEntities::from_concrete(entities, &schema)
.expect("Failed to create partial entities");
// Build partial request with no context (context is unknown)
let principal = PartialEntityUid::from_concrete(
r#"User::"user1""#.parse::<EntityUid>().expect("Failed to parse principal"),
);
let action: EntityUid = r#"Action::"RevealCredentials""#
.parse()
.expect("Failed to parse action");
let resource = PartialEntityUid::from_concrete(
r#"Account::"account1""#.parse::<EntityUid>().expect("Failed to parse resource"),
);
let request = PartialRequest::new(principal, action, resource, None, &schema)
.expect("Failed to create partial request");
// Run TPE
let response = policy_set
.tpe(&request, &partial_entities, &schema)
.expect("TPE evaluation failed");
println!("Decision: {:?}", response.decision());
// Attempt to serialize residual policies to JSON — this is where the error occurs
for policy in response.nontrivial_residual_policies() {
println!("Residual policy (cedar text): {}", policy);
match policy.to_json() {
Ok(json) => println!("Residual policy (json): {}", json),
Err(e) => {
eprintln!("ERROR: Failed to serialize residual to JSON: {}", e);
eprintln!(" Policy ID: {}", policy.id());
eprintln!(" Cedar text: {}", policy);
panic!("to_json() failed on residual policy — this is the bug");
}
}
}
println!("All residual policies serialized successfully (no bug).");
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't working. This is as high priority issue.Something isn't working. This is as high priority issue.