diff options
| author | mo khan <mo@mokhan.ca> | 2025-06-27 10:40:44 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-06-27 10:40:44 -0600 |
| commit | afd9729146a7e90bd97bf36f9d2081e29de9da35 (patch) | |
| tree | 0251e024592fd10c2d6eb1d1580c69371c4586da | |
| parent | 9f4bf84825c5a725b0ea36d4474d4fa2cec916fd (diff) | |
feat: scan directory for all policy files
| -rw-r--r-- | src/authorization/cedar_authorizer.rs | 34 | ||||
| -rw-r--r-- | tests/authorization/cedar_authorizer_test.rs | 21 | ||||
| -rw-r--r-- | tests/authorization/check_service_test.rs | 11 | ||||
| -rw-r--r-- | tests/integration_tests.rs | 12 |
4 files changed, 60 insertions, 18 deletions
diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 568bafbc..4ec3b34d 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -5,6 +5,8 @@ use cedar_policy::{ }; use envoy_types::ext_authz::v3::pb::CheckRequest; use std::collections::HashMap; +use std::fs; +use std::path::Path; use std::str::FromStr; #[derive(Debug)] @@ -20,10 +22,40 @@ impl CedarAuthorizer { authorizer: CedarAuth::new(), } } + + pub fn new_from(dir_path: &str) -> CedarAuthorizer { + Self::new(Self::load_from(dir_path).unwrap_or_else(|_| PolicySet::default())) + } + + fn load_from(dir_path: &str) -> Result<PolicySet, Box<dyn std::error::Error>> { + let path = Path::new(dir_path); + if !path.exists() || !path.is_dir() { + return Ok(PolicySet::default()); + } + + let mut policies = 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 = PolicySet::from_str(&content)?; + + for policy in file_policies.policies() { + policies.add(policy.clone())?; + } + } + } + } + + Ok(policies) + } } impl Default for CedarAuthorizer { fn default() -> Self { - Self::new(PolicySet::default()) + Self::new_from("/etc/authzd") } } diff --git a/tests/authorization/cedar_authorizer_test.rs b/tests/authorization/cedar_authorizer_test.rs index d6742995..3073417d 100644 --- a/tests/authorization/cedar_authorizer_test.rs +++ b/tests/authorization/cedar_authorizer_test.rs @@ -6,9 +6,14 @@ mod tests { use envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest; use std::collections::HashMap; + fn authorizer() -> CedarAuthorizer { + CedarAuthorizer::new_from( + "/home/mokhax/src/gitlab.com/gitlab-org/software-supply-chain-security/authorization/authzd/etc/authzd", + ) + } + #[test] fn test_cedar_authorizer_allows_valid_token() { - let authorizer = CedarAuthorizer::default(); let request = create_request(|item: &mut HttpRequest| { item.headers = build_with(|item: &mut HashMap<String, String>| { item.insert( @@ -18,12 +23,11 @@ mod tests { }); }); - assert!(authorizer.authorize(request)); + assert!(authorizer().authorize(request)); } #[test] fn test_cedar_authorizer_denies_invalid_token() { - let authorizer = CedarAuthorizer::default(); let request = create_request(|item: &mut HttpRequest| { item.headers = build_with(|item: &mut HashMap<String, String>| { item.insert( @@ -33,40 +37,37 @@ mod tests { }); }); - assert!(!authorizer.authorize(request)); + assert!(!authorizer().authorize(request)); } #[test] fn test_cedar_authorizer_denies_missing_header() { - let authorizer = CedarAuthorizer::default(); let request = create_request(|item: &mut HttpRequest| { item.headers = HashMap::new(); }); - assert!(!authorizer.authorize(request)); + assert!(!authorizer().authorize(request)); } #[test] fn test_cedar_authorizer_allows_static_assets() { - let authorizer = CedarAuthorizer::default(); let request = create_request(|item: &mut HttpRequest| { item.headers = build_with(|item: &mut HashMap<String, String>| { item.insert(String::from(":path"), String::from("/public/style.css")); }); }); - assert!(authorizer.authorize(request)); + assert!(authorizer().authorize(request)); } #[test] fn test_cedar_authorizer_allows_js_assets() { - let authorizer = CedarAuthorizer::default(); let mut headers = HashMap::new(); headers.insert(":path".to_string(), "/app.js".to_string()); let request = create_request(|item: &mut HttpRequest| { item.headers = headers; }); - assert!(authorizer.authorize(request)); + assert!(authorizer().authorize(request)); } } diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index a739b16a..c101850c 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -8,10 +8,16 @@ mod tests { use std::collections::HashMap; use std::sync::Arc; + fn authorizer() -> Arc<dyn authzd::Authorizer + Send + Sync> { + Arc::new(CedarAuthorizer::new_from( + "/home/mokhax/src/gitlab.com/gitlab-org/software-supply-chain-security/authorization/authzd/etc/authzd", + )) + } + #[tokio::test] async fn test_check_allows_valid_bearer_token() { let token = create_token(); - let server = CheckService::new(Arc::new(CedarAuthorizer::default())); + let server = CheckService::new(authorizer()); let mut headers = HashMap::new(); headers.insert("authorization".to_string(), format!("Bearer {}", token)); @@ -30,8 +36,7 @@ mod tests { #[tokio::test] async fn test_check_denies_invalid_bearer_token() { - let authorizer = Arc::new(CedarAuthorizer::default()); - let server = CheckService::new(authorizer); + let server = CheckService::new(authorizer()); let request = tonic::Request::new(create_request(|item: &mut HttpRequest| { item.headers = HashMap::new(); })); diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index a265c2be..8bf433d1 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -7,10 +7,15 @@ use std::sync::Arc; mod authorization; mod common; +fn authorizer() -> Arc<dyn authzd::Authorizer + Send + Sync> { + Arc::new(CedarAuthorizer::new_from( + "/home/mokhax/src/gitlab.com/gitlab-org/software-supply-chain-security/authorization/authzd/etc/authzd", + )) +} + #[tokio::test] async fn test_success_response() { - let authorizer = Arc::new(CedarAuthorizer::default()); - let server = CheckService::new(authorizer); + let server = CheckService::new(authorizer()); let request = tonic::Request::new(factory_bot::create_request(|item: &mut HttpRequest| { item.headers = factory_bot::build_headers(vec![( "authorization".to_string(), @@ -30,8 +35,7 @@ async fn test_success_response() { #[tokio::test] async fn test_multiple() { - let authorizer = Arc::new(CedarAuthorizer::default()); - let server = CheckService::new(authorizer); + let server = CheckService::new(authorizer()); let test_cases = vec