AWS has open-sourced Cedar, their language for defining access permissions using policies. Cedar is integrated within both Amazon Verified Permissions and AWS Verified Access. Cedar can also be integrated directly into an application via the provided SDK and language specification.
Cedar allows for expressing policies separate from the application code. This decoupling enables them to be independently authored, analyzed, and audited. Cedar supports role-based access control (RBAC) and attribute-based access control (ABAC) approaches.
The SDK can be used for authoring and validating policies as well as authorizing access requests. Cedar is written in Rust but also has both a Rust crate and a Java package to allow for using Cedar from Java.
Validating that a request is authorized can be done by invoking the Cedar authorization engine. The request information is translated into a Cedar request and passed into the Cedar authorization engine. The following example demonstrates this in Rust:
pub fn is_authorized(
&self,
principal: impl AsRef<EntityUid>,
action: impl AsRef<EntityUid>,
resource: impl AsRef<EntityUid>,
) -> Result<()> {
let es = self.entities.as_entities();
let q = Request::new(
Some(principal.as_ref().clone().into()),
Some(action.as_ref().clone().into()),
Some(resource.as_ref().clone().into()),
Context::empty(),
);
info!(
"is_authorized request: principal: {}, action: {}, resource: {}",
principal.as_ref(),
action.as_ref(),
resource.as_ref()
);
let response = self.authorizer.is_authorized(&q, &self.policies, &es);
info!("Auth response: {:?}", response);
match response.decision() {
Decision::Allow => Ok(()),
Decision::Deny => Err(Error::AuthDenied(response.diagnostics().clone())),
}
}
The Cedar authorization engine is invoked via the call self.authorizer.is_authorized(&q, &self.policies, &es)
. The arguments to the call include the access request, Cedar policies, and the entity set. The access request contains the principal, action, and resource information needed to confirm if the request is permitted. Based on the analysis, the call will return either Decision::Allow
or Decision::Deny
.
Policies can be created via the SDK as well. The following Java example creates a policy that permits the principal Alice to perform the action View_Photo on any resource that is a child of the Vacation resource:
private Set<Policy> buildPolicySlice() {
Set<Policy> ps = new HashSet<>();
String fullPolicy = "permit(principal == User::\"Alice\", action == Action::\"View_Photo\", resource in Album::\"Vacation\");";
ps.add(new Policy(fullPolicy, "p1"));
return ps;
}
In Java, a query can be performed using the isAuthorized method:
public boolean sampleMethod() throws AuthException {
AuthorizationEngine ae = new WrapperAuthorizationEngine();
AuthorizationQuery q = new AuthorizationQuery("User::\"Alice\"", "Action::\"View_Photo\"", "Photo::\"pic01\"");
return ae.isAuthorized(q, buildSlice()).isAllowed();
}
Permit.io followed the AWS announcement with the release of Cedar-Agent, an HTTP server that acts as a policy store and data store for Cedar-based policies. The store allows for creating, retrieving, updating, and deleting policies. The data store allows for in-memory storage of the application's data. It integrates with Cedar-Agent to allow for authorization checks to be performed on the stored data. Authorization checks are performed on incoming HTTP requests.
User dadadad100, on a HackerNews post, commented that they saw Cedar potentially filling a gap in the application authorization space:
Cedar falls somewhere between OPA with its datalog (prolog) based search approach and a Zanzibar based approach. It’s not clear which direction will win out, but it is time that this problem got some attention.
Other users, such as Oxbadcafebee, expressed frustration that AWS didn't lend their support to Open Policy Agent instead.
Cedar is open-source under Apache License 2.0 and is available via GitHub. More details can be found in the recent AWS blog and by joining the Cedar Policy Slack workspace.