use envoy_types::ext_authz::v3::CheckResponseExt; use envoy_types::ext_authz::v3::pb::{CheckRequest, CheckResponse}; use std::sync::Arc; use tonic::{Request, Response, Status}; use super::authorizer::Authorizer; #[derive(Debug)] pub struct CheckService { authorizer: Arc, } impl CheckService { pub fn new(authorizer: Arc) -> Self { Self { authorizer } } } #[tonic::async_trait] impl envoy_types::ext_authz::v3::pb::Authorization for CheckService { async fn check( &self, request: Request, ) -> Result, Status> { let request = request.into_inner(); if self.authorizer.authorize(request) { Ok(Response::new(CheckResponse::with_status(Status::ok("OK")))) } else { Ok(Response::new(CheckResponse::with_status( Status::unauthenticated("Unauthorized"), ))) } } } #[cfg(test)] mod tests { use super::*; use super::super::cedar_authorizer::CedarAuthorizer; use envoy_types::ext_authz::v3::pb::{Authorization, CheckRequest}; use envoy_types::pb::envoy::service::auth::v3::{AttributeContext, attribute_context}; use std::collections::HashMap; use std::sync::Arc; use tonic::Request; fn create_test_request_with_headers(headers: HashMap) -> Request { let http_request = attribute_context::HttpRequest { headers, ..Default::default() }; let request_context = attribute_context::Request { http: Some(http_request), ..Default::default() }; let attributes = AttributeContext { request: Some(request_context), ..Default::default() }; let check_request = CheckRequest { attributes: Some(attributes), ..Default::default() }; Request::new(check_request) } fn create_headers_with_auth(auth_value: &str) -> HashMap { let mut headers = HashMap::new(); headers.insert("authorization".to_string(), auth_value.to_string()); headers } #[tokio::test] async fn test_check_allows_valid_bearer_token() { let token = String::from("valid-token"); let authorizer = Arc::new(CedarAuthorizer::new()); let server = CheckService::new(authorizer); let headers = create_headers_with_auth(&format!("Bearer {}", token)); let request = create_test_request_with_headers(headers); let response = server.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!(status.code, tonic::Code::Ok as i32); } #[tokio::test] async fn test_check_denies_invalid_bearer_token() { let authorizer = Arc::new(CedarAuthorizer::new()); let server = CheckService::new(authorizer); let request = create_test_request_with_headers(HashMap::new()); let response = server.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!(status.code, tonic::Code::Unauthenticated as i32); } }