Doctor plugin checks: implement health check classes and documentation
Implement remediation-aware health checks across all Doctor plugin modules (Agent, Attestor, Auth, BinaryAnalysis, Compliance, Crypto, Environment, EvidenceLocker, Notify, Observability, Operations, Policy, Postgres, Release, Scanner, Storage, Vex) and their backing library counterparts (AI, Attestation, Authority, Core, Cryptography, Database, Docker, Integration, Notify, Observability, Security, ServiceGraph, Sources, Verification). Each check now emits structured remediation metadata (severity, category, runbook links, and fix suggestions) consumed by the Doctor dashboard remediation panel. Also adds: - docs/doctor/articles/ knowledge base for check explanations - Advisory AI search seed and allowlist updates for doctor content - Sprint plan for doctor checks documentation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
138
docs/doctor/articles/security/secrets.md
Normal file
138
docs/doctor/articles/security/secrets.md
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
checkId: check.security.secrets
|
||||
plugin: stellaops.doctor.security
|
||||
severity: fail
|
||||
tags: [security, secrets, configuration]
|
||||
---
|
||||
# Secrets Configuration
|
||||
|
||||
## What It Checks
|
||||
Validates that secrets are properly managed and not exposed as plain text in configuration. The check scans the following configuration keys for potential plain-text secrets:
|
||||
|
||||
| Key | What it protects |
|
||||
|---|---|
|
||||
| `Jwt:SigningKey` | JWT token signing |
|
||||
| `Jwt:Secret` | JWT secret (alternative key) |
|
||||
| `ApiKey` | API authentication key |
|
||||
| `ApiSecret` | API secret |
|
||||
| `S3:SecretKey` | Object storage credentials |
|
||||
| `Smtp:Password` | Email server credentials |
|
||||
| `Ldap:Password` | Directory service credentials |
|
||||
| `Redis:Password` | Cache/message broker credentials |
|
||||
| `Valkey:Password` | Cache/message broker credentials |
|
||||
|
||||
A value is considered a plain-text secret if it:
|
||||
1. Is at least 8 characters long.
|
||||
2. Contains both uppercase and lowercase letters.
|
||||
3. Contains digits or special characters.
|
||||
4. Does NOT start with a secrets provider prefix: `vault:`, `azurekv:`, `aws:`, `gcp:`, `${`, or `@Microsoft.KeyVault`.
|
||||
|
||||
The check also examines whether a secrets management provider is configured (`Secrets:Provider`, `KeyVault:Provider`, `Secrets:VaultUrl`, `KeyVault:Url`, `Vault:Address`). A missing secrets manager is only flagged if plain-text secrets are also found.
|
||||
|
||||
Note: Connection strings are intentionally excluded from this check as they are DSNs (host/port/db) and are expected in configuration.
|
||||
|
||||
## Why It Matters
|
||||
Plain-text secrets in configuration files are a critical security risk. Configuration files are often committed to version control, stored in CI artifacts, or readable by anyone with filesystem access. Leaked secrets enable:
|
||||
|
||||
- Token forgery (JWT signing keys).
|
||||
- Unauthorized API access (API keys).
|
||||
- Data access via backend services (database, SMTP, LDAP passwords).
|
||||
- Lateral movement within the infrastructure.
|
||||
|
||||
## Common Causes
|
||||
- Secrets stored directly in `appsettings.json` instead of using a secrets provider
|
||||
- Environment variables containing secrets not sourced from a secrets manager
|
||||
- Development secrets left in production configuration
|
||||
- No secrets management provider configured (HashiCorp Vault, Azure Key Vault, etc.)
|
||||
|
||||
## How to Fix
|
||||
|
||||
### Docker Compose
|
||||
Use Docker secrets or reference an external secrets manager:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
platform:
|
||||
environment:
|
||||
Jwt__SigningKey: "vault:secret/data/stellaops/jwt#signing_key"
|
||||
Secrets__Provider: "vault"
|
||||
Secrets__VaultUrl: "http://vault:8200"
|
||||
secrets:
|
||||
- jwt_signing_key
|
||||
|
||||
secrets:
|
||||
jwt_signing_key:
|
||||
file: ./secrets/jwt_signing_key.txt
|
||||
```
|
||||
|
||||
Or use `dotnet user-secrets` for development:
|
||||
```bash
|
||||
dotnet user-secrets set "Jwt:SigningKey" "<your-secret>"
|
||||
```
|
||||
|
||||
### Bare Metal / systemd
|
||||
Configure a secrets provider in `appsettings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"Secrets": {
|
||||
"Provider": "vault",
|
||||
"VaultUrl": "https://vault.internal:8200",
|
||||
"UseSecretManager": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Store secrets in the provider instead of config files:
|
||||
```bash
|
||||
# HashiCorp Vault
|
||||
vault kv put secret/stellaops/jwt signing_key="<key>"
|
||||
|
||||
# dotnet user-secrets (development)
|
||||
dotnet user-secrets set "Jwt:SigningKey" "<key>"
|
||||
```
|
||||
|
||||
### Kubernetes / Helm
|
||||
Store secrets as Kubernetes Secrets:
|
||||
|
||||
```bash
|
||||
kubectl create secret generic stellaops-secrets \
|
||||
--from-literal=jwt-signing-key="<key>" \
|
||||
--from-literal=smtp-password="<password>"
|
||||
```
|
||||
|
||||
Reference in Helm values:
|
||||
```yaml
|
||||
secrets:
|
||||
provider: "kubernetes"
|
||||
existingSecret: "stellaops-secrets"
|
||||
```
|
||||
|
||||
Or use an external secrets operator (e.g., External Secrets Operator with Vault):
|
||||
```yaml
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: stellaops-secrets
|
||||
spec:
|
||||
secretStoreRef:
|
||||
name: vault-backend
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: stellaops-secrets
|
||||
data:
|
||||
- secretKey: jwt-signing-key
|
||||
remoteRef:
|
||||
key: secret/stellaops/jwt
|
||||
property: signing_key
|
||||
```
|
||||
|
||||
## Verification
|
||||
```
|
||||
stella doctor run --check check.security.secrets
|
||||
```
|
||||
|
||||
## Related Checks
|
||||
- `check.security.jwt.config` — JWT signing key security
|
||||
- `check.security.encryption` — encryption key management
|
||||
- `check.security.apikey` — API key security practices
|
||||
Reference in New Issue
Block a user