Secrets Management¶
Securely manage sensitive values in your deployments.
Overview¶
OmniDeploy supports multiple approaches for handling secrets:
- Environment Variables - Pass at deploy time
- Pulumi Config - Encrypted in Pulumi state
- AWS Secrets Manager - Fetched at container runtime
- AWS SSM Parameter Store - Fetched at container runtime
Environment Variables¶
The simplest approach - pass secrets when deploying:
Deploy:
Pros:
- Simple, no setup required
- Works everywhere
Cons:
- Secrets visible in process list
- Not suitable for shared CI/CD
- No audit trail
Pulumi Secrets¶
Store secrets encrypted in Pulumi state:
# Set secret
cd ~/.omnideploy/pulumi
pulumi stack select my-app
pulumi config set --secret api_key sk-...
pulumi config set --secret database_url postgres://...
Reference in deployment:
Pros:
- Encrypted at rest
- Version controlled (with state)
- Team sharing via remote state
Cons:
- Requires Pulumi CLI for management
- Secrets in Pulumi state
AWS Secrets Manager¶
Store secrets in AWS and fetch at container runtime:
1. Create Secret¶
aws secretsmanager create-secret \
--name my-app/api-key \
--secret-string "sk-..."
aws secretsmanager create-secret \
--name my-app/database-url \
--secret-string "postgres://..."
2. Reference in Config¶
# deploy.yaml
secrets:
- name: API_KEY
source: secretsmanager:my-app/api-key
- name: DATABASE_URL
source: secretsmanager:my-app/database-url
3. Grant Access¶
Ensure your container has IAM permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:*:*:secret:my-app/*"
]
}
]
}
Pros:
- Secrets never in config or state
- Audit trail via CloudTrail
- Automatic rotation support
- Fine-grained access control
Cons:
- AWS-specific
- Additional cost (~$0.40/secret/month)
- Requires IAM setup
AWS SSM Parameter Store¶
Similar to Secrets Manager, but simpler and cheaper:
1. Create Parameter¶
aws ssm put-parameter \
--name /my-app/api-key \
--value "sk-..." \
--type SecureString
aws ssm put-parameter \
--name /my-app/database-url \
--value "postgres://..." \
--type SecureString
2. Reference in Config¶
# deploy.yaml
secrets:
- name: API_KEY
source: ssm:/my-app/api-key
- name: DATABASE_URL
source: ssm:/my-app/database-url
Pros:
- Free for standard parameters
- Simple API
- Integrated with AWS
Cons:
- Less features than Secrets Manager
- No automatic rotation
Comparison¶
| Method | Security | Cost | Complexity | Audit |
|---|---|---|---|---|
| Environment Variables | Low | Free | Low | None |
| Pulumi Config | Medium | Free | Medium | Git history |
| AWS Secrets Manager | High | ~$0.40/mo | Medium | CloudTrail |
| AWS SSM | High | Free | Medium | CloudTrail |
Best Practices¶
1. Never Commit Secrets¶
2. Use Different Secrets Per Environment¶
# Staging
aws secretsmanager create-secret --name staging/my-app/api-key ...
# Production
aws secretsmanager create-secret --name production/my-app/api-key ...
3. Rotate Secrets Regularly¶
Set up automatic rotation in AWS Secrets Manager.
4. Audit Access¶
Enable CloudTrail and monitor for unexpected secret access.
5. Least Privilege¶
Grant minimal IAM permissions:
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue"],
"Resource": ["arn:aws:secretsmanager:*:*:secret:my-app/*"],
"Condition": {
"StringEquals": {
"aws:RequestTag/environment": "production"
}
}
}
CI/CD Integration¶
GitHub Actions¶
- name: Deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# App secrets via AWS Secrets Manager - not in env
run: omnideploy up --config deploy.yaml --yes