From 2185b6d8a80d78e3b1b1421f99cab884705d3cbf Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 13:29:34 -0600 Subject: refactor: start to refactor the sparkle policies --- src/authorization/cedar_authorizer.rs | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 432102ef..17867aba 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -1,10 +1,9 @@ use super::authorizer::Authorizer; use cedar_policy::{ Authorizer as CedarAuth, Context, Entities, EntityId, EntityTypeName, EntityUid, PolicySet, - Request as CedarRequest, RestrictedExpression, + Request as CedarRequest, }; use envoy_types::ext_authz::v3::pb::CheckRequest; -use std::collections::HashMap; use std::fs; use std::str::FromStr; @@ -86,14 +85,7 @@ impl Authorizer for CedarAuthorizer { return true; } - let headers = &http_request.headers; - - let bearer_token = headers - .get("authorization") - .and_then(|auth| auth.strip_prefix("Bearer ")) - .unwrap_or(""); - - match self.create_cedar_request(bearer_token, &http_request.path.to_string()) { + match self.create_cedar_request(http_request.clone()) { Ok(cedar_request) => { let entities = Entities::empty(); let response = @@ -117,9 +109,14 @@ impl Authorizer for CedarAuthorizer { impl CedarAuthorizer { fn create_cedar_request( &self, - bearer_token: &str, - path: &str, + http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { + let headers = &http_request.headers; + let bearer_token = headers + .get("authorization") + .and_then(|auth| auth.strip_prefix("Bearer ")) + .unwrap_or(""); + // Create principal entity let principal_id = EntityId::from_str("client")?; let principal_type = EntityTypeName::from_str("User")?; @@ -135,18 +132,17 @@ impl CedarAuthorizer { let resource_type = EntityTypeName::from_str("Resource")?; let resource = EntityUid::from_type_name_and_id(resource_type, resource_id); - // Create context with bearer token and path - let mut context_map = HashMap::new(); + let mut context_map = std::collections::HashMap::new(); if !bearer_token.is_empty() { context_map.insert( "bearer_token".to_string(), - RestrictedExpression::from_str(&format!("\"{bearer_token}\""))?, + cedar_policy::RestrictedExpression::from_str(bearer_token)?, ); } - if !path.is_empty() { + if !http_request.path.is_empty() { context_map.insert( "path".to_string(), - RestrictedExpression::from_str(&format!("\"{path}\""))?, + cedar_policy::RestrictedExpression::from_str(&http_request.path.to_string())?, ); } -- cgit v1.2.3 From 784e0740a6ca7684feba3fb4f26d68e098b5c826 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 16:39:37 -0600 Subject: refactor: map from http request to cedar request --- src/authorization/cedar_authorizer.rs | 8 ++++---- tests/authorization/cedar_authorizer_test.rs | 20 ++++++++------------ tests/authorization/check_service_test.rs | 17 +++++++---------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 17867aba..4eeaf645 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -85,7 +85,7 @@ impl Authorizer for CedarAuthorizer { return true; } - match self.create_cedar_request(http_request.clone()) { + match self.map_from(http_request.clone()) { Ok(cedar_request) => { let entities = Entities::empty(); let response = @@ -107,7 +107,7 @@ impl Authorizer for CedarAuthorizer { } impl CedarAuthorizer { - fn create_cedar_request( + fn map_from( &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { @@ -136,13 +136,13 @@ impl CedarAuthorizer { if !bearer_token.is_empty() { context_map.insert( "bearer_token".to_string(), - cedar_policy::RestrictedExpression::from_str(bearer_token)?, + cedar_policy::RestrictedExpression::new_string(bearer_token.to_string()), ); } if !http_request.path.is_empty() { context_map.insert( "path".to_string(), - cedar_policy::RestrictedExpression::from_str(&http_request.path.to_string())?, + cedar_policy::RestrictedExpression::new_string(http_request.path.clone()), ); } diff --git a/tests/authorization/cedar_authorizer_test.rs b/tests/authorization/cedar_authorizer_test.rs index 79f83c00..317ef67f 100644 --- a/tests/authorization/cedar_authorizer_test.rs +++ b/tests/authorization/cedar_authorizer_test.rs @@ -8,12 +8,10 @@ mod tests { #[test] fn test_cedar_authorizer_allows_valid_token() { let request = build_request(|item: &mut HttpRequest| { - item.headers = build_with(|item: &mut HashMap| { - item.insert( - String::from("authorization"), - String::from("Bearer valid-token"), - ); - }); + item.headers = build_headers(vec![( + "authorization".to_string(), + "Bearer valid-token".to_string(), + )]); }); assert!(build_cedar_authorizer().authorize(request)); @@ -22,12 +20,10 @@ mod tests { #[test] fn test_cedar_authorizer_denies_invalid_token() { let request = build_request(|item: &mut HttpRequest| { - item.headers = build_with(|item: &mut HashMap| { - item.insert( - String::from("authorization"), - String::from("Bearer invalid-token"), - ); - }); + item.headers = build_headers(vec![( + "authorization".to_string(), + "Bearer invalid-token".to_string(), + )]); }); assert!(!build_cedar_authorizer().authorize(request)); diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index a4b8f2ee..fe45712d 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -14,6 +14,7 @@ mod tests { #[tokio::test] async fn test_check_allows_valid_bearer_token() { let request = tonic::Request::new(build_request(|item: &mut HttpRequest| { + item.path = String::from("/"); item.headers = build_headers(vec![( "authorization".to_string(), format!("Bearer {}", String::from("valid-token")), @@ -100,13 +101,13 @@ mod tests { #[tokio::test] async fn test_table() { let test_cases = vec![ - ("Bearer valid-token", true), - ("Bearer invalid-token", false), - ("Basic valid-token", false), - ("", false), + ("Bearer valid-token", tonic::Code::Ok), + ("Bearer invalid-token", tonic::Code::Unauthenticated), + ("Basic valid-token", tonic::Code::Unauthenticated), + ("", tonic::Code::Unauthenticated), ]; - for (auth_value, should_succeed) in test_cases { + for (auth_value, expected_status_code) in test_cases { let request = tonic::Request::new(build_request(|item: &mut HttpRequest| { item.headers = build_headers(vec![("authorization".to_string(), auth_value.to_string())]); @@ -118,11 +119,7 @@ mod tests { let check_response = response.unwrap().into_inner(); let status = check_response.status.unwrap(); - if should_succeed { - assert_eq!(status.code, tonic::Code::Ok as i32); - } else { - assert_eq!(status.code, tonic::Code::Unauthenticated as i32); - } + assert_eq!(status.code, expected_status_code as i32); } } -- cgit v1.2.3 From c27093125aed8434c16655af7e7f415d84859dc7 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 17:03:20 -0600 Subject: test: start to build table tests --- tests/authorization/check_service_test.rs | 55 ++++++++++++++----------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index fe45712d..4ff7a89b 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -146,39 +146,34 @@ mod tests { // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "GET", Path: "/dashboard"}}, // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "GET", Path: "/dashboard", Headers: invalidHeaders}}, // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "POST", Path: "/sparkles"}}, - // - // http: - // method: \"GET\", - // headers: { - // \":method\": \"GET\", - // \":authority\": \"localhost:10000\", - // \":path\": \"/sparkles\", - // }, - // path: \"/sparkles\", - // host: \"localhost:10000\", - let request = tonic::Request::new(build_request(|item: &mut HttpRequest| { - let path = String::from("/"); - let method = String::from("GET"); - let host = String::from("sparkle.staging.runway.gitlab.net"); - - item.method = method.clone(); - item.path = path.clone(); - item.host = host.clone(); - item.headers = build_headers(vec![ - (String::from(":path"), path), - (String::from(":method"), method), - (String::from(":authority"), host), - ]); - })); + let test_cases = vec![( + "GET", + "/", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + )]; - let response = subject().check(request).await; - assert!(response.is_ok()); + for (method, path, host, expected_status_code) in test_cases { + let request = tonic::Request::new(build_request(|item: &mut HttpRequest| { + item.method = method.to_string(); + item.path = path.to_string(); + item.host = host.to_string(); + item.headers = build_headers(vec![ + (String::from(":path"), path.to_string()), + (String::from(":method"), method.to_string()), + (String::from(":authority"), host.to_string()), + ]); + })); - let check_response = response.unwrap().into_inner(); - assert!(check_response.status.is_some()); + let response = subject().check(request).await; + assert!(response.is_ok()); - let status = check_response.status.unwrap(); - assert_eq!(status.code, tonic::Code::Ok as i32); + let check_response = response.unwrap().into_inner(); + assert!(check_response.status.is_some()); + + let status = check_response.status.unwrap(); + assert_eq!(status.code, expected_status_code as i32); + } } } -- cgit v1.2.3 From e821b395783f2494f48ad941c606bec615e3b44e Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 17:44:34 -0600 Subject: refactor: extract method to convert http request to cedar context --- src/authorization/cedar_authorizer.rs | 26 ++++++++++++++++---------- tests/authorization/check_service_test.rs | 27 ++++++++++++++++++++------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 4eeaf645..e56640f9 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -111,12 +111,6 @@ impl CedarAuthorizer { &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { - let headers = &http_request.headers; - let bearer_token = headers - .get("authorization") - .and_then(|auth| auth.strip_prefix("Bearer ")) - .unwrap_or(""); - // Create principal entity let principal_id = EntityId::from_str("client")?; let principal_type = EntityTypeName::from_str("User")?; @@ -132,7 +126,22 @@ impl CedarAuthorizer { let resource_type = EntityTypeName::from_str("Resource")?; let resource = EntityUid::from_type_name_and_id(resource_type, resource_id); + let context = self.context_from(http_request); + CedarRequest::new(principal, action, resource, context?, None) + .map_err(|e| Box::new(e) as Box) + } + + fn context_from( + &self, + http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, + ) -> Result { let mut context_map = std::collections::HashMap::new(); + + let headers = &http_request.headers; + let bearer_token = headers + .get("authorization") + .and_then(|auth| auth.strip_prefix("Bearer ")) + .unwrap_or(""); if !bearer_token.is_empty() { context_map.insert( "bearer_token".to_string(), @@ -146,9 +155,6 @@ impl CedarAuthorizer { ); } - let context = Context::from_pairs(context_map.into_iter().collect::>())?; - - CedarRequest::new(principal, action, resource, context, None) - .map_err(|e| Box::new(e) as Box) + Context::from_pairs(context_map.into_iter().collect::>()) } } diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index 4ff7a89b..73812fa1 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -125,7 +125,6 @@ mod tests { #[tokio::test] async fn test_public_sparkle_endpoints() { - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/"}}, // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/application.js"}}, // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/callback"}}, // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/dashboard", Headers: loggedInHeaders}}, @@ -147,12 +146,26 @@ mod tests { // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "GET", Path: "/dashboard", Headers: invalidHeaders}}, // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "POST", Path: "/sparkles"}}, - let test_cases = vec![( - "GET", - "/", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - )]; + let test_cases = vec![ + ( + "GET", + "/", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/application.js", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/callback", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ]; for (method, path, host, expected_status_code) in test_cases { let request = tonic::Request::new(build_request(|item: &mut HttpRequest| { -- cgit v1.2.3 From c6dd31046b369e6ac44ee85f6206a4384f9dd148 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 18:13:28 -0600 Subject: refactor: extract method to parse principal --- src/authorization/cedar_authorizer.rs | 63 ++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index e56640f9..1780eddd 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -85,6 +85,20 @@ impl Authorizer for CedarAuthorizer { return true; } + if http_request.host == "sparkle.staging.runway.gitlab.net" + && http_request.method == "GET" + && http_request.path == "/application.js" + { + return true; + } + + if http_request.host == "sparkle.staging.runway.gitlab.net" + && http_request.method == "GET" + && http_request.path == "/callback" + { + return true; + } + match self.map_from(http_request.clone()) { Ok(cedar_request) => { let entities = Entities::empty(); @@ -111,10 +125,7 @@ impl CedarAuthorizer { &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { - // Create principal entity - let principal_id = EntityId::from_str("client")?; - let principal_type = EntityTypeName::from_str("User")?; - let principal = EntityUid::from_type_name_and_id(principal_type, principal_id); + let principal = self.principal_from(&http_request)?; // Create action entity let action_id = EntityId::from_str("check")?; @@ -131,30 +142,42 @@ impl CedarAuthorizer { .map_err(|e| Box::new(e) as Box) } + fn principal_from( + &self, + _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, + ) -> Result> { + let principal_id = EntityId::from_str("client")?; + let principal_type = EntityTypeName::from_str("User")?; + let principal = EntityUid::from_type_name_and_id(principal_type, principal_id); + Ok(principal) + } + fn context_from( &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result { - let mut context_map = std::collections::HashMap::new(); + let mut items = std::collections::HashMap::new(); + + items.insert("bearer_token".to_string(), self.token_from(&http_request)); + items.insert("path".to_string(), self.safe_string(&http_request.path)); - let headers = &http_request.headers; - let bearer_token = headers + Context::from_pairs(items.into_iter().collect::>()) + } + + 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(""); - if !bearer_token.is_empty() { - context_map.insert( - "bearer_token".to_string(), - cedar_policy::RestrictedExpression::new_string(bearer_token.to_string()), - ); - } - if !http_request.path.is_empty() { - context_map.insert( - "path".to_string(), - cedar_policy::RestrictedExpression::new_string(http_request.path.clone()), - ); - } - Context::from_pairs(context_map.into_iter().collect::>()) + self.safe_string(bearer_token) + } + + fn safe_string(&self, item: &str) -> cedar_policy::RestrictedExpression { + cedar_policy::RestrictedExpression::new_string(item.to_string()) } } -- cgit v1.2.3 From 7f045aced7b556f46911aafb0a23764577d84e82 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 18:15:44 -0600 Subject: refactor: extract method to parse permission --- src/authorization/cedar_authorizer.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 1780eddd..6f5b8e63 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -126,11 +126,7 @@ impl CedarAuthorizer { http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { let principal = self.principal_from(&http_request)?; - - // Create action entity - let action_id = EntityId::from_str("check")?; - let action_type = EntityTypeName::from_str("Action")?; - let action = EntityUid::from_type_name_and_id(action_type, action_id); + let permission = self.permission_from(&http_request)?; // Create resource entity let resource_id = EntityId::from_str("resource")?; @@ -138,7 +134,7 @@ impl CedarAuthorizer { let resource = EntityUid::from_type_name_and_id(resource_type, resource_id); let context = self.context_from(http_request); - CedarRequest::new(principal, action, resource, context?, None) + CedarRequest::new(principal, permission, resource, context?, None) .map_err(|e| Box::new(e) as Box) } @@ -152,6 +148,16 @@ impl CedarAuthorizer { Ok(principal) } + fn permission_from( + &self, + _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, + ) -> Result> { + let action_id = EntityId::from_str("check")?; + let action_type = EntityTypeName::from_str("Action")?; + let action = EntityUid::from_type_name_and_id(action_type, action_id); + Ok(action) + } + fn context_from( &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, -- cgit v1.2.3 From 0ba8f6c8ecaa366afbb90fcddbc58fcd395fd03d Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 18:22:27 -0600 Subject: refactor: inline variables --- src/authorization/cedar_authorizer.rs | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 6f5b8e63..f90e8d8b 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -127,13 +127,9 @@ impl CedarAuthorizer { ) -> Result> { let principal = self.principal_from(&http_request)?; let permission = self.permission_from(&http_request)?; - - // Create resource entity - let resource_id = EntityId::from_str("resource")?; - let resource_type = EntityTypeName::from_str("Resource")?; - let resource = EntityUid::from_type_name_and_id(resource_type, resource_id); - + let resource = self.resource_from(&http_request)?; let context = self.context_from(http_request); + CedarRequest::new(principal, permission, resource, context?, None) .map_err(|e| Box::new(e) as Box) } @@ -142,20 +138,30 @@ impl CedarAuthorizer { &self, _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { - let principal_id = EntityId::from_str("client")?; - let principal_type = EntityTypeName::from_str("User")?; - let principal = EntityUid::from_type_name_and_id(principal_type, principal_id); - Ok(principal) + Ok(EntityUid::from_type_name_and_id( + EntityTypeName::from_str("User")?, + EntityId::from_str("client")?, + )) } fn permission_from( &self, _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { - let action_id = EntityId::from_str("check")?; - let action_type = EntityTypeName::from_str("Action")?; - let action = EntityUid::from_type_name_and_id(action_type, action_id); - Ok(action) + Ok(EntityUid::from_type_name_and_id( + EntityTypeName::from_str("Action")?, + EntityId::from_str("check")?, + )) + } + + fn resource_from( + &self, + _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, + ) -> Result> { + Ok(EntityUid::from_type_name_and_id( + EntityTypeName::from_str("Resource")?, + EntityId::from_str("resource")?, + )) } fn context_from( -- cgit v1.2.3 From 6c6f1a7225022ae285bd6603aa0a2a81afc8baf3 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 18:39:27 -0600 Subject: refactor: move hard coded checks with cedar policy --- etc/authzd/policy0.cedar | 12 ++++++++++++ src/authorization/cedar_authorizer.rs | 28 +++++----------------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index 034e81b5..56457622 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -18,3 +18,15 @@ when { context.path like "*.html" ) }; + +permit(principal, action, resource) +when { + context has host && context has method && context has path && ( + context.host == "sparkle.staging.runway.gitlab.net" && + context.method == "GET" && ( + context.path == "/" || + context.path == "/app.js" || + context.path == "/callback" + ) + ) +}; diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index f90e8d8b..96a406d8 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -78,27 +78,6 @@ impl Authorizer for CedarAuthorizer { "Processing HTTP request" ); - if http_request.host == "sparkle.staging.runway.gitlab.net" - && http_request.method == "GET" - && http_request.path == "/" - { - return true; - } - - if http_request.host == "sparkle.staging.runway.gitlab.net" - && http_request.method == "GET" - && http_request.path == "/application.js" - { - return true; - } - - if http_request.host == "sparkle.staging.runway.gitlab.net" - && http_request.method == "GET" - && http_request.path == "/callback" - { - return true; - } - match self.map_from(http_request.clone()) { Ok(cedar_request) => { let entities = Entities::empty(); @@ -109,6 +88,7 @@ impl Authorizer for CedarAuthorizer { matches!(response.decision(), cedar_policy::Decision::Allow) } Err(e) => { + println!("error: {}", e); tracing::error!( error = %e, path = %http_request.path, @@ -128,9 +108,9 @@ impl CedarAuthorizer { 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); + let context = self.context_from(http_request)?; - CedarRequest::new(principal, permission, resource, context?, None) + CedarRequest::new(principal, permission, resource, context, None) .map_err(|e| Box::new(e) as Box) } @@ -171,6 +151,8 @@ impl CedarAuthorizer { 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)); Context::from_pairs(items.into_iter().collect::>()) -- cgit v1.2.3 From a45c159dac5893c7214e18a59c8a6d5115472e44 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 4 Jul 2025 18:47:33 -0600 Subject: test: add missing public asset tests --- etc/authzd/policy0.cedar | 21 ++++++- tests/authorization/check_service_test.rs | 101 +++++++++++++++++++++++++----- 2 files changed, 103 insertions(+), 19 deletions(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index 56457622..75cf8178 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -22,11 +22,28 @@ when { permit(principal, action, resource) when { context has host && context has method && context has path && ( - context.host == "sparkle.staging.runway.gitlab.net" && + context.host == "sparkle.staging.runway.gitlab.net" && ( context.method == "GET" && ( context.path == "/" || - context.path == "/app.js" || + context.path == "/callback" || + context.path == "/dashboard/nav" || + context.path == "/health" || + context.path == "/signout" || + context.path == "/sparkles" || + context.path like "*.bmp" || + context.path like "*.css" || + context.path like "*.gif" || + context.path like "*.html" || + context.path like "*.ico" || + context.path like "*.jpeg" || + context.path like "*.jpg" || + context.path like "*.js" || + context.path like "*.png" || context.path == "/callback" ) + ) || ( + context.method == "POST" && ( + context.path == "/sparkles/restore" + ) ) }; diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index 73812fa1..5ea0cb95 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -125,26 +125,9 @@ mod tests { #[tokio::test] async fn test_public_sparkle_endpoints() { - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/application.js"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/callback"}}, // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/dashboard", Headers: loggedInHeaders}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/dashboard/nav"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/favicon.ico"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/favicon.png"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/favicon.png"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/health"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/htmx.js"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/index.html"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/logo.png"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/pico.min.css"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/signout"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/sparkles"}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "GET", Path: "/vue.global.js"}}, // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "POST", Path: "/sparkles", Headers: loggedInHeaders}}, - // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "POST", Path: "/sparkles/restore"}}, - // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "GET", Path: "/dashboard"}}, // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "GET", Path: "/dashboard", Headers: invalidHeaders}}, - // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "POST", Path: "/sparkles"}}, let test_cases = vec![ ( @@ -165,6 +148,90 @@ mod tests { "sparkle.staging.runway.gitlab.net", tonic::Code::Ok, ), + ( + "GET", + "/dashboard/nav", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/favicon.ico", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/favicon.png", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/health", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/htmx.js", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/index.html", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/logo.png", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/pico.min.css", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/signout", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/sparkles", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/vue.global.js", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "POST", + "/sparkles/restore", + "sparkle.staging.runway.gitlab.net", + tonic::Code::Ok, + ), + ( + "GET", + "/dashboard", + "sparkle.staging.runway.gitlab.net", + tonic::Code::PermissionDenied, + ), + ( + "POST", + "/sparkles", + "sparkle.staging.runway.gitlab.net", + tonic::Code::PermissionDenied, + ), ]; for (method, path, host, expected_status_code) in test_cases { -- cgit v1.2.3 From fc4bbd8efd805411239406c6323a37537d4534f2 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 11:29:37 -0600 Subject: fix: fix typo in cedar policy file --- etc/authzd/policy0.cedar | 1 + src/authorization/cedar_authorizer.rs | 110 +++++++++++++-------------- tests/authorization/cedar_authorizer_test.rs | 18 +++-- tests/authorization/check_service_test.rs | 4 +- 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index 75cf8178..e1037457 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -44,6 +44,7 @@ when { ) || ( context.method == "POST" && ( context.path == "/sparkles/restore" + ) ) ) }; diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 96a406d8..9fb7513a 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -49,58 +49,7 @@ impl CedarAuthorizer { Ok(policies) } -} - -impl Default for CedarAuthorizer { - fn default() -> Self { - Self::new_from(std::path::Path::new("/etc/authzd")) - } -} - -impl Authorizer for CedarAuthorizer { - fn authorize(&self, request: 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, - }; - - tracing::info!( - method = %http_request.method, - host = %http_request.host, - path = %http_request.path, - scheme = %http_request.scheme, - protocol = %http_request.protocol, - "Processing HTTP request" - ); - match self.map_from(http_request.clone()) { - Ok(cedar_request) => { - let entities = Entities::empty(); - let response = - self.authorizer - .is_authorized(&cedar_request, &self.policies, &entities); - - matches!(response.decision(), cedar_policy::Decision::Allow) - } - Err(e) => { - println!("error: {}", e); - tracing::error!( - error = %e, - path = %http_request.path, - "Failed to create Cedar request" - ); - false - } - } - } -} - -impl CedarAuthorizer { fn map_from( &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, @@ -110,8 +59,9 @@ impl CedarAuthorizer { let resource = self.resource_from(&http_request)?; let context = self.context_from(http_request)?; - CedarRequest::new(principal, permission, resource, context, None) - .map_err(|e| Box::new(e) as Box) + Ok(CedarRequest::new( + principal, permission, resource, context, None, + )?) } fn principal_from( @@ -147,7 +97,7 @@ impl CedarAuthorizer { fn context_from( &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, - ) -> Result { + ) -> Result> { let mut items = std::collections::HashMap::new(); items.insert("bearer_token".to_string(), self.token_from(&http_request)); @@ -155,7 +105,7 @@ impl CedarAuthorizer { items.insert("method".to_string(), self.safe_string(&http_request.method)); items.insert("path".to_string(), self.safe_string(&http_request.path)); - Context::from_pairs(items.into_iter().collect::>()) + Ok(Context::from_pairs(items.into_iter().collect::>())?) } fn token_from( @@ -175,3 +125,53 @@ impl CedarAuthorizer { cedar_policy::RestrictedExpression::new_string(item.to_string()) } } + +impl Default for CedarAuthorizer { + fn default() -> Self { + Self::new_from(std::path::Path::new("/etc/authzd")) + } +} + +impl Authorizer for CedarAuthorizer { + fn authorize(&self, request: 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, + }; + + tracing::info!( + method = %http_request.method, + host = %http_request.host, + path = %http_request.path, + scheme = %http_request.scheme, + protocol = %http_request.protocol, + "Processing HTTP request" + ); + + let entities = Entities::empty(); + + match self.map_from(http_request.clone()) { + Ok(cedar_request) => { + let response = + self.authorizer + .is_authorized(&cedar_request, &self.policies, &entities); + + matches!(response.decision(), cedar_policy::Decision::Allow) + } + Err(e) => { + println!("error: {}", e); + tracing::error!( + error = %e, + path = %http_request.path, + "Failed to create Cedar request" + ); + false + } + } + } +} diff --git a/tests/authorization/cedar_authorizer_test.rs b/tests/authorization/cedar_authorizer_test.rs index 317ef67f..ccf8a1f8 100644 --- a/tests/authorization/cedar_authorizer_test.rs +++ b/tests/authorization/cedar_authorizer_test.rs @@ -5,16 +5,18 @@ mod tests { use envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest; use std::collections::HashMap; + fn subject() -> authzd::CedarAuthorizer { + build_cedar_authorizer() + } + #[test] fn test_cedar_authorizer_allows_valid_token() { - let request = build_request(|item: &mut HttpRequest| { + assert!(subject().authorize(build_request(|item: &mut HttpRequest| { item.headers = build_headers(vec![( "authorization".to_string(), "Bearer valid-token".to_string(), )]); - }); - - assert!(build_cedar_authorizer().authorize(request)); + }))); } #[test] @@ -26,7 +28,7 @@ mod tests { )]); }); - assert!(!build_cedar_authorizer().authorize(request)); + assert!(!subject().authorize(request)); } #[test] @@ -35,7 +37,7 @@ mod tests { item.headers = HashMap::new(); }); - assert!(!build_cedar_authorizer().authorize(request)); + assert!(!subject().authorize(request)); } #[test] @@ -55,7 +57,7 @@ mod tests { ]); }); - assert!(build_cedar_authorizer().authorize(request)); + assert!(subject().authorize(request)); } #[test] @@ -75,6 +77,6 @@ mod tests { ]); }); - assert!(build_cedar_authorizer().authorize(request)); + assert!(subject().authorize(request)); } } diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index 5ea0cb95..a32f2a2c 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -224,13 +224,13 @@ mod tests { "GET", "/dashboard", "sparkle.staging.runway.gitlab.net", - tonic::Code::PermissionDenied, + tonic::Code::Unauthenticated, ), ( "POST", "/sparkles", "sparkle.staging.runway.gitlab.net", - tonic::Code::PermissionDenied, + tonic::Code::Unauthenticated, ), ]; -- cgit v1.2.3 From 2dd12b6a8109f05f508f382604f49744158d2080 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 11:32:15 -0600 Subject: test: invalid request variables in tests --- tests/authorization/cedar_authorizer_test.rs | 38 +++++++++++++--------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/tests/authorization/cedar_authorizer_test.rs b/tests/authorization/cedar_authorizer_test.rs index ccf8a1f8..490a0107 100644 --- a/tests/authorization/cedar_authorizer_test.rs +++ b/tests/authorization/cedar_authorizer_test.rs @@ -21,28 +21,28 @@ mod tests { #[test] fn test_cedar_authorizer_denies_invalid_token() { - let request = build_request(|item: &mut HttpRequest| { - item.headers = build_headers(vec![( - "authorization".to_string(), - "Bearer invalid-token".to_string(), - )]); - }); - - assert!(!subject().authorize(request)); + assert!( + !subject().authorize(build_request(|item: &mut HttpRequest| { + item.headers = build_headers(vec![( + "authorization".to_string(), + "Bearer invalid-token".to_string(), + )]); + })) + ); } #[test] fn test_cedar_authorizer_denies_missing_header() { - let request = build_request(|item: &mut HttpRequest| { - item.headers = HashMap::new(); - }); - - assert!(!subject().authorize(request)); + assert!( + !subject().authorize(build_request(|item: &mut HttpRequest| { + item.headers = HashMap::new(); + })) + ); } #[test] fn test_cedar_authorizer_allows_static_assets() { - let request = build_request(|item: &mut HttpRequest| { + assert!(subject().authorize(build_request(|item: &mut HttpRequest| { let method = String::from("GET"); let host = String::from("sparkle.staging.runway.gitlab.net"); let path = "/public/style.css"; @@ -55,14 +55,12 @@ mod tests { (String::from(":method"), method), (String::from(":authority"), host), ]); - }); - - assert!(subject().authorize(request)); + }))); } #[test] fn test_cedar_authorizer_allows_js_assets() { - let request = build_request(|item: &mut HttpRequest| { + assert!(subject().authorize(build_request(|item: &mut HttpRequest| { let method = String::from("GET"); let host = String::from("sparkle.staging.runway.gitlab.net"); let path = "/app.js"; @@ -75,8 +73,6 @@ mod tests { (String::from(":method"), method), (String::from(":authority"), host), ]); - }); - - assert!(subject().authorize(request)); + }))); } } -- cgit v1.2.3 From 3d821c356af75cdddddf72d8dc9d877972ee8d20 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 11:36:43 -0600 Subject: refactor: remove duplication from cedar policy --- etc/authzd/policy0.cedar | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index e1037457..a7a0ccb5 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -6,7 +6,7 @@ when { permit(principal, action == Action::"check", resource) when { - context has path && ( + context has path && context has method && context.method == "GET" && ( context.path like "*.css" || context.path like "*.js" || context.path like "*.ico" || @@ -30,15 +30,6 @@ when { context.path == "/health" || context.path == "/signout" || context.path == "/sparkles" || - context.path like "*.bmp" || - context.path like "*.css" || - context.path like "*.gif" || - context.path like "*.html" || - context.path like "*.ico" || - context.path like "*.jpeg" || - context.path like "*.jpg" || - context.path like "*.js" || - context.path like "*.png" || context.path == "/callback" ) ) || ( -- cgit v1.2.3 From 43ea56f31f1f00b5f6dfb84682ef40b716a327a4 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 11:42:26 -0600 Subject: test: refactor tests to provide multiple sparkle hosts --- tests/authorization/check_service_test.rs | 166 ++++++++---------------------- 1 file changed, 44 insertions(+), 122 deletions(-) diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index a32f2a2c..f6546802 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -129,131 +129,53 @@ mod tests { // {status: tonic::Code::Ok, http: &HTTPRequest{Method: "POST", Path: "/sparkles", Headers: loggedInHeaders}}, // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "GET", Path: "/dashboard", Headers: invalidHeaders}}, - let test_cases = vec![ - ( - "GET", - "/", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/application.js", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/callback", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/dashboard/nav", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/favicon.ico", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/favicon.png", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/health", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/htmx.js", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/index.html", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/logo.png", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/pico.min.css", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/signout", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/sparkles", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/vue.global.js", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "POST", - "/sparkles/restore", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Ok, - ), - ( - "GET", - "/dashboard", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Unauthenticated, - ), - ( - "POST", - "/sparkles", - "sparkle.staging.runway.gitlab.net", - tonic::Code::Unauthenticated, - ), + let hosts = vec![ + "sparkle.staging.runway.gitlab.net", + // "sparkle.runway.gitlab.net", ]; - for (method, path, host, expected_status_code) in test_cases { - let request = tonic::Request::new(build_request(|item: &mut HttpRequest| { - item.method = method.to_string(); - item.path = path.to_string(); - item.host = host.to_string(); - item.headers = build_headers(vec![ - (String::from(":path"), path.to_string()), - (String::from(":method"), method.to_string()), - (String::from(":authority"), host.to_string()), - ]); - })); - - let response = subject().check(request).await; - assert!(response.is_ok()); - - let check_response = response.unwrap().into_inner(); - assert!(check_response.status.is_some()); + let routes = vec![ + ("GET", "/", tonic::Code::Ok), + ("GET", "/application.js", tonic::Code::Ok), + ("GET", "/callback", tonic::Code::Ok), + ("GET", "/dashboard/nav", tonic::Code::Ok), + ("GET", "/favicon.ico", tonic::Code::Ok), + ("GET", "/favicon.png", tonic::Code::Ok), + ("GET", "/health", tonic::Code::Ok), + ("GET", "/htmx.js", tonic::Code::Ok), + ("GET", "/index.html", tonic::Code::Ok), + ("GET", "/logo.png", tonic::Code::Ok), + ("GET", "/pico.min.css", tonic::Code::Ok), + ("GET", "/signout", tonic::Code::Ok), + ("GET", "/sparkles", tonic::Code::Ok), + ("GET", "/vue.global.js", tonic::Code::Ok), + ("POST", "/sparkles/restore", tonic::Code::Ok), + ("GET", "/dashboard", tonic::Code::Unauthenticated), + ("POST", "/sparkles", tonic::Code::Unauthenticated), + ]; - let status = check_response.status.unwrap(); - assert_eq!(status.code, expected_status_code as i32); + for host in hosts { + for (method, path, expected_status_code) in &routes { + let request = tonic::Request::new(build_request(|item: &mut HttpRequest| { + item.method = method.to_string(); + item.path = path.to_string(); + item.host = host.to_string(); + item.headers = build_headers(vec![ + (String::from(":path"), path.to_string()), + (String::from(":method"), method.to_string()), + (String::from(":authority"), host.to_string()), + ]); + })); + + let response = subject().check(request).await; + assert!(response.is_ok()); + + let check_response = response.unwrap().into_inner(); + assert!(check_response.status.is_some()); + + let status = check_response.status.unwrap(); + assert_eq!(tonic::Code::from_i32(status.code), *expected_status_code); + } } } } -- cgit v1.2.3 From 3dbd58536a4c37a2cc3b18572ac9e46bbd19d718 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 11:45:17 -0600 Subject: feat: allow access from production sparkle --- etc/authzd/policy0.cedar | 31 ++++++++++++++++++------------- tests/authorization/check_service_test.rs | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index a7a0ccb5..18a48476 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -22,19 +22,24 @@ when { permit(principal, action, resource) when { context has host && context has method && context has path && ( - context.host == "sparkle.staging.runway.gitlab.net" && ( - context.method == "GET" && ( - context.path == "/" || - context.path == "/callback" || - context.path == "/dashboard/nav" || - context.path == "/health" || - context.path == "/signout" || - context.path == "/sparkles" || - context.path == "/callback" - ) - ) || ( - context.method == "POST" && ( - context.path == "/sparkles/restore" + ( + context.host == "sparkle.staging.runway.gitlab.net" || + context.host == "sparkle.runway.gitlab.net" + ) && ( + ( + context.method == "GET" && ( + context.path == "/" || + context.path == "/callback" || + context.path == "/dashboard/nav" || + context.path == "/health" || + context.path == "/signout" || + context.path == "/sparkles" || + context.path == "/callback" + ) + ) || ( + context.method == "POST" && ( + context.path == "/sparkles/restore" + ) ) ) ) diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index f6546802..fc1ab75a 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -131,7 +131,7 @@ mod tests { let hosts = vec![ "sparkle.staging.runway.gitlab.net", - // "sparkle.runway.gitlab.net", + "sparkle.runway.gitlab.net", ]; let routes = vec![ -- cgit v1.2.3 From aa5ad67a7d3cc154fa65d291999f3b0e1c4b3f94 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 11:54:38 -0600 Subject: refactor: remove action check in policy --- etc/authzd/policy0.cedar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index 18a48476..12950df5 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -4,7 +4,7 @@ when { context.bearer_token == "valid-token" }; -permit(principal, action == Action::"check", resource) +permit(principal, action, resource) when { context has path && context has method && context.method == "GET" && ( context.path like "*.css" || -- cgit v1.2.3 From 2c46c12427c6ae44e6ca96e6cef7522e4435482d Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 11:58:02 -0600 Subject: chore: log the decision and diagnostics --- src/authorization/cedar_authorizer.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 9fb7513a..db54aaed 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -10,13 +10,16 @@ use std::str::FromStr; #[derive(Debug)] pub struct CedarAuthorizer { policies: PolicySet, + entities: cedar_policy::Entities, authorizer: CedarAuth, } impl CedarAuthorizer { pub fn new(policies: cedar_policy::PolicySet) -> CedarAuthorizer { + let entities = Entities::empty(); CedarAuthorizer { policies, + entities, authorizer: CedarAuth::new(), } } @@ -31,7 +34,6 @@ impl CedarAuthorizer { } let mut policies = PolicySet::new(); - for entry in fs::read_dir(path)? { let file_path = entry?.path(); @@ -144,24 +146,26 @@ impl Authorizer for CedarAuthorizer { None => return false, }; - tracing::info!( - method = %http_request.method, - host = %http_request.host, - path = %http_request.path, - scheme = %http_request.scheme, - protocol = %http_request.protocol, - "Processing HTTP request" - ); - - let entities = Entities::empty(); - match self.map_from(http_request.clone()) { Ok(cedar_request) => { let response = self.authorizer - .is_authorized(&cedar_request, &self.policies, &entities); + .is_authorized(&cedar_request, &self.policies, &self.entities); + + let decision = response.decision(); + + tracing::info!( + method = %http_request.method, + host = %http_request.host, + path = %http_request.path, + scheme = %http_request.scheme, + protocol = %http_request.protocol, + decision = ?decision, + diagnostics = ?response.diagnostics(), + "Processing HTTP request" + ); - matches!(response.decision(), cedar_policy::Decision::Allow) + matches!(decision, cedar_policy::Decision::Allow) } Err(e) => { println!("error: {}", e); -- cgit v1.2.3 From 836e6658fabdab957ab2ce7be973a5de31247750 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 12:12:56 -0600 Subject: refactor: provide cedar entities in constructor --- src/authorization/cedar_authorizer.rs | 19 ++++++++++++------- tests/support/factory_bot.rs | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index db54aaed..4b697680 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -9,14 +9,16 @@ use std::str::FromStr; #[derive(Debug)] pub struct CedarAuthorizer { - policies: PolicySet, - entities: cedar_policy::Entities, authorizer: CedarAuth, + entities: cedar_policy::Entities, + policies: PolicySet, } impl CedarAuthorizer { - pub fn new(policies: cedar_policy::PolicySet) -> CedarAuthorizer { - let entities = Entities::empty(); + pub fn new( + policies: cedar_policy::PolicySet, + entities: cedar_policy::Entities, + ) -> CedarAuthorizer { CedarAuthorizer { policies, entities, @@ -24,8 +26,11 @@ impl CedarAuthorizer { } } - pub fn new_from(path: &std::path::Path) -> CedarAuthorizer { - Self::new(Self::load_from(path).unwrap_or_else(|_| PolicySet::default())) + pub fn new_from(path: &std::path::Path, entities: cedar_policy::Entities) -> CedarAuthorizer { + Self::new( + Self::load_from(path).unwrap_or_else(|_| PolicySet::default()), + entities, + ) } fn load_from(path: &std::path::Path) -> Result> { @@ -130,7 +135,7 @@ impl CedarAuthorizer { impl Default for CedarAuthorizer { fn default() -> Self { - Self::new_from(std::path::Path::new("/etc/authzd")) + Self::new_from(std::path::Path::new("/etc/authzd"), Entities::empty()) } } diff --git a/tests/support/factory_bot.rs b/tests/support/factory_bot.rs index 15c6f1f3..051b248c 100644 --- a/tests/support/factory_bot.rs +++ b/tests/support/factory_bot.rs @@ -39,7 +39,7 @@ pub fn build_headers(headers: Vec<(String, String)>) -> HashMap pub fn build_cedar_authorizer() -> authzd::CedarAuthorizer { let realpath = std::fs::canonicalize("./etc/authzd").unwrap(); let path = realpath.as_path(); - authzd::CedarAuthorizer::new_from(path) + authzd::CedarAuthorizer::new_from(path, cedar_policy::Entities::empty()) } pub async fn build_channel(addr: SocketAddr) -> Channel { -- cgit v1.2.3 From a9be59c733e63b57bf872bdc82495a6d93308577 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 12:16:04 -0600 Subject: refactor: remove cedar aliases --- src/authorization/cedar_authorizer.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 4b697680..5fe0dd64 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -1,17 +1,13 @@ use super::authorizer::Authorizer; -use cedar_policy::{ - Authorizer as CedarAuth, Context, Entities, EntityId, EntityTypeName, EntityUid, PolicySet, - Request as CedarRequest, -}; -use envoy_types::ext_authz::v3::pb::CheckRequest; +use cedar_policy::{Context, Entities, EntityId, EntityTypeName, EntityUid}; use std::fs; use std::str::FromStr; #[derive(Debug)] pub struct CedarAuthorizer { - authorizer: CedarAuth, + authorizer: cedar_policy::Authorizer, entities: cedar_policy::Entities, - policies: PolicySet, + policies: cedar_policy::PolicySet, } impl CedarAuthorizer { @@ -22,30 +18,32 @@ impl CedarAuthorizer { CedarAuthorizer { policies, entities, - authorizer: CedarAuth::new(), + 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(|_| PolicySet::default()), + Self::load_from(path).unwrap_or_else(|_| cedar_policy::PolicySet::default()), entities, ) } - fn load_from(path: &std::path::Path) -> Result> { + fn load_from( + path: &std::path::Path, + ) -> Result> { if !path.exists() || !path.is_dir() { - return Ok(PolicySet::default()); + return Ok(cedar_policy::PolicySet::default()); } - let mut policies = PolicySet::new(); + 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 = PolicySet::from_str(&content)?; + let file_policies = cedar_policy::PolicySet::from_str(&content)?; for policy in file_policies.policies() { policies.add(policy.clone())?; @@ -60,13 +58,13 @@ impl CedarAuthorizer { fn map_from( &self, http_request: envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, - ) -> Result> { + ) -> Result> { 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(CedarRequest::new( + Ok(cedar_policy::Request::new( principal, permission, resource, context, None, )?) } @@ -140,7 +138,7 @@ impl Default for CedarAuthorizer { } impl Authorizer for CedarAuthorizer { - fn authorize(&self, request: CheckRequest) -> bool { + fn authorize(&self, request: envoy_types::ext_authz::v3::pb::CheckRequest) -> bool { let http_request = match request .attributes .as_ref() -- cgit v1.2.3 From 3b6b2b3029e0b9ba185028db0eb77a3d46998a5c Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 12:18:58 -0600 Subject: refactor: inline cedar policy namespace --- src/authorization/cedar_authorizer.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 5fe0dd64..6b901e5d 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -1,5 +1,4 @@ use super::authorizer::Authorizer; -use cedar_policy::{Context, Entities, EntityId, EntityTypeName, EntityUid}; use std::fs; use std::str::FromStr; @@ -73,9 +72,9 @@ impl CedarAuthorizer { &self, _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { - Ok(EntityUid::from_type_name_and_id( - EntityTypeName::from_str("User")?, - EntityId::from_str("client")?, + Ok(cedar_policy::EntityUid::from_type_name_and_id( + cedar_policy::EntityTypeName::from_str("User")?, + cedar_policy::EntityId::from_str("client")?, )) } @@ -83,9 +82,9 @@ impl CedarAuthorizer { &self, _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { - Ok(EntityUid::from_type_name_and_id( - EntityTypeName::from_str("Action")?, - EntityId::from_str("check")?, + Ok(cedar_policy::EntityUid::from_type_name_and_id( + cedar_policy::EntityTypeName::from_str("Action")?, + cedar_policy::EntityId::from_str("check")?, )) } @@ -93,9 +92,9 @@ impl CedarAuthorizer { &self, _http_request: &envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest, ) -> Result> { - Ok(EntityUid::from_type_name_and_id( - EntityTypeName::from_str("Resource")?, - EntityId::from_str("resource")?, + Ok(cedar_policy::EntityUid::from_type_name_and_id( + cedar_policy::EntityTypeName::from_str("Resource")?, + cedar_policy::EntityId::from_str("resource")?, )) } @@ -110,7 +109,9 @@ impl CedarAuthorizer { items.insert("method".to_string(), self.safe_string(&http_request.method)); items.insert("path".to_string(), self.safe_string(&http_request.path)); - Ok(Context::from_pairs(items.into_iter().collect::>())?) + Ok(cedar_policy::Context::from_pairs( + items.into_iter().collect::>(), + )?) } fn token_from( @@ -133,7 +134,10 @@ impl CedarAuthorizer { impl Default for CedarAuthorizer { fn default() -> Self { - Self::new_from(std::path::Path::new("/etc/authzd"), Entities::empty()) + Self::new_from( + std::path::Path::new("/etc/authzd"), + cedar_policy::Entities::empty(), + ) } } -- cgit v1.2.3 From 7a23f5256b861705b69405c690eead5b30df7775 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 12:30:04 -0600 Subject: feat: allow requests from localhost --- etc/authzd/policy0.cedar | 3 ++- src/authorization/server.rs | 6 +++--- tests/authorization/check_service_test.rs | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index 12950df5..bc67afc3 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -23,8 +23,9 @@ permit(principal, action, resource) when { context has host && context has method && context has path && ( ( + context.host == "sparkle.runway.gitlab.net" || context.host == "sparkle.staging.runway.gitlab.net" || - context.host == "sparkle.runway.gitlab.net" + context.host like "localhost:*" ) && ( ( context.method == "GET" && ( diff --git a/src/authorization/server.rs b/src/authorization/server.rs index 23b7720e..feb89d52 100644 --- a/src/authorization/server.rs +++ b/src/authorization/server.rs @@ -40,9 +40,9 @@ impl Server { tracing::info!( method = %req.method(), path = %req.uri().path(), - content_type = ?req.headers().get("content-type").and_then(|v| v.to_str().ok()), - user_agent = ?req.headers().get("user-agent").and_then(|v| v.to_str().ok()), - x_request_id = ?req.headers().get("x-request-id").and_then(|v| v.to_str().ok()), + content_type = req.headers().get("content-type").map_or("unknown", |v| v.to_str().unwrap_or("unknown")), + user_agent = req.headers().get("user-agent").map_or("unknown", |v| v.to_str().unwrap_or("unknown")), + x_request_id = req.headers().get("x-request-id").map_or("none", |v| v.to_str().unwrap_or("none")), "gRPC request" ); diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index fc1ab75a..b50d3689 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -130,8 +130,9 @@ mod tests { // {status: tonic::Code::PermissionDenied, http: &HTTPRequest{Method: "GET", Path: "/dashboard", Headers: invalidHeaders}}, let hosts = vec![ - "sparkle.staging.runway.gitlab.net", + "localhost:10000", "sparkle.runway.gitlab.net", + "sparkle.staging.runway.gitlab.net", ]; let routes = vec![ -- cgit v1.2.3 From c23770fe752b7cdd92de4af5dd5b65f57da80709 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 12:36:21 -0600 Subject: chore: remove unhelpful logging --- src/authorization/check_service.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/authorization/check_service.rs b/src/authorization/check_service.rs index 57f7b5d5..f8c7577f 100644 --- a/src/authorization/check_service.rs +++ b/src/authorization/check_service.rs @@ -23,10 +23,8 @@ impl envoy_types::ext_authz::v3::pb::Authorization for CheckService { request: Request, ) -> Result, Status> { if self.authorizer.authorize(request.into_inner()) { - log::info!("OK"); Ok(Response::new(CheckResponse::with_status(Status::ok("OK")))) } else { - log::info!("Unauthorized"); Ok(Response::new(CheckResponse::with_status( Status::unauthenticated("Unauthorized"), ))) -- cgit v1.2.3 From 2a56b8fa13aef71493959ca9e50b48d806082f33 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 12:49:18 -0600 Subject: refactor: pass the PaC autorizer to the server to allow trying different ones --- src/authorization/authorizer.rs | 2 +- src/authorization/server.rs | 6 +++--- src/main.rs | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/authorization/authorizer.rs b/src/authorization/authorizer.rs index 14a7df27..62733585 100644 --- a/src/authorization/authorizer.rs +++ b/src/authorization/authorizer.rs @@ -1,5 +1,5 @@ use envoy_types::ext_authz::v3::pb::CheckRequest; -pub trait Authorizer: std::fmt::Debug { +pub trait Authorizer: std::fmt::Debug + std::marker::Sync + std::marker::Send + 'static { fn authorize(&self, request: CheckRequest) -> bool; } diff --git a/src/authorization/server.rs b/src/authorization/server.rs index feb89d52..759a550d 100644 --- a/src/authorization/server.rs +++ b/src/authorization/server.rs @@ -8,13 +8,13 @@ pub struct Server { } impl Server { - pub fn new() -> Result> { + pub fn new(authorizer: T) -> Result> { let (health_reporter, health_service) = tonic_health::server::health_reporter(); std::mem::drop( health_reporter.set_service_status("", tonic_health::ServingStatus::Serving), ); let authorization_service = - AuthorizationServer::new(CheckService::new(Arc::new(CedarAuthorizer::default()))); + AuthorizationServer::new(CheckService::new(Arc::new(authorizer))); let reflection_service = tonic_reflection::server::Builder::configure() .register_encoded_file_descriptor_set(tonic_health::pb::FILE_DESCRIPTOR_SET) @@ -64,6 +64,6 @@ impl Server { impl Default for Server { fn default() -> Self { - Self::new().unwrap() + Self::new(CedarAuthorizer::default()).unwrap() } } diff --git a/src/main.rs b/src/main.rs index 511d3d04..add0d88d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,8 @@ async fn main() -> Result<(), Box> { .parse()?; tracing::info!(address = %addr, "Starting authorization server"); - let server = authzd::authorization::Server::new()?; + let cedar = authzd::authorization::CedarAuthorizer::default(); + let server = authzd::authorization::Server::new(cedar)?; server.serve(addr).await?; Ok(()) -- cgit v1.2.3 From 172ccab744de1fcb10e8b1dbf71f706866175b0f Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 12:55:05 -0600 Subject: refactor: remove duplicate path in cedar policy --- etc/authzd/policy0.cedar | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index bc67afc3..e67f0db5 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -34,8 +34,7 @@ when { context.path == "/dashboard/nav" || context.path == "/health" || context.path == "/signout" || - context.path == "/sparkles" || - context.path == "/callback" + context.path == "/sparkles" ) ) || ( context.method == "POST" && ( -- cgit v1.2.3 From f399f108259602d4337167ab58876504a00f83a6 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 13:05:24 -0600 Subject: chore: use cedar policy cli to format and lint cedar policies --- Makefile | 4 +++ etc/authzd/policy0.cedar | 80 +++++++++++++++++++++++------------------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index 6eb1ec31..701b2422 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ setup: mise install mise exec go -- go install github.com/xlgmokha/minit@latest mise exec rust -- rustup component add clippy rustfmt + mise exec rust -- cargo install --locked cedar-policy-cli # Cargo targets build: @@ -29,9 +30,12 @@ clean: fmt: @cargo fmt + @cedar format --policies etc/authzd/policy0.cedar --write lint: @cargo clippy + @cedar check-parse --policies etc/authzd/policy0.cedar + @cedar format --policies etc/authzd/policy0.cedar --check doc: @cargo doc --open diff --git a/etc/authzd/policy0.cedar b/etc/authzd/policy0.cedar index e67f0db5..9410eced 100644 --- a/etc/authzd/policy0.cedar +++ b/etc/authzd/policy0.cedar @@ -1,46 +1,42 @@ -permit(principal, action == Action::"check", resource) -when { - context has bearer_token && - context.bearer_token == "valid-token" -}; +permit ( + principal, + action == Action::"check", + resource +) +when { context has bearer_token && context.bearer_token == "valid-token" }; -permit(principal, action, resource) -when { - context has path && context has method && context.method == "GET" && ( - context.path like "*.css" || - context.path like "*.js" || - context.path like "*.ico" || - context.path like "*.png" || - context.path like "*.jpg" || - context.path like "*.jpeg" || - context.path like "*.gif" || - context.path like "*.bmp" || - context.path like "*.html" - ) +permit (principal, action, resource) +when +{ + context has path && + context has method && + context.method == "GET" && + (context.path like "*.css" || + context.path like "*.js" || + context.path like "*.ico" || + context.path like "*.png" || + context.path like "*.jpg" || + context.path like "*.jpeg" || + context.path like "*.gif" || + context.path like "*.bmp" || + context.path like "*.html") }; -permit(principal, action, resource) -when { - context has host && context has method && context has path && ( - ( - context.host == "sparkle.runway.gitlab.net" || - context.host == "sparkle.staging.runway.gitlab.net" || - context.host like "localhost:*" - ) && ( - ( - context.method == "GET" && ( - context.path == "/" || - context.path == "/callback" || - context.path == "/dashboard/nav" || - context.path == "/health" || - context.path == "/signout" || - context.path == "/sparkles" - ) - ) || ( - context.method == "POST" && ( - context.path == "/sparkles/restore" - ) - ) - ) - ) +permit (principal, action, resource) +when +{ + context has host && + context has method && + context has path && + ((context.host == "sparkle.runway.gitlab.net" || + context.host == "sparkle.staging.runway.gitlab.net" || + context.host like "localhost:*") && + ((context.method == "GET" && + (context.path == "/" || + context.path == "/callback" || + context.path == "/dashboard/nav" || + context.path == "/health" || + context.path == "/signout" || + context.path == "/sparkles")) || + (context.method == "POST" && (context.path == "/sparkles/restore")))) }; -- cgit v1.2.3 From aa13cc129c316054a5d5b58c8df0df8216ed9cfc Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 13:16:02 -0600 Subject: chore: apply clippy suggestions --- tests/support/factory_bot.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/support/factory_bot.rs b/tests/support/factory_bot.rs index 051b248c..007f0cb7 100644 --- a/tests/support/factory_bot.rs +++ b/tests/support/factory_bot.rs @@ -7,7 +7,7 @@ use tonic::transport::Channel; #[allow(dead_code)] pub fn build() -> T { - return please::build(); + please::build() } pub fn build_with(initializer: F) -> T @@ -15,7 +15,7 @@ where T: Default, F: std::ops::FnOnce(&mut T), { - return please::build_with(initializer); + please::build_with(initializer) } pub fn build_request(f: impl std::ops::FnOnce(&mut HttpRequest)) -> CheckRequest { @@ -29,11 +29,11 @@ pub fn build_request(f: impl std::ops::FnOnce(&mut HttpRequest)) -> CheckRequest } pub fn build_headers(headers: Vec<(String, String)>) -> HashMap { - return build_with(|item: &mut HashMap| { + build_with(|item: &mut HashMap| { for (key, value) in headers { item.insert(key, value); } - }); + }) } pub fn build_cedar_authorizer() -> authzd::CedarAuthorizer { -- cgit v1.2.3 From a0594f92033f2e9a09ba69261421684b9bf57185 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 13:16:23 -0600 Subject: chore: remove println! --- src/authorization/cedar_authorizer.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/authorization/cedar_authorizer.rs b/src/authorization/cedar_authorizer.rs index 6b901e5d..64287414 100644 --- a/src/authorization/cedar_authorizer.rs +++ b/src/authorization/cedar_authorizer.rs @@ -175,7 +175,6 @@ impl Authorizer for CedarAuthorizer { matches!(decision, cedar_policy::Decision::Allow) } Err(e) => { - println!("error: {}", e); tracing::error!( error = %e, path = %http_request.path, -- cgit v1.2.3 From 9db67d2d2f4f2b109b10ca7b21a8edbe7cfbc9e1 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 13:19:55 -0600 Subject: chore: install cedar cli in CI --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6ae0a526..4968aa7b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -44,5 +44,6 @@ lint: needs: [] before_script: - rustup component add clippy rustfmt + - cargo install --locked cedar-policy-cli script: - make lint -- cgit v1.2.3 From c6ec4e63d797c5e6cc01a4f09e723ad781b1034e Mon Sep 17 00:00:00 2001 From: mo khan Date: Sat, 5 Jul 2025 13:25:42 -0600 Subject: test: convert i32 to tonic::Code --- tests/authorization/check_service_test.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index b50d3689..c5c824fc 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -28,7 +28,7 @@ mod tests { assert!(check_response.status.is_some()); let status = check_response.status.unwrap(); - assert_eq!(status.code, tonic::Code::Ok as i32); + assert_eq!(tonic::Code::from_i32(status.code), tonic::Code::Ok); } #[tokio::test] @@ -44,7 +44,10 @@ mod tests { assert!(check_response.status.is_some()); let status = check_response.status.unwrap(); - assert_eq!(status.code, tonic::Code::Unauthenticated as i32); + assert_eq!( + tonic::Code::from_i32(status.code), + tonic::Code::Unauthenticated + ); } #[tokio::test] @@ -80,7 +83,7 @@ mod tests { assert!(check_response.status.is_some()); let status = check_response.status.unwrap(); - assert_eq!(status.code, tonic::Code::Ok as i32); + assert_eq!(tonic::Code::from_i32(status.code), tonic::Code::Ok); } } @@ -95,7 +98,10 @@ mod tests { assert!(check_response.status.is_some()); let status = check_response.status.unwrap(); - assert_eq!(status.code, tonic::Code::Unauthenticated as i32); + assert_eq!( + tonic::Code::from_i32(status.code), + tonic::Code::Unauthenticated + ); } #[tokio::test] @@ -119,7 +125,7 @@ mod tests { let check_response = response.unwrap().into_inner(); let status = check_response.status.unwrap(); - assert_eq!(status.code, expected_status_code as i32); + assert_eq!(tonic::Code::from_i32(status.code), expected_status_code); } } -- cgit v1.2.3