chore: update configuration and Docker setup for JWT and test results
ci/woodpecker/push/build-arm Pipeline was successful

Enhanced the .gitignore to exclude test results and updated the Dockerfile to include a new entrypoint script for improved container initialization. Refactored JWT configuration to support additional parameters for automatic refresh intervals, ensuring better control over token management. Updated the ConfigurationResolver to enforce required environment variables without hardcoded fallbacks, enhancing security and flexibility.
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-15 03:23:23 +03:00
parent 7025f4d075
commit 78dea8ebab
40 changed files with 1990 additions and 510 deletions
+8 -8
View File
@@ -40,16 +40,16 @@
| # | Restriction | Evidence |
|---|-------------|----------|
| E1 | Two required env vars at runtime: `DATABASE_URL`, `JWT_SECRET` | `Program.cs` `Environment.GetEnvironmentVariable` |
| E2 | `DATABASE_URL` accepts either a `postgresql://user:pass@host:port/db` URL OR a raw Npgsql connection string (local helper `ConvertPostgresUrl`) | `Program.cs` `ConvertPostgresUrl` |
| E3 | Hardcoded development fallbacks: `JWT_SECRET=development-secret-key-min-32-chars!!`, `DATABASE_URL=Host=localhost;Database=azaion;Username=postgres;Password=changeme` (NOT gated on `IsDevelopment()`) — ADR-005 carry-forward; production deploys MUST override | `Program.cs` |
| E4 | `JWT_SECRET` is shared across `admin` + every backend service on the same edge device — rotation requires a coordinated re-deploy across all of them | `_docs/02_document/components/05_identity/description.md`; suite arch doc |
| E1 | Four required env vars at runtime: `DATABASE_URL`, `JWT_ISSUER`, `JWT_AUDIENCE`, `JWT_JWKS_URL`. Each resolved via `Infrastructure/ConfigurationResolver.cs` `ResolveRequiredOrThrow` (env-first, then `IConfiguration` config key `Database:Url` / `Jwt:Issuer` / `Jwt:Audience` / `Jwt:JwksUrl`, else throw at startup). The legacy `JWT_SECRET` env var is no longer consulted | `Program.cs`, `Auth/JwtExtensions.cs`, `Infrastructure/ConfigurationResolver.cs` |
| E2 | `DATABASE_URL` accepts either a `postgresql://user:pass@host:port/db` URL OR a raw Npgsql connection string (local helper `ConvertPostgresUrl`). `ConvertPostgresUrl` does NOT URL-decode user/password — credentials with `@`, `:`, `/`, `%` need raw Npgsql form | `Program.cs` `ConvertPostgresUrl` |
| E3 | **No hardcoded development fallbacks.** `ResolveRequiredOrThrow` throws `InvalidOperationException` at startup if any of `DATABASE_URL` / `JWT_ISSUER` / `JWT_AUDIENCE` / `JWT_JWKS_URL` is missing or whitespace-only. ADR-005's "dev fallback secret" branch is obsolete; only the Swagger-unconditional branch remains | `Infrastructure/ConfigurationResolver.cs`; `Program.cs` |
| E4 | JWT signature validation is asymmetric (ECDSA-SHA256) against the JWKS at `JWT_JWKS_URL`. `admin` holds the private key; this service caches the public JWKS via `Microsoft.IdentityModel.Protocols.ConfigurationManager<JsonWebKeySet>` (fetched at startup, refreshed on default schedule, HTTPS-only via `HttpDocumentRetriever { RequireHttps = true }`). **JWKS rotation does NOT require a coordinated redeploy** — consumers pick up the new keys at the next refresh tick | `Auth/JwtExtensions.cs`; `_docs/02_document/components/05_identity/description.md` |
| E5 | Container `EXPOSE 8080`; edge compose maps host port `5002:8080` | `Dockerfile`; suite `_infra/_compose/` |
| E6 | Image tag: `${REGISTRY_HOST}/azaion/missions:${BRANCH}-arm` post-B10 (was `azaion/flights:*-arm` pre-B10) | `.woodpecker/build-arm.yml` (post-B10) |
| E7 | Entrypoint: `dotnet Azaion.Missions.dll` post-B5 (was `Azaion.Flights.dll` pre-B5) | `Dockerfile` (post-B5) |
| E8 | No environment-specific overrides in `appsettings.*.json` — single config flow via env vars | `Program.cs`; no `appsettings.Production.json` in repo |
| E9 | CORS: `AllowAnyOrigin / AllowAnyMethod / AllowAnyHeader` in **all** environments (assumed safe behind suite reverse proxy) | `Program.cs` |
| E10 | TLS termination is the suite reverse proxy's responsibility — container exposes plain HTTP on `:8080` | `Dockerfile`; suite arch doc |
| E8 | No environment-specific overrides in `appsettings.*.json` today, but `IConfiguration` lookups (e.g. `Database:Url`, `Jwt:Issuer`) are wired so adding `appsettings.*.json` later requires no code changes | `Program.cs`; no `appsettings.*.json` in repo |
| E9 | CORS is gated by `Infrastructure/CorsConfigurationValidator.cs`. In `Production` (case-insensitive on `ASPNETCORE_ENVIRONMENT`) startup THROWS when `CorsConfig:AllowedOrigins` is empty AND `CorsConfig:AllowAnyOrigin != true`. In non-Production environments, an empty allow-list with `AllowAnyOrigin=false` falls back to permissive (`AllowAnyOrigin/Method/Header`) and emits the `PermissiveDefaultWarning` startup log. The "all environments permissive" claim no longer holds | `Program.cs`, `Infrastructure/CorsConfigurationValidator.cs` |
| E10 | TLS termination is the suite reverse proxy's responsibility — container exposes plain HTTP on `:8080`. The JWKS fetch itself is independently constrained to HTTPS (`RequireHttps = true`) | `Dockerfile`; suite arch doc; `Auth/JwtExtensions.cs` |
## Operational restrictions
@@ -79,5 +79,5 @@
| Orthophoto / live-GPS / GPS correction | `gps-denied` (separate service after B7) | ADR-007 |
| TLS / HTTPS termination | Suite reverse proxy | `_docs/02_document/architecture.md` § 7 |
| Schema rename / column drop / type change | Future migration tool (ADR-004 carry-forward) | Today's `IF NOT EXISTS` migrator can't reshape existing schema; B9's `DROP TABLE IF EXISTS` is the single explicit destructive step |
| `iss` / `aud` JWT validation | Suite-level remediation (CMMC L2 row 3, AZ-487 / AZ-494) | Out of this Epic; consistent with shared-secret model today |
| `iss` / `aud` JWT validation | **Now implemented in this service's code** (`ValidateIssuer=true` against `JWT_ISSUER`, `ValidateAudience=true` against `JWT_AUDIENCE`). The CMMC L2 row 3 finding is structurally fixed here; suite-level docs may still describe the legacy model and have a separate sync task pending | n/a — no longer a carry-forward in this repo |
| camelCase wire-shape migration | Suite-wide cutover (ADR-002 carry-forward) | All-or-nothing; UI + autopilot consume PascalCase today |