summaryrefslogtreecommitdiff
path: root/src/authorization/cedar_authorizer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/authorization/cedar_authorizer.rs')
-rw-r--r--src/authorization/cedar_authorizer.rs183
1 files changed, 0 insertions, 183 deletions
diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs
deleted file mode 100644
index 0d30ee77..00000000
--- a/src/authorization/cedar_authorizer.rs
+++ /dev/null
@@ -1,183 +0,0 @@
-use super::authorizer::Authorizer;
-use std::fs;
-use std::str::FromStr;
-
-#[derive(Debug)]
-pub struct CedarAuthorizer {
- authorizer: cedar_policy::Authorizer,
- entities: cedar_policy::Entities,
- policies: cedar_policy::PolicySet,
-}
-
-impl CedarAuthorizer {
- pub fn new(
- policies: cedar_policy::PolicySet,
- entities: cedar_policy::Entities,
- ) -> CedarAuthorizer {
- CedarAuthorizer {
- policies,
- entities,
- authorizer: cedar_policy::Authorizer::new(),
- }
- }
-
- pub fn new_from(path: &std::path::Path, entities: cedar_policy::Entities) -> CedarAuthorizer {
- Self::new(
- Self::load_from(path).unwrap_or_else(|e| {
- tracing::error!(
- path = ?path,
- error = %e,
- "Failed to load Cedar policies, using empty policy set"
- );
- cedar_policy::PolicySet::default()
- }),
- entities,
- )
- }
-
- fn load_from(
- path: &std::path::Path,
- ) -> Result<cedar_policy::PolicySet, Box<dyn std::error::Error>> {
- if !path.exists() {
- return Ok(cedar_policy::PolicySet::default());
- }
-
- if path.is_file() && path.extension().is_some_and(|ext| ext == "cedar") {
- let content = fs::read_to_string(path)?;
- return Ok(cedar_policy::PolicySet::from_str(&content)?);
- }
-
- if !path.is_dir() {
- return Ok(cedar_policy::PolicySet::default());
- }
-
- let mut policies = cedar_policy::PolicySet::new();
- for entry in fs::read_dir(path)? {
- policies.merge(&Self::load_from(&entry?.path())?, true)?;
- }
- Ok(policies)
- }
-
- fn map_from(
- &self,
- http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest,
- ) -> Result<cedar_policy::Request, Box<dyn std::error::Error>> {
- let principal = self.principal_from(&http_request)?;
- let permission = self.permission_from(&http_request)?;
- let resource = self.resource_from(&http_request)?;
- let context = self.context_from(http_request)?;
-
- Ok(cedar_policy::Request::new(
- principal, permission, resource, context, None,
- )?)
- }
-
- fn principal_from(
- &self,
- http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest,
- ) -> Result<cedar_policy::EntityUid, Box<dyn std::error::Error>> {
- let subject = http_request
- .headers
- .get("x-jwt-claim-sub")
- .map_or("", |v| v);
-
- Ok(cedar_policy::EntityUid::from_type_name_and_id(
- cedar_policy::EntityTypeName::from_str("User")?,
- cedar_policy::EntityId::from_str(subject)?,
- ))
- }
-
- fn permission_from(
- &self,
- http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest,
- ) -> Result<cedar_policy::EntityUid, Box<dyn std::error::Error>> {
- Ok(cedar_policy::EntityUid::from_type_name_and_id(
- cedar_policy::EntityTypeName::from_str("Action")?,
- cedar_policy::EntityId::from_str(&http_request.method)?,
- ))
- }
-
- fn resource_from(
- &self,
- http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest,
- ) -> Result<cedar_policy::EntityUid, Box<dyn std::error::Error>> {
- Ok(cedar_policy::EntityUid::from_type_name_and_id(
- cedar_policy::EntityTypeName::from_str("Resource")?,
- cedar_policy::EntityId::from_str(&http_request.path)?,
- ))
- }
-
- fn context_from(
- &self,
- http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest,
- ) -> Result<cedar_policy::Context, Box<dyn std::error::Error>> {
- let mut items = std::collections::HashMap::new();
-
- items.insert("host".to_string(), self.safe_string(&http_request.host));
- items.insert("method".to_string(), self.safe_string(&http_request.method));
- items.insert("path".to_string(), self.safe_string(&http_request.path));
-
- Ok(cedar_policy::Context::from_pairs(
- items.into_iter().collect::<Vec<_>>(),
- )?)
- }
-
- fn safe_string(&self, item: &str) -> cedar_policy::RestrictedExpression {
- cedar_policy::RestrictedExpression::new_string(item.to_string())
- }
-}
-
-impl Default for CedarAuthorizer {
- fn default() -> Self {
- Self::new_from(
- std::path::Path::new("./etc/authzd"),
- cedar_policy::Entities::empty(),
- )
- }
-}
-
-impl Authorizer for CedarAuthorizer {
- fn authorize(&self, request: envoy_types::ext_authz::v3::pb::CheckRequest) -> bool {
- let http_request = match request
- .attributes
- .as_ref()
- .and_then(|attr| attr.request.as_ref())
- .and_then(|req| req.http.as_ref())
- {
- Some(http) => http,
- None => return false,
- };
-
- match self.map_from(http_request.clone()) {
- Ok(cedar_request) => {
- let response =
- self.authorizer
- .is_authorized(&cedar_request, &self.policies, &self.entities);
-
- let decision = response.decision();
-
- tracing::info!(
- decision = ?decision,
- diagnostics = ?response.diagnostics(),
- principal = %cedar_request.principal().unwrap(),
- action = %cedar_request.action().unwrap(),
- resource = %cedar_request.resource().unwrap(),
- host = %http_request.host,
- method = %http_request.method,
- path = %http_request.path,
- "http"
- );
-
- matches!(decision, cedar_policy::Decision::Allow)
- }
- Err(e) => {
- tracing::error!(
- error = %e,
- path = %http_request.path,
- "Failed to create Cedar request"
- );
- false
- }
- }
- }
-}