mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 15:11:13 +00:00
[AZ-491] [AZ-492] [AZ-493] [AZ-494] [AZ-496] Cycle 3 Step 14: security audit refresh
All 5 phases refreshed against cycle-3 delta:
Phase 1 (Dependency Scan):
- D1 RESOLVED (AZ-496): Microsoft.AspNetCore.OpenApi 8.0.21 → 8.0.25
- D3 RESOLVED (AZ-496): JwtBearer 8.0.21 → 8.0.25
- D4 NEW (Low, test-only): System.IdentityModel.Tokens.Jwt 7.0.3 +
Microsoft.IdentityModel.Tokens 7.0.3 pinned in TestSupport carry
CVE-2024-21319 (JWE DoS). Bump to ≥ 7.1.2 tracked as future PBI.
Phase 2 (Static Analysis):
- F-AUTH-3 (Info): test runner Program.cs logs iss/aud at startup;
production API does NOT (verified by grep).
- F-AUTH-4 (Info): DEV-ONLY iss/aud placeholders in
appsettings.Development.json + .env.example — by design per
Option B for AZ-494.
- F-DBR-1: TRUNCATE string interpolation in
IntegrationTestDatabaseReset.cs — false positive (hard-coded
table list).
- F-DBR-2 (Low): TRUNCATE guard is operator-bypassable. Two-guard
model is conservative-by-default and unit-tested.
- F-PERF-1 (Low): perf-bootstrap --mint-only writes a 4-hour
GPS-permission token to stdout. Operator-trusted machine assumed.
Phase 3 (OWASP Top 10):
- A03 carries D1/D3 RESOLVED + D4 NEW.
- A07 flips F-AUTH-2 to RESOLVED (AZ-494); residual revocation-list
Low recorded.
- A05 status unchanged (F-DBR-1 false positive).
- A08 picks up F-DBR-2.
Phase 4 (Infrastructure):
- JWT_ISSUER / JWT_AUDIENCE flow .env → compose → Kestrel config,
same pattern as JWT_SECRET.
- INTEGRATION_TEST_DB_RESET + ASPNETCORE_ENVIRONMENT=Testing wired
for AZ-493 reset gate.
- SatelliteProvider.TestSupport is IsPackable=false — never ships
in a production container image.
- New operational gate added to deploy runbook: grep for DEV-ONLY-
in the rendered deploy environment must return zero hits.
Phase 5 (Security Report):
- Verdict: PASS_WITH_WARNINGS (cycle 3 does not escalate).
- 0 Critical, 0 High, 0 new Medium.
- Cycle-2 F-AUTH-2 (Medium) RESOLVED; cycle-1 D1 + cycle-2 D3
RESOLVED.
Autodev state advanced to Step 14 completed. Next: Step 15
(Performance Test, optional gate).
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -109,4 +109,33 @@
|
||||
### Cycle-2 operational follow-ups (NOT findings — pre-deploy verification)
|
||||
|
||||
1. The deploy pipeline must verify `JWT_SECRET` is set to a ≥ 32-byte value distinct from the DEV-ONLY placeholder before promoting `api`. The application throws at startup if the value is missing or short, so a misconfigured deploy fails fast — but a deploy that *promotes* the dev placeholder verbatim would still pass the 32-byte gate. Tracked in `security_report.md` cycle-2 recommendations.
|
||||
2. Coordinate with admin team on `iss`/`aud` values (F-AUTH-2). When values are defined, both the `AddSatelliteJwt` call site and `.env`/compose docs must be updated together.
|
||||
2. Coordinate with admin team on `iss`/`aud` values (F-AUTH-2). When values are defined, both the `AddSatelliteJwt` call site and `.env`/compose docs must be updated together. **RESOLVED in cycle 3 (AZ-494)** — `AddSatelliteJwt` now validates both; values flow `JWT_ISSUER` / `JWT_AUDIENCE` env → compose `environment` → Kestrel config. See cycle-3 delta below.
|
||||
|
||||
---
|
||||
|
||||
## Cycle 3 Delta (AZ-491 / AZ-492 / AZ-493 / AZ-494 / AZ-495 / AZ-496)
|
||||
|
||||
### Infra changes this cycle
|
||||
|
||||
- `docker-compose.yml:33-34` adds `JWT_ISSUER=${JWT_ISSUER}` and `JWT_AUDIENCE=${JWT_AUDIENCE}` to the `api` service `environment` block (AZ-494).
|
||||
- `docker-compose.tests.yml:24-25` mirrors them on `integration-tests` so the runner mints tokens against the same iss/aud the API validates.
|
||||
- `.env.example` documents both new variables with the fail-fast contract and ships explicit `DEV-ONLY-` placeholder values (AZ-494). Replaces an earlier draft that left them blank with a stale "leave blank to fall back" comment — corrected during Step 16 setup.
|
||||
- `.env` (gitignored, developer-only) now also carries `JWT_ISSUER=DEV-ONLY-iss-admin-azaion-local` + `JWT_AUDIENCE=DEV-ONLY-aud-satellite-provider` for the local docker-compose flow.
|
||||
- `docker-compose.tests.yml:21` sets `ASPNETCORE_ENVIRONMENT=Testing` and `:22` sets `DB_CONNECTION_STRING=Host=postgres;...`. Both are consumed by AZ-493's `IntegrationTestResetGuard.EnsureGuardPassesOrThrow(env, host)` — env must be `Testing` AND host must be in the allowlist (`postgres` / `localhost` / `127.0.0.1`), otherwise the reset throws.
|
||||
- `docker-compose.tests.yml:20` adds `INTEGRATION_KEEP_STATE=${INTEGRATION_KEEP_STATE:-}` so the `--keep-state` flag on `scripts/run-tests.sh` short-circuits the reset (debugging convenience).
|
||||
- `scripts/run-tests.sh` + `scripts/run-performance-tests.sh` both load + export the new env vars and fail-fast if missing (mirrors the AZ-487 `JWT_SECRET` pattern).
|
||||
- No new exposed ports. No new external services. No CI workflow changes (`.woodpecker/01-test.yml` and `02-build-push.yml` unchanged).
|
||||
- New `SatelliteProvider.TestSupport` project — `IsPackable=false`, never builds a container, never ships outside test images. Confirmed via `Dockerfile` review: only `SatelliteProvider.Api/Dockerfile` and `SatelliteProvider.IntegrationTests/Dockerfile` exist; neither produces a published artifact from TestSupport.
|
||||
|
||||
### Cycle-3 verdict — clean
|
||||
|
||||
- **Secret distribution**: `JWT_ISSUER` / `JWT_AUDIENCE` flow `.env` → docker-compose `environment` → Kestrel `IConfiguration` → `AddSatelliteJwt`. Same path as `JWT_SECRET`, no new mechanism introduced. Production values are NOT in the repo (the .env in git tracks only the example); production deploy supplies them via the deploy pipeline (operator-confirmed admin-team values).
|
||||
- **Production safety contract**: empty `Jwt.Issuer` / `Jwt.Audience` in `appsettings.json` + the fail-fast `ResolveRequiredOrThrow` extension guarantees that a production deploy without explicit env-var values cannot start. This is the user-selected Option B forcing function.
|
||||
- **Test-side DB reset**: AZ-493's two-guard logic (`ASPNETCORE_ENVIRONMENT == "Testing"` + Host allowlist) is the test-runner's equivalent of a fail-fast contract. Documented as F-DBR-2 (Low) in static_analysis.md.
|
||||
- **Perf harness**: `scripts/run-performance-tests.sh` uses `mktemp -d` for fixture + response paths; cleaned up on `trap EXIT`. Token minted via `dotnet <integration-tests.dll> --mint-only` — never written to disk by the harness (only to a shell variable). Documented as F-PERF-1 (Low) in static_analysis.md.
|
||||
|
||||
### Cycle-3 operational follow-ups (NOT findings — pre-deploy verification)
|
||||
|
||||
1. The deploy pipeline must supply real `JWT_ISSUER` + `JWT_AUDIENCE` values (admin-team-confirmed) when promoting `api`. The application throws at startup if either is empty or whitespace — a misconfigured deploy fails fast.
|
||||
2. The DEV-ONLY iss/aud placeholders in `appsettings.Development.json` + `.env.example` are deliberately committed (Option B). A grep for `DEV-ONLY-` surfaces every site that must NOT ship to production. Make this grep part of the deploy gate runbook.
|
||||
3. The cross-repo `suite/_docs/10_auth.md` write (AC-7) is deferred — outside this workspace's boundary. The suite repo's owner must take this on as a follow-up.
|
||||
|
||||
Reference in New Issue
Block a user