[NX-204 Issue] Add secret management guidelines and enhance security notes
Some checks are pending
Container CVE Scan (development) / Scan backend/frontend images for CVEs (push) Waiting to run
Migration Safety / Alembic upgrade/downgrade safety (push) Successful in 2m43s
PostgreSQL Compatibility Matrix / PG14 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG15 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG16 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG17 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG18 smoke (push) Successful in 7s
Proxy Profile Validation / validate (push) Successful in 3s
Python Dependency Security / pip-audit (block high/critical) (push) Successful in 26s
Docker Publish (Release) / Build and Push Docker Images (release) Successful in 1m41s
Some checks are pending
Container CVE Scan (development) / Scan backend/frontend images for CVEs (push) Waiting to run
Migration Safety / Alembic upgrade/downgrade safety (push) Successful in 2m43s
PostgreSQL Compatibility Matrix / PG14 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG15 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG16 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG17 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG18 smoke (push) Successful in 7s
Proxy Profile Validation / validate (push) Successful in 3s
Python Dependency Security / pip-audit (block high/critical) (push) Successful in 26s
Docker Publish (Release) / Build and Push Docker Images (release) Successful in 1m41s
Introduced a comprehensive guide for secure production secret handling (`docs/security/secret-management.md`). Updated `.env.example` files with clearer comments on best practices, emphasizing not hardcoding secrets and implementing rotation strategies. Enhanced README with a new section linking to the secret management documentation.
This commit is contained in:
@@ -12,6 +12,7 @@ LOG_LEVEL=INFO
|
||||
# Core Database (internal metadata DB)
|
||||
# ------------------------------
|
||||
# Database that stores users, targets, metrics, query stats, and audit logs.
|
||||
# DEV default only. Use strong unique credentials in production.
|
||||
DB_NAME=nexapg
|
||||
DB_USER=nexapg
|
||||
DB_PASSWORD=nexapg
|
||||
@@ -23,7 +24,7 @@ DB_PORT=5433
|
||||
# ------------------------------
|
||||
# Host port mapped to backend container port 8000.
|
||||
BACKEND_PORT=8000
|
||||
# JWT signing secret. Change this in every non-local environment.
|
||||
# JWT signing secret. Never hardcode in source. Rotate regularly.
|
||||
JWT_SECRET_KEY=change_this_super_secret
|
||||
JWT_ALGORITHM=HS256
|
||||
# Access token lifetime in minutes.
|
||||
@@ -31,6 +32,7 @@ JWT_ACCESS_TOKEN_MINUTES=15
|
||||
# Refresh token lifetime in minutes (10080 = 7 days).
|
||||
JWT_REFRESH_TOKEN_MINUTES=10080
|
||||
# Key used to encrypt monitored target passwords at rest.
|
||||
# Never hardcode in source. Rotate with re-encryption plan.
|
||||
# Generate with:
|
||||
# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||||
ENCRYPTION_KEY=REPLACE_WITH_FERNET_KEY
|
||||
|
||||
16
README.md
16
README.md
@@ -23,6 +23,7 @@ It combines FastAPI, React, and PostgreSQL in a Docker Compose stack with RBAC,
|
||||
- [Production Proxy Profile](#production-proxy-profile)
|
||||
- [PostgreSQL Compatibility Smoke Test](#postgresql-compatibility-smoke-test)
|
||||
- [Dependency Exception Flow](#dependency-exception-flow)
|
||||
- [Secret Management (Production)](#secret-management-production)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Security Notes](#security-notes)
|
||||
|
||||
@@ -414,6 +415,19 @@ Python dependency vulnerabilities are enforced by CI via `pip-audit`.
|
||||
- Full process and required metadata are documented in:
|
||||
- `docs/security/dependency-exceptions.md`
|
||||
|
||||
## Secret Management (Production)
|
||||
|
||||
Secret handling guidance is documented in:
|
||||
|
||||
- `docs/security/secret-management.md`
|
||||
|
||||
It includes:
|
||||
|
||||
- secure handling for `JWT_SECRET_KEY`, `ENCRYPTION_KEY`, `DB_PASSWORD`, and SMTP credentials
|
||||
- clear **Do / Don't** rules
|
||||
- recommended secret provider patterns (Vault/cloud/orchestrator/CI injection)
|
||||
- practical rotation basics and operational checklist
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Backend container keeps restarting during `make migrate`
|
||||
@@ -448,3 +462,5 @@ Set target `sslmode` to `disable` (or correct SSL config on target DB).
|
||||
- RBAC enforced on protected endpoints
|
||||
- Audit logs for critical actions
|
||||
- Collector error logging includes throttling to reduce repeated noise
|
||||
- Production secret handling and rotation guidance:
|
||||
- `docs/security/secret-management.md`
|
||||
|
||||
74
docs/security/secret-management.md
Normal file
74
docs/security/secret-management.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Secret Management (Production)
|
||||
|
||||
This guide defines secure handling for NexaPG secrets in production deployments.
|
||||
|
||||
## In Scope Secrets
|
||||
|
||||
- `JWT_SECRET_KEY`
|
||||
- `ENCRYPTION_KEY`
|
||||
- `DB_PASSWORD`
|
||||
- SMTP credentials (configured in Admin Settings, encrypted at rest)
|
||||
|
||||
## Do / Don't
|
||||
|
||||
## Do
|
||||
|
||||
- Use an external secret source (Vault, cloud secret manager, orchestrator secrets, or CI/CD secret injection).
|
||||
- Keep secrets out of Git history and out of image layers.
|
||||
- Use strong random values:
|
||||
- JWT secret: at least 32+ bytes random
|
||||
- Fernet key: generated via `Fernet.generate_key()`
|
||||
- Restrict access to runtime secrets (least privilege).
|
||||
- Rotate secrets on schedule and on incident.
|
||||
- Store production `.env` with strict permissions if file-based injection is used:
|
||||
- owner-only read/write (e.g., `chmod 600 .env`)
|
||||
- Audit who can read/update secrets in your deployment platform.
|
||||
|
||||
## Don't
|
||||
|
||||
- Do **not** hardcode secrets in source code.
|
||||
- Do **not** commit `.env` with real values.
|
||||
- Do **not** bake production secrets into Dockerfiles or image build args.
|
||||
- Do **not** share secrets in tickets, chat logs, or CI console output.
|
||||
- Do **not** reuse the same secrets between environments.
|
||||
|
||||
## Recommended Secret Providers
|
||||
|
||||
Pick one of these models:
|
||||
|
||||
1. Platform/Cloud secrets
|
||||
- AWS Secrets Manager
|
||||
- Azure Key Vault
|
||||
- Google Secret Manager
|
||||
2. HashiCorp Vault
|
||||
3. CI/CD secret injection
|
||||
- Inject as runtime env vars during deployment
|
||||
4. Docker/Kubernetes secrets
|
||||
- Prefer secret mounts or orchestrator-native secret stores
|
||||
|
||||
If you use plain `.env` files, treat them as sensitive artifacts and protect at OS and backup level.
|
||||
|
||||
## Rotation Basics
|
||||
|
||||
Minimum baseline:
|
||||
|
||||
1. `JWT_SECRET_KEY`
|
||||
- Rotate on schedule (e.g., quarterly) and immediately after compromise.
|
||||
- Expect existing sessions/tokens to become invalid after rotation.
|
||||
2. `ENCRYPTION_KEY`
|
||||
- Rotate with planned maintenance.
|
||||
- Re-encrypt stored encrypted values (target passwords, SMTP password) during key transition.
|
||||
3. `DB_PASSWORD`
|
||||
- Rotate service account credentials regularly.
|
||||
- Apply password changes in DB and deployment config atomically.
|
||||
4. SMTP credentials
|
||||
- Use dedicated sender account/app password.
|
||||
- Rotate regularly and after provider-side security alerts.
|
||||
|
||||
## Operational Checklist
|
||||
|
||||
- [ ] No production secret in repository files.
|
||||
- [ ] No production secret in container image metadata or build args.
|
||||
- [ ] Runtime secret source documented for your environment.
|
||||
- [ ] Secret rotation owner and schedule defined.
|
||||
- [ ] Incident runbook includes emergency rotation steps.
|
||||
@@ -12,6 +12,7 @@ LOG_LEVEL=INFO
|
||||
# Core Database (internal metadata DB)
|
||||
# ------------------------------
|
||||
# Database that stores users, targets, metrics, query stats, and audit logs.
|
||||
# DEV default only. Use strong unique credentials in production.
|
||||
DB_NAME=nexapg
|
||||
DB_USER=nexapg
|
||||
DB_PASSWORD=nexapg
|
||||
@@ -23,7 +24,7 @@ DB_PORT=5433
|
||||
# ------------------------------
|
||||
# Host port mapped to backend container port 8000.
|
||||
BACKEND_PORT=8000
|
||||
# JWT signing secret. Change this in every non-local environment.
|
||||
# JWT signing secret. Never hardcode in source. Rotate regularly.
|
||||
JWT_SECRET_KEY=change_this_super_secret
|
||||
JWT_ALGORITHM=HS256
|
||||
# Access token lifetime in minutes.
|
||||
@@ -31,6 +32,7 @@ JWT_ACCESS_TOKEN_MINUTES=15
|
||||
# Refresh token lifetime in minutes (10080 = 7 days).
|
||||
JWT_REFRESH_TOKEN_MINUTES=10080
|
||||
# Key used to encrypt monitored target passwords at rest.
|
||||
# Never hardcode in source. Rotate with re-encryption plan.
|
||||
# Generate with:
|
||||
# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||||
ENCRYPTION_KEY=REPLACE_WITH_FERNET_KEY
|
||||
|
||||
Reference in New Issue
Block a user