HIPAA PR1: provision audit signing secret for security-audit + worker - #48
Merged
Merged
Conversation
Problem: security-audit and security-audit-worker never received JWT_SECRET
in this compose file, so two things silently fell back to the public
literal "change-me" instead of the real platform secret:
- security-audit's own JWT verification (api/deps.py::require_
platform_admin, audit/identity.py::validate_identity_token)
- AuditConfig.EVENT_SIGNING_SECRET (audit/config.py:34,
os.getenv("JWT_SECRET", "change-me")), which PR2's
classify_event_integrity() uses to verify audit-event signatures
Fix: both services now receive JWT_SECRET: ${AUTH_SECRET_KEY:-change-me},
the exact same variable name/value every other JWT_SECRET consumer in
this file already uses (auth-service's own SECRET_KEY, api-gateway,
control-center, tes, ...). No new variable introduced, no secret value
added to source -- AUTH_SECRET_KEY is sourced from .env (gitignored,
untracked) exactly as it already is for every other consumer.
Verified live prior to this commit (hash comparison only, values never
printed): security-audit's JWT_SECRET, security-audit-worker's
JWT_SECRET, and auth-service's SECRET_KEY all hash identical inside
their running containers.
Scope: this is provisioning only. It does not add producer-side signing,
run the audit-integrity DB migration, touch audit classification/
verification code, address TES work_dir isolation, or touch GHCR/release
tooling -- each is a separate, later PR.
Validation:
- docker compose -f docker-compose.yml config --quiet: exit 0
- pytest tests/ (excl. integration): 97 passed
- pytest tests/test_compose_release_config.py
tests/test_compose_network_exposure.py: 71 passed (unaffected --
these cover the release compose files, not this one)
- node --test tests/test_secret_generation.js: 13 passed
- git diff reviewed: docker-compose.yml only, two services, both
additions match the file's own established JWT_SECRET pattern
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The audit-signing implementation exists in
omnibioai-security-audit(signing helper, integrity classification,EVENT_SIGNING_SECRET), but the signing component was not receiving the correctly provisioned secret in this repository's deployed configuration. Bothsecurity-auditandsecurity-audit-workerwere missingJWT_SECRETindocker-compose.yml, so:security-audit's own JWT verification (api/deps.py::require_platform_admin,audit/identity.py::validate_identity_token)AuditConfig.EVENT_SIGNING_SECRET(audit/config.py,os.getenv("JWT_SECRET", "change-me")), which the worker'sclassify_event_integrity()uses to verify audit-event signaturesboth silently fell back to the public literal
"change-me"instead of the real platform secret.Fix
Both services now receive
JWT_SECRET: ${AUTH_SECRET_KEY:-change-me}— the exact same variable name and value every otherJWT_SECRETconsumer in this compose file already uses (api-gateway,control-center,tes, and others;auth-serviceitself signs with the equivalentSECRET_KEY). No new variable was introduced and no secret value was added to source —AUTH_SECRET_KEYis sourced from.env, which is gitignored and untracked, exactly as it already is for every existing consumer.Verified live prior to this commit, by hash comparison only (no value ever printed):
security-audit'sJWT_SECRET,security-audit-worker'sJWT_SECRET, andauth-service'sSECRET_KEYall hash identical inside their running containers.Security impact
This enables the existing audit-event signing/verification mechanism in
omnibioai-security-auditto operate with the intended platform signing secret instead of a public default. It is a prerequisite for making audit integrity operational — without it, once a producer starts signing events (a later PR), the worker would verify against the wrong secret and misclassify every legitimately signed event asinvalid.Scope
This PR is provisioning only. It explicitly does not implement:
work_dirisolationEach of the above is a separate, later PR per the planned sequence (PR2: DB/schema deployment, PR3: producer signing, PR4: TES isolation).
Validation
git diffreviewed:docker-compose.ymlonly, two services (security-audit,security-audit-worker), both additions match the file's own establishedJWT_SECRETpattern exactly.🤖 Generated with Claude Code