From 5c3ee5670ba8546208dd26af90ac2e44bd43906e Mon Sep 17 00:00:00 2001 From: o0Ignition0o Date: Mon, 31 Jul 2023 16:21:24 +0200 Subject: [PATCH] add counters, and a test --- ...nfiguration__tests__schema_generation.snap | 11 ++++- .../src/plugins/authentication/subgraph.rs | 30 +++++++++---- .../tests/fixtures/subgraph_auth.router.yaml | 34 +++++++++++++++ apollo-router/tests/metrics_tests.rs | 42 +++++++++++++++++++ 4 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 apollo-router/tests/fixtures/subgraph_auth.router.yaml diff --git a/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap b/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap index 99079cdde0..bf7d0901f1 100644 --- a/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap +++ b/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap @@ -211,6 +211,7 @@ expression: "&schema" "additionalProperties": false } }, + "additionalProperties": false, "nullable": true }, "subgraph": { @@ -271,6 +272,7 @@ expression: "&schema" "type": "string" } }, + "additionalProperties": false, "nullable": true }, "region": { @@ -327,6 +329,7 @@ expression: "&schema" "type": "string" } }, + "additionalProperties": false, "nullable": true }, "profile_name": { @@ -342,7 +345,8 @@ expression: "&schema" "description": "The service you're trying to access, eg: \"s3\", \"vpc-lattice-svcs\", etc.", "type": "string" } - } + }, + "additionalProperties": false } }, "additionalProperties": false @@ -411,6 +415,7 @@ expression: "&schema" "type": "string" } }, + "additionalProperties": false, "nullable": true }, "region": { @@ -467,6 +472,7 @@ expression: "&schema" "type": "string" } }, + "additionalProperties": false, "nullable": true }, "profile_name": { @@ -482,7 +488,8 @@ expression: "&schema" "description": "The service you're trying to access, eg: \"s3\", \"vpc-lattice-svcs\", etc.", "type": "string" } - } + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/apollo-router/src/plugins/authentication/subgraph.rs b/apollo-router/src/plugins/authentication/subgraph.rs index 9831166329..6c3acea3d7 100644 --- a/apollo-router/src/plugins/authentication/subgraph.rs +++ b/apollo-router/src/plugins/authentication/subgraph.rs @@ -195,10 +195,20 @@ pub(crate) struct SigningParamsConfig { service_name: String, } -#[allow(dead_code)] -fn increment_success_counter(_subgraph_name: &str) {} -#[allow(dead_code)] -fn increment_failure_counter(_subgraph_name: &str) {} +fn increment_success_counter(subgraph_name: &str) { + tracing::info!( + monotonic_counter.apollo.router.operations.authentication.aws.sigv4 = 1u64, + authentication.aws.sigv4.failed = false, + service_name = %subgraph_name, + ); +} +fn increment_failure_counter(subgraph_name: &str) { + tracing::info!( + monotonic_counter.apollo.router.operations.authentication.aws.sigv4 = 1u64, + authentication.aws.sigv4.failed = true, + service_name = %subgraph_name, + ); +} pub(super) async fn make_signing_params( config: &AuthConfig, @@ -251,9 +261,11 @@ impl SubgraphAuth { service: crate::services::subgraph::BoxService, ) -> crate::services::subgraph::BoxService { if let Some(signing_params) = self.params_for_service(name) { + let name = name.to_string(); ServiceBuilder::new() .checkpoint_async(move |mut req: SubgraphRequest| { let signing_params = signing_params.clone(); + let name = name.clone(); async move { let credentials = match signing_params.credentials_provider.provide_credentials().await { Ok(credentials) => credentials, @@ -262,6 +274,7 @@ impl SubgraphAuth { "Failed to serialize GraphQL body for AWS SigV4 signing, skipping signing. Error: {}", err ); + increment_failure_counter(name.as_str()); return Ok(ControlFlow::Continue(req)); } }; @@ -279,9 +292,10 @@ impl SubgraphAuth { Ok(b) => b, Err(err) => { tracing::error!( - "Failed to serialize GraphQL body for AWS SigV4 signing, skipping signing. Error: {}", - err - ); + "Failed to serialize GraphQL body for AWS SigV4 signing, skipping signing. Error: {}", + err + ); + increment_failure_counter(name.as_str()); return Ok(ControlFlow::Continue(req)); } }; @@ -302,10 +316,12 @@ impl SubgraphAuth { Ok(output) => output, Err(err) => { tracing::error!("Failed to sign GraphQL request for AWS SigV4, skipping signing. Error: {}", err); + increment_failure_counter(name.as_str()); return Ok(ControlFlow::Continue(req)); } }.into_parts(); signing_instructions.apply_to_request(&mut req.subgraph_request); + increment_success_counter(name.as_str()); Ok(ControlFlow::Continue(req)) } }).buffered() diff --git a/apollo-router/tests/fixtures/subgraph_auth.router.yaml b/apollo-router/tests/fixtures/subgraph_auth.router.yaml new file mode 100644 index 0000000000..6abe171ad7 --- /dev/null +++ b/apollo-router/tests/fixtures/subgraph_auth.router.yaml @@ -0,0 +1,34 @@ +telemetry: + metrics: + prometheus: + listen: 127.0.0.1:4000 + enabled: true + path: /metrics + common: + attributes: + subgraph: + all: + request: + header: + - named: "x-custom-header" + rename: "custom_header" + default: "unknown" +headers: + all: + request: + - insert: + name: "x-custom-header" + value: "test_custom" +override_subgraph_url: + products: http://localhost:4005 +include_subgraph_errors: + all: true +authentication: + subgraph: + all: + aws_sig_v4: + hardcoded: + access_key_id: "test" + secret_access_key: "test" + region: "us-east-1" + service_name: "test_service" diff --git a/apollo-router/tests/metrics_tests.rs b/apollo-router/tests/metrics_tests.rs index be58864d1e..c93bd892f2 100644 --- a/apollo-router/tests/metrics_tests.rs +++ b/apollo-router/tests/metrics_tests.rs @@ -1,5 +1,6 @@ use std::time::Duration; +use serde_json::json; use tower::BoxError; use crate::common::IntegrationTest; @@ -7,6 +8,7 @@ use crate::common::IntegrationTest; mod common; const PROMETHEUS_CONFIG: &str = include_str!("fixtures/prometheus.router.yaml"); +const SUBGRAPH_AUTH_CONFIG: &str = include_str!("fixtures/subgraph_auth.router.yaml"); #[tokio::test(flavor = "multi_thread")] async fn test_metrics_reloading() -> Result<(), BoxError> { @@ -69,3 +71,43 @@ async fn test_metrics_reloading() -> Result<(), BoxError> { Ok(()) } + +#[tokio::test(flavor = "multi_thread")] +async fn test_subgraph_auth_metrics() -> Result<(), BoxError> { + let mut router = IntegrationTest::builder() + .config(SUBGRAPH_AUTH_CONFIG) + .build() + .await; + + router.start().await; + router.assert_started().await; + + router.execute_default_query().await; + router.execute_default_query().await; + + // Remove auth + router.update_config(PROMETHEUS_CONFIG).await; + router.assert_reloaded().await; + // This one will not be signed, counters shouldn't increment. + router + .execute_query(&json! {{ "query": "query { me { name } }"}}) + .await; + + // Get Prometheus metrics. + let metrics_response = router.get_metrics_response().await.unwrap(); + + // Validate metric headers. + let metrics_headers = metrics_response.headers(); + assert!( + "text/plain; version=0.0.4" + == metrics_headers + .get(http::header::CONTENT_TYPE) + .unwrap() + .to_str() + .unwrap() + ); + + router.assert_metrics_contains(r#"apollo_router_operations_authentication_aws_sigv4_total{authentication_aws_sigv4_failed="false",service_name="apollo-router",service_name="products",otel_scope_name="apollo/router",otel_scope_version=""} 2"#, None).await; + + Ok(()) +}