diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-10 17:49:29 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-10 17:49:29 -0600 |
| commit | ef572ae666732e87a35417710669ce88233a754a (patch) | |
| tree | 3cc32004dee9600014417d404dbe01ac0e1faca9 /src/authorization/cedar_authorizer.rs | |
| parent | 8417a15087cc6f42c77fe070011ac2207f8d852d (diff) | |
| parent | 6721aaffa33894624c87a54f4ed10eccd3c080e5 (diff) | |
Merge branch 'entities' into 'main'
Use a static ACL file(s) to make authorization decisions
See merge request gitlab-org/software-supply-chain-security/authorization/authzd!6
Diffstat (limited to 'src/authorization/cedar_authorizer.rs')
| -rw-r--r-- | src/authorization/cedar_authorizer.rs | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 64287414..662aafeb 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -23,7 +23,14 @@ impl CedarAuthorizer { pub fn new_from(path: &std::path::Path, entities: cedar_policy::Entities) -> CedarAuthorizer { Self::new( - Self::load_from(path).unwrap_or_else(|_| cedar_policy::PolicySet::default()), + 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, ) } @@ -31,27 +38,24 @@ impl CedarAuthorizer { fn load_from( path: &std::path::Path, ) -> Result<cedar_policy::PolicySet, Box<dyn std::error::Error>> { - if !path.exists() || !path.is_dir() { + if !path.exists() { return Ok(cedar_policy::PolicySet::default()); } - let mut policies = cedar_policy::PolicySet::new(); - for entry in fs::read_dir(path)? { - let file_path = entry?.path(); - - if let Some(extension) = file_path.extension() { - if extension == "cedar" { - let content = fs::read_to_string(&file_path)?; - let file_policies = cedar_policy::PolicySet::from_str(&content)?; + if path.is_file() && path.extension().map_or(false, |ext| ext == "cedar") { + let content = fs::read_to_string(&path)?; + return Ok(cedar_policy::PolicySet::from_str(&content)?); + } - for policy in file_policies.policies() { - policies.add(policy.clone())?; - } - } - } + if !path.is_dir() { + return Ok(cedar_policy::PolicySet::default()); } - Ok(policies) + let mut policies = cedar_policy::PolicySet::new(); + for entry in fs::read_dir(path)? { + policies.merge(&Self::load_from(&entry?.path())?, true)?; + } + return Ok(policies); } fn map_from( @@ -70,31 +74,36 @@ impl CedarAuthorizer { fn principal_from( &self, - _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, + 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("client")?, + cedar_policy::EntityId::from_str(subject)?, )) } fn permission_from( &self, - _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, + 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("check")?, + cedar_policy::EntityId::from_str(&http_request.method)?, )) } fn resource_from( &self, - _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, + 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("resource")?, + cedar_policy::EntityId::from_str(&http_request.path)?, )) } @@ -104,7 +113,6 @@ impl CedarAuthorizer { ) -> Result<cedar_policy::Context, Box<dyn std::error::Error>> { let mut items = std::collections::HashMap::new(); - items.insert("bearer_token".to_string(), self.token_from(&http_request)); 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)); @@ -114,19 +122,6 @@ impl CedarAuthorizer { )?) } - fn token_from( - &self, - http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, - ) -> cedar_policy::RestrictedExpression { - let bearer_token = &http_request - .headers - .get("authorization") - .and_then(|auth| auth.strip_prefix("Bearer ")) - .unwrap_or(""); - - self.safe_string(bearer_token) - } - fn safe_string(&self, item: &str) -> cedar_policy::RestrictedExpression { cedar_policy::RestrictedExpression::new_string(item.to_string()) } |
