Secrets Management
Application secrets are stored as a single JSON object in GCP Secret
Manager. Each environment (production, non-production) has its own GCP
project containing a vault secret (e.g., hbcrm-vault).
At container startup, the entrypoint script calls
fetch_secrets.sh, which authenticates through a two-step
chain: first it gets a VM service account token from the GCE metadata
server, then uses that to fetch a vault service account key from the
vault-keys project, and finally exchanges that for a token to read the
actual app secrets from the vault-secrets project. The fetched JSON is
parsed and each key-value pair is written as an individual file to
/app/secrets/. The envdir utility then exports
each file as an environment variable, making secrets available to Django
via os.environ.
If GCP is unavailable, the script falls back to a Redis cache of the last successful fetch.
Vault Console Links
| Environment | Console URL |
|---|---|
| Production | prj-bu1-p-vault-secrets-8d4a |
| Non-production | prj-bu1-n-vault-secrets-9d03 |
Tip: Always update non-production first, deploy and verify, then repeat for production.
Steps
Open the vault for your target environment using the links above. The vault secret is named
{app_name}-vaultClick the secret, open the latest version, and click “View secret value”.Copy the entire JSON to a temporary local file:
Warning: This file contains every secret for the environment. Do NOT save it inside the repo or leave it on disk.
Edit the JSON – add a new key or update an existing value:
{ "EXISTING_SECRET": "existing-value", "NEW_OR_UPDATED_SECRET": "your-secret-value-here" }Key names are case-sensitive and must match what the application reads via
os.environ.get().Validate the JSON by pretty-printing it to verify syntax and content:
python -m json.tool $TEMP_FILE # OR jq . $TEMP_FILEUpload the new version – on the vault secret page, click “+ New Version”, paste the updated JSON, and click “Add new version”.
Disable the previous version to prevent rollback to stale data. It can be re-enabled if needed.
Delete the temporary file.
Deploy. On next deploy, containers automatically pull the latest version. The secret is available in the application as
os.environ.get("YOUR_SECRET_NAME")– no additional configuration needed.
Notes for HA Admin Portals
- Add the secret key and placeholder value to .env
(prod and staging)
.webappfor the Admin Portal Apps.interfacetaskservicefor Interface Tasks.interfacetaskwebtestfor Interface Task Swagger, e.g., https://massmu.myhaapp.com/test