--- name: credential-handling description: No hardcoded credentials; use SOPS vault or env vars; JWT auth; Argon2 hashing; log auth attempts applies-to: all --- # Credential Handling ## Core rules - **Never hardcode credentials** — no passwords, tokens, API keys, or connection strings in any source file, script, or config file that is committed to git - **Use SOPS vault** for all secrets in this repo — access via the ClaudeTools vault wrapper: ```bash VAULT="$CLAUDETOOLS_ROOT/.claude/scripts/vault.sh" bash "$VAULT" get-field bash "$VAULT" get bash "$VAULT" search "keyword" ``` - **Use environment variables** as an alternative when SOPS is impractical (e.g., Docker, CI). Never put the env var value in a committed file. - **`.env` files are gitignored** and must never be committed. Verify before staging any `.env` file. ## Vault path structure ``` infrastructure/ — servers, services, SSH keys clients/ — per-client credentials services/ — third-party APIs (Syncro, etc.) projects/ — project-specific secrets (GuruRMM DB, etc.) msp-tools/ — MSP app suite tokens ``` The vault wrapper reads `vault_path` from `.claude/identity.json` (per-machine, gitignored). Every machine sets its own vault path there — no hardcoded vault paths in any shared file. ## API authentication - **JWT tokens** for all ClaudeTools API authentication - **Argon2** for password hashing (not bcrypt, not MD5, not SHA-256 plain) - Log all authentication attempts and sensitive operations — failures must be logged with timestamp, IP, and identity attempted ## What not to commit Never commit: - `.env` files - `credentials.json`, `*.pem`, `*.p12`, `*.pfx` - Any file matching `*secret*`, `*password*`, `*token*` unless it is a SOPS-encrypted `.sops.yaml` - Vault YAML files before encryption (plaintext SOPS files) - SSH private keys ## Accessing secrets in scripts ```bash # Correct — vault wrapper PASSWORD=$(bash "$VAULT" get-field projects/claudetools/database.sops.yaml credentials.password) # Correct — environment variable (set externally, not hardcoded) psql "postgres://${DB_USER}:${DB_PASS}@localhost:5432/gururmm" # WRONG — hardcoded inline (caught in code review) psql "postgres://gururmm:43617ebf7eb242e814ca9988cc4df5ad@localhost:5432/gururmm" ``` ## 1Password fallback The 1Password service account token is in `infrastructure/1password-service-account.sops.yaml`. Use 1Password as a secondary vault for secrets that need to be accessed outside the SOPS workflow.