mirror of
https://github.com/azaion/missions.git
synced 2026-06-21 09:31:06 +00:00
3398ec49a0
ci/woodpecker/push/build-arm Pipeline was successful
- Updated Azaion.Missions.csproj to exclude test sources from service compilation, preventing build failures due to test project dependencies. - Modified docker-compose.test.yml to preload the pg_stat_statements extension for testing and adjusted JWT refresh intervals for better test execution timing. - Enhanced Dockerfile to install wget for health checks and ensure proper initialization of the container. - Introduced a test-only endpoint for JWKS refresh to facilitate end-to-end testing without relying on the default refresh intervals. - Updated DTOs in ApiDtos.cs to reflect camelCase naming conventions for consistency with service responses. - Improved test cases to handle JWKS rotation and refresh scenarios effectively, ensuring robust validation of JWT handling. This commit lays the groundwork for more reliable and efficient testing of the Azaion.Missions project.
168 lines
7.6 KiB
YAML
168 lines
7.6 KiB
YAML
## Test compose stack for the missions service.
|
|
## Naming: post-rename target. Project entrypoint is Azaion.Missions.csproj.
|
|
## B5 (namespace), B6 (domain), B7 (drop GPS-Denied), B8 (HTTP routes), B9
|
|
## (DB migration), B12 (default-vehicle rule) have all landed locally.
|
|
## Cross-repo work pending: B4 (Gitea repo rename + suite .gitmodules + git mv),
|
|
## B10 (suite compose service block), B11 (autopilot/ui consumer cutover).
|
|
## Documented in _docs/02_document/tests/environment.md.
|
|
##
|
|
## Post-2026-05-14 drift re-verification: JWT model is ECDSA-SHA256 with JWKS
|
|
## fetched from the `admin` service. Tests provide a `jwks-mock` container that
|
|
## stands in for `admin` -- it holds a fixed ECDSA P-256 keypair, serves the
|
|
## public key as JWKS over HTTPS at `https://jwks-mock/.well-known/jwks.json`,
|
|
## and signs test tokens on demand at `https://jwks-mock/sign`. The consumer
|
|
## fetches signed tokens from the mock; missions validates them against the
|
|
## mock's JWKS. The private key never leaves the mock container.
|
|
services:
|
|
postgres-test:
|
|
image: postgres:16-alpine
|
|
container_name: missions-postgres-test
|
|
environment:
|
|
POSTGRES_DB: azaion
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres-test
|
|
## FT-N-06 (AC-3.2 cascade short-circuit) inspects pg_stat_statements
|
|
## to assert that DELETE statements against dependency tables are never
|
|
## issued for a 404. The extension must be preloaded at server start;
|
|
## CREATE EXTENSION alone is not enough. Production deployments would
|
|
## leave shared_preload_libraries unset by default — this knob lives in
|
|
## the test-only compose file.
|
|
command: ["postgres", "-c", "shared_preload_libraries=pg_stat_statements"]
|
|
ports:
|
|
- "5433:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d azaion"]
|
|
interval: 1s
|
|
timeout: 1s
|
|
retries: 30
|
|
networks:
|
|
- e2e-net
|
|
tmpfs:
|
|
## Ephemeral PG data; recreated per `docker compose down -v`.
|
|
- /var/lib/postgresql/data
|
|
|
|
jwks-mock:
|
|
## Build context populated by Step 6 (Implement Tests). The mock is a tiny
|
|
## ASP.NET Core / Python / Node app that:
|
|
## - Holds a fixed ECDSA P-256 keypair (in-memory; never exported).
|
|
## - Serves `GET /.well-known/jwks.json` over HTTPS with `Cache-Control:
|
|
## public, max-age=60` (60s instead of admin's 3600s so tests can observe
|
|
## rotation within a single 15-minute CI window).
|
|
## - Serves `POST /sign` over HTTPS accepting a claims JSON body and
|
|
## returning a signed JWT (ECDSA-SHA256) for test consumption.
|
|
## - Supports `POST /rotate-key` to generate a new keypair with a new
|
|
## `kid`; the prior public key stays in the JWKS for `OldKeyGraceSeconds`
|
|
## to verify the rotation transition (used by NFT-RES-07).
|
|
## - Self-signs its TLS certificate; the `missions` container trusts the
|
|
## mock's CA via a mounted volume at /etc/ssl/certs/jwks-mock-ca.crt.
|
|
## - Image tag: `azaion/jwks-mock:test`. Until built, run-tests.sh prints
|
|
## a clear "jwks-mock not yet built" message.
|
|
build:
|
|
context: tests/Azaion.Missions.JwksMock
|
|
dockerfile: Dockerfile
|
|
container_name: missions-jwks-mock
|
|
environment:
|
|
JWT_ISSUER: https://admin-test.azaion.local
|
|
JWT_AUDIENCE: azaion-edge
|
|
OLD_KEY_GRACE_SECONDS: 5
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -q --no-check-certificate -O - https://127.0.0.1:8443/.well-known/jwks.json || exit 1"]
|
|
interval: 2s
|
|
timeout: 1s
|
|
retries: 30
|
|
networks:
|
|
- e2e-net
|
|
|
|
missions:
|
|
build:
|
|
context: .
|
|
container_name: missions-sut
|
|
environment:
|
|
DATABASE_URL: postgresql://postgres:postgres-test@postgres-test:5432/azaion
|
|
JWT_ISSUER: https://admin-test.azaion.local
|
|
JWT_AUDIENCE: azaion-edge
|
|
JWT_JWKS_URL: https://jwks-mock:8443/.well-known/jwks.json
|
|
## Shorten the JWKS refresh throttle to the library minimum (1s) so
|
|
## the test-only /test/refresh-jwks endpoint can refresh on back-to-
|
|
## back rotation tests. ConfigurationManager.RequestRefresh() is
|
|
## itself throttled: after the very first call, subsequent calls are
|
|
## a no-op until (now - _lastRefresh) >= RefreshInterval. With 10s
|
|
## throttle, two rotation tests running ~300ms apart could not both
|
|
## force a refresh and the second one's cache would stay stale,
|
|
## poisoning every test downstream of it. 1s leaves the rotation
|
|
## tests pinned to their own grace-window timing (5s+) without
|
|
## introducing artificial delays.
|
|
##
|
|
## JWT_JWKS_AUTO_REFRESH_INTERVAL_SECONDS is intentionally NOT set:
|
|
## Microsoft.IdentityModel.Tokens.BaseConfigurationManager pins the
|
|
## floor to a static 5-minute MinimumAutomaticRefreshInterval, so
|
|
## any value below 300 throws at startup. The 12h default is fine for
|
|
## tests because rotation observation depends on RefreshInterval +
|
|
## /test/refresh-jwks, not the proactive auto-refresh path.
|
|
JWT_JWKS_REFRESH_INTERVAL_SECONDS: "1"
|
|
ASPNETCORE_URLS: http://+:8080
|
|
ASPNETCORE_ENVIRONMENT: Test
|
|
## CORS: Test environment (NOT Production) -- empty allow-list falls back
|
|
## to permissive with a PermissiveDefaultWarning log line (per
|
|
## CorsConfigurationValidator). Production-gate scenarios (E9 lock test)
|
|
## set ASPNETCORE_ENVIRONMENT=Production and assert startup THROWS.
|
|
## The jwks-mock CA cert is mounted so missions can validate the mock's
|
|
## TLS cert when fetching JWKS over HTTPS. The container ENTRYPOINT runs
|
|
## update-ca-certificates on startup so the mounted CA is trusted by the
|
|
## OS bundle that .NET HttpClient reads from.
|
|
volumes:
|
|
- ./tests/jwks-mock-ca.crt:/usr/local/share/ca-certificates/jwks-mock-ca.crt:ro
|
|
ports:
|
|
- "5002:8080"
|
|
depends_on:
|
|
postgres-test:
|
|
condition: service_healthy
|
|
jwks-mock:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
## Per AC-7.1, /health is anonymous. Container is "healthy" once /health returns 200.
|
|
test: ["CMD-SHELL", "wget -q -O - http://127.0.0.1:8080/health || exit 1"]
|
|
interval: 2s
|
|
timeout: 1s
|
|
retries: 30
|
|
networks:
|
|
- e2e-net
|
|
|
|
e2e-consumer:
|
|
## Build context placeholder -- populated by Step 6 (Implement Tests) when the
|
|
## test csproj is created. Until then, run-tests.sh detects the absence and
|
|
## prints a clear "test project not yet created" message.
|
|
build:
|
|
context: tests/Azaion.Missions.E2E.Tests
|
|
dockerfile: Dockerfile
|
|
container_name: missions-e2e
|
|
environment:
|
|
MISSIONS_BASE_URL: http://missions:8080
|
|
DB_SIDE_CHANNEL: Host=postgres-test;Port=5432;Database=azaion;Username=postgres;Password=postgres-test
|
|
## Consumer fetches test tokens from jwks-mock instead of minting locally:
|
|
## the private key never leaves the mock container, so tests can't
|
|
## accidentally sign with a key that doesn't match the mock's published JWKS.
|
|
JWKS_MOCK_SIGN_URL: https://jwks-mock:8443/sign
|
|
JWT_ISSUER: https://admin-test.azaion.local
|
|
JWT_AUDIENCE: azaion-edge
|
|
## Fixtures consumed by FixtureSql.Load (cascade_F3 / F4 in batch 2,
|
|
## NFT-* fixtures in subsequent batches). Mounted read-only below.
|
|
FIXTURE_SQL_DIR: /app/fixtures
|
|
depends_on:
|
|
missions:
|
|
condition: service_healthy
|
|
jwks-mock:
|
|
condition: service_healthy
|
|
volumes:
|
|
- ./test-results:/app/results
|
|
- ./tests/jwks-mock-ca.crt:/usr/local/share/ca-certificates/jwks-mock-ca.crt:ro
|
|
- ./_docs/00_problem/input_data/expected_results:/app/fixtures:ro
|
|
networks:
|
|
- e2e-net
|
|
profiles:
|
|
- test
|
|
|
|
networks:
|
|
e2e-net:
|
|
name: missions-e2e-net
|