sec: externalize hardcoded secrets in docker-compose.yml - #330
sec: externalize hardcoded secrets in docker-compose.yml#330raaidrushdy wants to merge 2 commits into
Conversation
Preview EnvironmentA preview environment can be spun up on demand for this PR.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f798130222
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| # Required: Database connection (PostgreSQL with asyncpg driver) | ||
| - DATABASE_URL=postgresql+asyncpg://autoaudit:autoaudit_dev_password@db:5432/autoaudit | ||
| - DATABASE_URL=postgresql+asyncpg://autoaudit:${POSTGRES_PASSWORD}@db:5432/autoaudit |
There was a problem hiding this comment.
Migrate passwords for existing PostgreSQL volumes
For developers upgrading with an existing postgres_data volume, the Postgres image does not reapply POSTGRES_PASSWORD after the data directory has been initialized, but this URL immediately makes the backend authenticate with the newly generated .env value. Unless users retain the old exposed password, both application services will fail authentication after the upgrade; provide a password migration/reset step or explicitly recreate the development volume before switching the connection URLs.
Useful? React with 👍 / 👎.
| # Generate with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" | ||
| # This will be passed in with a secret provider in production. This is for local use only. | ||
| - ENCRYPTION_KEY=Ps-HiS3ww5QzQPc_Mdu5-JyA_jCNbdFHMdiwWSlAfgM= | ||
| - ENCRYPTION_KEY=${ENCRYPTION_KEY:?ENCRYPTION_KEY not set — see env.example} |
There was a problem hiding this comment.
Preserve access to credentials encrypted with the old key
When an existing installation replaces the committed Fernet key with a newly generated ENCRYPTION_KEY, credentials already stored in its persistent PostgreSQL volume remain encrypted with the old key. Calls through backend-api/app/services/encryption.py::decrypt and engine/worker/db.py::decrypt will then raise InvalidToken, preventing saved connections and scans from working; migrate/re-encrypt those values or document a required credential reset before rotating the key.
Useful? React with 👍 / 👎.
|
|
||
| # Required: Database connection (PostgreSQL with asyncpg driver) | ||
| - DATABASE_URL=postgresql+asyncpg://autoaudit:autoaudit_dev_password@db:5432/autoaudit | ||
| - DATABASE_URL=postgresql+asyncpg://autoaudit:${POSTGRES_PASSWORD}@db:5432/autoaudit |
There was a problem hiding this comment.
Keep reserved characters out of the database URL
If POSTGRES_PASSWORD contains URI-reserved characters such as @, /, : or %, interpolating it verbatim into this SQLAlchemy URL changes how the authority is parsed even though PostgreSQL receives the literal password from its environment. Since the new template neither encodes nor constrains this value, an otherwise valid generated password can prevent both backend and worker database connections; use a URL-encoded companion value or document a URL-safe generation command.
Useful? React with 👍 / 👎.
| GOOGLE_OAUTH_CLIENT_SECRET= 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 | ||
|
|
||
| # Postgres (used by db, backend-api, worker) | ||
| POSTGRES_PASSWORD= |
There was a problem hiding this comment.
Make the documented Compose quick start runnable
For a new checkout following docs/GETTING_STARTED.md, the documented sequence is only cp env.example .env followed by docker compose --profile all up, but these newly required entries remain empty and Compose's ${VAR:?…} expressions reject empty values before starting anything. Update the onboarding instructions to require populating all three values—also providing a PostgreSQL password generation command—or supply safe development defaults through a non-secret mechanism.
Useful? React with 👍 / 👎.
26T2-DEV-RR-002 - Testing & EvidenceWhat I didI removed three hardcoded credentials from WhyThis closes the primary finding from my Week 4/5 baseline audit How I tested it
Result
Related finding raised separately (not fixed here, out of scope for this task)The Alembic "multiple head revisions" error blocks a clean first-time |
|
addressed codex review |
Summary
Removes three hardcoded credentials from docker-compose.yml (POSTGRES_PASSWORD, SECRET_KEY, ENCRYPTION_KEY) and replaces them with
${VAR:?}references sourced from a local, gitignored.envfile. The previously-exposed Fernet ENCRYPTION_KEY has been rotated, the new value only exists in local.envfiles, never in version control. env.example is updated with the three new required variables and generation instructions for each.Type of Change
Affected Components
/infrastructure(docker-compose.yml is root-level dev infra config)Motivation
Covers Planner task 26T2-DEV-RR-002 (Workstream 4). Follows directly from the baseline audit (26T2-SEC-RR-001), which documented three real credentials sitting in plaintext in docker-compose.yml, including a live Fernet key actively used to encrypt stored M365/AWS/Azure/GCP credentials at rest. This closes that finding by moving all three to environment variables that are never committed.
Testing Done
.env, and randocker compose --profile all up --build -dwith a fresh volume. Confirmed Postgres authentication succeeded with the new.env-sourced password (proving the${VAR}substitution works correctly) before hitting an unrelated, pre-existing Alembic "multiple head revisions" migration error. Verified this error is not caused by this change by reproducing it against unmodifiedmainas well.Security Considerations
This is the core fix for the credential-exposure finding in the Week 4/5 baseline audit. The old ENCRYPTION_KEY value is treated as compromised (it was exposed in git history) and has been rotated, not just relocated; the new key only exists in local
.envfiles..envis already covered by.gitignore.env.examplekeeps blank placeholders only, with generation commands documented as comments.Breaking Changes
Anyone running the stack locally now needs a
.envfile (cp env.example .env) populated withPOSTGRES_PASSWORD,SECRET_KEY, andENCRYPTION_KEYbeforedocker compose upwill work; previously, these had working defaults baked into docker-compose.yml. Generation commands for each are documented in env.example.Rollback Plan
Checklist
Screenshots
N/A — infra config change, no UI impact.