Secrets Management for .NET Apps
Secrets are not config values. Learn how to manage connection strings, API keys, and signing secrets securely using environment isolation, secret stores, and rotation strategies.
Secrets Leak by Default
Connection strings.
JWT signing keys.
API tokens.
Database passwords.
If you treat them like normal configuration:
- they end up in source control
- they end up in logs
- they end up in crash dumps
- they end up in CI artifacts
Production rule:
Secrets must never live in code or static config files.
Real Production Incident
Symptoms:
- Unexpected external API usage spike.
- Billing alert triggered.
- Investigation finds API key exposed in public Git repository.
Root cause:
- API key hardcoded in appsettings.json.
- File committed to repository.
- Repository mirrored publicly.
This is not rare. It is common.
Symptom → Cause → Diagnosis → Fix
Symptom:
- unauthorized third-party access
- leaked credentials detected by scanners
- production compromise via stolen secret
Cause:
- secrets stored in source control
- secrets shared via chat/email
- no rotation plan
- no environment separation
Diagnosis:
- scan repositories for secrets.
- audit CI logs and artifacts.
- check appsettings.* files for credentials.
- review environment variable usage.
Fix:
- move secrets to secure secret store.
- inject secrets via environment or managed identity.
- rotate exposed credentials immediately.
- implement secret scanning in CI.
Anti-Pattern: appsettings.json With Secrets
{
"ConnectionStrings": {
"Default": "Server=...;User Id=...;Password=SuperSecret123"
}
}
This will leak.
Even if private repo:
- backups
- logs
- contractor access
- misconfiguration
Production rule:
appsettings.json must not contain production secrets.
Correct Pattern: Environment + Secret Store
Options:
- Environment variables
- Cloud secret managers
- Kubernetes secrets (with caution)
- Managed identity / workload identity
Conceptual usage:
builder.Configuration
.AddEnvironmentVariables();
And inject:
var connectionString = builder.Configuration["ConnectionStrings:Default"];
But:
Environment variables are transport, not storage security.
Use them to inject secrets from a secure store.
Rotation Strategy
Secrets expire.
Keys rotate.
Credentials get compromised.
If you cannot rotate without downtime, you have operational debt.
Best practice:
- support overlapping keys (old + new)
- update secret store first
- deploy app using new secret
- remove old secret after confirmation
Production rule:
Rotation must be testable and automated.
Do Not Log Secrets
Common leak vector:
- logging full connection string
- logging configuration dump
- logging request headers (Authorization)
Mitigation:
- redact sensitive config values
- never log raw tokens
- use structured logging filters
Production rule:
Logs are semi-public. Treat them as such.
Secrets in Containers
If using containers:
- do not bake secrets into image
- inject at runtime
- avoid writing secrets to disk if possible
Kubernetes:
- prefer external secret stores
- avoid plain-text secrets in manifests
- use RBAC to restrict secret access
Managed Identity / Federated Identity
Prefer:
- identity-based access (e.g., workload identity)
- avoid static credentials
Instead of:
- storing database password
Use:
- managed identity with role-based access
Production rule:
Static secrets are last resort.
Security Notes
- Enable secret scanning in CI.
- Rotate secrets after any suspected exposure.
- Limit blast radius (different secrets per environment).
- Do not reuse secrets across services.
Defense in depth:
- secret store
- environment injection
- least privilege
- monitoring access
Operational Notes
Monitoring:
- track secret access events (if supported).
- alert on unusual secret retrieval patterns.
- audit configuration changes.
Rollout:
- test secret rotation in staging.
- canary new secret before decommissioning old one.
Rollback:
- if new secret breaks connectivity, revert to previous valid secret quickly.
- maintain versioned secret entries.
Governance:
- maintain secret inventory.
- define ownership per secret.
- define rotation interval per sensitivity level.
Checklist
- No production secrets stored in source code or appsettings files.
- Secrets injected via environment or secure store.
- Secret rotation strategy documented and tested.
- Logs do not contain sensitive values.
- Secrets separated per environment.
- CI includes secret scanning.
- Secret access monitored and auditable.
- Secret changes are canaried and rollbackable.