|
1 | 1 | use std::net::IpAddr; |
2 | 2 | use std::sync::{Arc, Mutex}; |
3 | 3 |
|
| 4 | +use base64::{engine::general_purpose::STANDARD, Engine as _}; |
4 | 5 | use edgezero_core::body::Body as EdgeBody; |
5 | 6 | use edgezero_core::http::response_builder as edge_response_builder; |
6 | 7 | use edgezero_core::key_value_store::NoopKvStore; |
@@ -258,6 +259,10 @@ fn test_runtime_services(req: &Request) -> RuntimeServices { |
258 | 259 | ) |
259 | 260 | } |
260 | 261 |
|
| 262 | +fn admin_authorization_header() -> String { |
| 263 | + format!("Basic {}", STANDARD.encode("admin:admin-pass")) |
| 264 | +} |
| 265 | + |
261 | 266 | fn test_runtime_services_with_http_client( |
262 | 267 | req: &Request, |
263 | 268 | backend: Arc<dyn PlatformBackend>, |
@@ -350,6 +355,66 @@ fn configured_missing_consent_store_only_breaks_consent_routes() { |
350 | 355 | ); |
351 | 356 | } |
352 | 357 |
|
| 358 | +#[test] |
| 359 | +fn admin_s3_debug_requires_auth_even_when_disabled() { |
| 360 | + let settings = create_test_settings(); |
| 361 | + let orchestrator = build_orchestrator(&settings).expect("should build auction orchestrator"); |
| 362 | + let integration_registry = |
| 363 | + IntegrationRegistry::new(&settings).expect("should create integration registry"); |
| 364 | + |
| 365 | + let req = Request::get("https://test.com/admin/debug/s3-objects"); |
| 366 | + let services = test_runtime_services(&req); |
| 367 | + let resp = futures::executor::block_on(route_request( |
| 368 | + &settings, |
| 369 | + &orchestrator, |
| 370 | + &integration_registry, |
| 371 | + &services, |
| 372 | + req, |
| 373 | + )) |
| 374 | + .expect("should route admin S3 debug request"); |
| 375 | + |
| 376 | + assert_eq!( |
| 377 | + resp.get_status(), |
| 378 | + StatusCode::UNAUTHORIZED, |
| 379 | + "should challenge unauthenticated S3 debug requests" |
| 380 | + ); |
| 381 | +} |
| 382 | + |
| 383 | +#[test] |
| 384 | +fn admin_s3_debug_disabled_returns_404_after_auth() { |
| 385 | + let mut settings = create_test_settings(); |
| 386 | + settings.response_headers.insert( |
| 387 | + header::CACHE_CONTROL.as_str().to_string(), |
| 388 | + "public, max-age=3600".to_string(), |
| 389 | + ); |
| 390 | + let orchestrator = build_orchestrator(&settings).expect("should build auction orchestrator"); |
| 391 | + let integration_registry = |
| 392 | + IntegrationRegistry::new(&settings).expect("should create integration registry"); |
| 393 | + |
| 394 | + let req = Request::get("https://test.com/admin/debug/s3-objects") |
| 395 | + .with_header(header::AUTHORIZATION, admin_authorization_header()); |
| 396 | + let services = test_runtime_services(&req); |
| 397 | + let resp = futures::executor::block_on(route_request( |
| 398 | + &settings, |
| 399 | + &orchestrator, |
| 400 | + &integration_registry, |
| 401 | + &services, |
| 402 | + req, |
| 403 | + )) |
| 404 | + .expect("should route admin S3 debug request"); |
| 405 | + |
| 406 | + assert_eq!( |
| 407 | + resp.get_status(), |
| 408 | + StatusCode::NOT_FOUND, |
| 409 | + "should hide the S3 debug endpoint when the config flag is disabled" |
| 410 | + ); |
| 411 | + assert_eq!( |
| 412 | + resp.get_header_str(header::CACHE_CONTROL), |
| 413 | + Some("no-store, private"), |
| 414 | + "should prevent configured response headers from making S3 debug responses cacheable" |
| 415 | + ); |
| 416 | +} |
| 417 | + |
353 | 418 | #[test] |
354 | 419 | fn asset_routes_bypass_publisher_consent_dependencies() { |
355 | 420 | let mut settings = create_test_settings(); |
|
0 commit comments