summaryrefslogtreecommitdiff
path: root/tests/authorization
diff options
context:
space:
mode:
Diffstat (limited to 'tests/authorization')
-rw-r--r--tests/authorization/cedar_authorizer_test.rs66
-rw-r--r--tests/authorization/check_service_test.rs118
-rw-r--r--tests/authorization/mod.rs3
-rw-r--r--tests/authorization/server_test.rs48
4 files changed, 235 insertions, 0 deletions
diff --git a/tests/authorization/cedar_authorizer_test.rs b/tests/authorization/cedar_authorizer_test.rs
new file mode 100644
index 00000000..76bf06df
--- /dev/null
+++ b/tests/authorization/cedar_authorizer_test.rs
@@ -0,0 +1,66 @@
+#[cfg(test)]
+mod tests {
+ use crate::support::factory_bot::*;
+ use authzd::Authorizer;
+ use envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest;
+ use std::collections::HashMap;
+
+ #[test]
+ fn test_cedar_authorizer_allows_valid_token() {
+ let request = build_request(|item: &mut HttpRequest| {
+ item.headers = build_with(|item: &mut HashMap<String, String>| {
+ item.insert(
+ String::from("authorization"),
+ String::from("Bearer valid-token"),
+ );
+ });
+ });
+
+ assert!(build_cedar_authorizer().authorize(request));
+ }
+
+ #[test]
+ fn test_cedar_authorizer_denies_invalid_token() {
+ let request = build_request(|item: &mut HttpRequest| {
+ item.headers = build_with(|item: &mut HashMap<String, String>| {
+ item.insert(
+ String::from("authorization"),
+ String::from("Bearer invalid-token"),
+ );
+ });
+ });
+
+ assert!(!build_cedar_authorizer().authorize(request));
+ }
+
+ #[test]
+ fn test_cedar_authorizer_denies_missing_header() {
+ let request = build_request(|item: &mut HttpRequest| {
+ item.headers = HashMap::new();
+ });
+
+ assert!(!build_cedar_authorizer().authorize(request));
+ }
+
+ #[test]
+ fn test_cedar_authorizer_allows_static_assets() {
+ let request = build_request(|item: &mut HttpRequest| {
+ item.headers = build_with(|item: &mut HashMap<String, String>| {
+ item.insert(String::from(":path"), String::from("/public/style.css"));
+ });
+ });
+
+ assert!(build_cedar_authorizer().authorize(request));
+ }
+
+ #[test]
+ fn test_cedar_authorizer_allows_js_assets() {
+ let mut headers = HashMap::new();
+ headers.insert(":path".to_string(), "/app.js".to_string());
+ let request = build_request(|item: &mut HttpRequest| {
+ item.headers = headers;
+ });
+
+ assert!(build_cedar_authorizer().authorize(request));
+ }
+}
diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs
new file mode 100644
index 00000000..3a225974
--- /dev/null
+++ b/tests/authorization/check_service_test.rs
@@ -0,0 +1,118 @@
+#[cfg(test)]
+mod tests {
+ use crate::support::factory_bot::*;
+ use authzd::CheckService;
+ use envoy_types::ext_authz::v3::pb::Authorization;
+ use envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest;
+ use std::collections::HashMap;
+ use std::sync::Arc;
+
+ fn subject() -> CheckService {
+ CheckService::new(Arc::new(build_cedar_authorizer()))
+ }
+
+ #[tokio::test]
+ async fn test_check_allows_valid_bearer_token() {
+ let request = tonic::Request::new(build_request(|item: &mut HttpRequest| {
+ item.headers = build_headers(vec![(
+ "authorization".to_string(),
+ format!("Bearer {}", String::from("valid-token")),
+ )])
+ }));
+
+ 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!(status.code, tonic::Code::Ok as i32);
+ }
+
+ #[tokio::test]
+ async fn test_check_denies_invalid_bearer_token() {
+ let request = tonic::Request::new(build_request(|item: &mut HttpRequest| {
+ item.headers = HashMap::new();
+ }));
+
+ 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!(status.code, tonic::Code::Unauthenticated as i32);
+ }
+
+ #[tokio::test]
+ async fn test_static_assets() {
+ let static_paths = vec![
+ "app.js",
+ "favicon.ico",
+ "image.jpg",
+ "index.html",
+ "logo.png",
+ "style.css",
+ ];
+
+ for path in static_paths {
+ let request = tonic::Request::new(build_request(|http| {
+ http.headers = build_headers(vec![(":path".to_string(), path.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!(status.code, tonic::Code::Ok as i32);
+ }
+ }
+
+ #[tokio::test]
+ async fn test_no_headers() {
+ let request = tonic::Request::new(build_request(|_http| {}));
+
+ 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!(status.code, tonic::Code::Unauthenticated as i32);
+ }
+
+ #[tokio::test]
+ async fn test_table() {
+ let test_cases = vec![
+ ("Bearer valid-token", true),
+ ("Bearer invalid-token", false),
+ ("Basic valid-token", false),
+ ("", false),
+ ];
+
+ for (auth_value, should_succeed) 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())]);
+ }));
+
+ let response = subject().check(request).await;
+ assert!(response.is_ok());
+
+ 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);
+ }
+ }
+ }
+}
diff --git a/tests/authorization/mod.rs b/tests/authorization/mod.rs
new file mode 100644
index 00000000..675247d4
--- /dev/null
+++ b/tests/authorization/mod.rs
@@ -0,0 +1,3 @@
+mod cedar_authorizer_test;
+mod check_service_test;
+mod server_test;
diff --git a/tests/authorization/server_test.rs b/tests/authorization/server_test.rs
new file mode 100644
index 00000000..fe8c8a73
--- /dev/null
+++ b/tests/authorization/server_test.rs
@@ -0,0 +1,48 @@
+#[cfg(test)]
+mod tests {
+ use crate::support::factory_bot::*;
+ use std::net::SocketAddr;
+ use tokio::net::TcpListener;
+
+ async fn available_port() -> SocketAddr {
+ let listener = TcpListener::bind("127.0.0.1:0")
+ .await
+ .expect("Failed to bind to random port");
+ let addr = listener.local_addr().expect("Failed to get local address");
+ drop(listener);
+ addr
+ }
+
+ async fn start_server() -> (SocketAddr, tokio::task::JoinHandle<()>) {
+ let addr = available_port().await;
+ let server = authzd::authorization::Server::default();
+
+ let handle = tokio::spawn(async move {
+ server.serve(addr).await.expect("Failed to start server");
+ });
+
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
+
+ (addr, handle)
+ }
+
+ #[tokio::test]
+ async fn test_health_check_service() {
+ let (addr, server) = start_server().await;
+ let mut client =
+ build_rpc_client(addr, tonic_health::pb::health_client::HealthClient::new).await;
+
+ let request = tonic::Request::new(tonic_health::pb::HealthCheckRequest {
+ service: String::new(),
+ });
+ let response = client.check(request).await;
+
+ assert!(response.is_ok());
+ assert_eq!(
+ response.unwrap().into_inner().status(),
+ tonic_health::pb::health_check_response::ServingStatus::Serving
+ );
+
+ server.abort();
+ }
+}