Secrets Patterns
Patterns & Best Practices
Secrets vs. Config
A common question is whether to use the Config Store or the Secret Vault.
| Feature | Secrets | Config Store |
|---|---|---|
| Encryption | AES-256-GCM (Encrypted). | Plaintext JSON. |
| Visibility | Write-only (except in function). | Readable via API/UI. |
| Best For | API Keys, DB Passwords. | Feature flags, Timeouts. |
Pattern: Optional Dependencies
Functions should check if a secret is available before using it. This allows your code to gracefully degrade if an integration (like Slack or Sentry) isn’t configured in a specific environment.
async ({ event, secrets, step }) => { if (secrets.has("SLACK_WEBHOOK")) { const url = secrets.get("SLACK_WEBHOOK"); await step.run("notify", () => postToSlack(url, "Task started!")); }}func(ctx ironflow.Context) (any, error) { if ctx.Secrets.Has("SLACK_WEBHOOK") { var url string if err := ctx.Secrets.Get("SLACK_WEBHOOK", &url); err != nil { return nil, err } // ... } return nil, nil}Environment Promotion
Secrets are strictly scoped to an Environment. You must set them independently for each stage of your pipeline.
# Developmentironflow secret set DB_PASSWORD dev_pass --env default
# Production (using the specific environment API Key)IRONFLOW_API_KEY="ifkey_prod_..." ironflow secret set DB_PASSWORD prod_passSecurity Checklist
- Always Set the Master Key in Production:
IRONFLOW_MASTER_KEYmust be set to a hex-encoded 32 bytes (openssl rand -hex 32). If the variable is unset or empty, Ironflow falls back to a development mode that stores secret values in plaintext on disk and logs a warning at startup. - Treat the Master Key as Immutable: If you rotate
IRONFLOW_MASTER_KEY, all previously stored secrets become unreadable. Plan rotations as a full re-set of every secret. - Environment Isolation: Use different API Keys for CI/CD and Production. An API Key leaked from a dev environment cannot access production secrets.
- No Logging: Decrypted secret values are not automatically redacted from your application logs. Avoid passing secret values into
console.log, structured log fields, error messages, or third-party telemetry. The engine itself never logs the plaintext. - Least Privilege: Only declare the secrets your function actually needs in the
secrets: [...]array.