feat(security): add .gitignore and protection guide to prevent sensitive file commits

docs(audit): create comprehensive security audit report with critical findings and remediation steps
This commit is contained in:
nathan 2026-04-12 00:16:21 -04:00
parent 3d7eba7044
commit 623fdec2bf
4 changed files with 532 additions and 2 deletions

47
.gitignore vendored Normal file
View File

@ -0,0 +1,47 @@
# Environment variables and secrets
**/.env
**/*.env
.env
.env.*
# Komodo environment files (if extracted from UI)
**/komodo.env
# SSH keys and certificates
*.key
*.pem
*.crt
*.p12
*.pfx
id_rsa*
id_ed25519*
# Backup files that might contain sensitive data
*.backup
*.bak
*.old
# Temporary files
*.tmp
*.swp
*.swo
*~
# OS-specific files
.DS_Store
Thumbs.db
desktop.ini
# Editor directories
.vscode/
.idea/
*.code-workspace
# Logs that might contain sensitive information
*.log
logs/
**/access-logs/
# Local development overrides
docker-compose.override.yml
compose.override.yml

39
.gitignore.md Normal file
View File

@ -0,0 +1,39 @@
# .gitignore Protection Guide
**Created:** April 12, 2026
**Purpose:** Prevent accidental commit of sensitive files
## What This File Does
This `.gitignore` protects your homelab from accidentally committing:
- ✅ `.env` files containing secrets
- ✅ Private SSH keys and certificates
- ✅ Backup files that might contain sensitive data
- ✅ Log files with access tokens
- ✅ Local configuration overrides
## Verification
Check that `.gitignore` is working:
```bash
# Create a test .env file
echo "SECRET=test123" > test.env
# Try to see if Git tracks it
git status
# You should NOT see test.env in the output
# Clean up
rm test.env
```
## Already Committed Secrets?
If secrets were already committed to Git history, see:
- [SECURITY_AUDIT_REPORT.md](documentation/SECURITY_AUDIT_REPORT.md) - Section: "Git History Cleanup"
## Related Documentation
- [SECURITY_AUDIT_REPORT.md](documentation/SECURITY_AUDIT_REPORT.md)
- [SOP-001: Secrets Management](documentation/SOPs/SOP-001-Migrate-Stack-from-UI-to-Git.md#security-considerations)

View File

@ -11,7 +11,7 @@ This directory contains all technical documentation for the Castaldi Family Home
### 📘 Runbooks & Guides
- **[TECHNICAL_RUNBOOK.md](TECHNICAL_RUNBOOK.md)** - Complete infrastructure reference, emergency procedures, and maintenance schedule
- **[LLM_HANDOVER.md](LLM_HANDOVER.md)** - Quick-start context document for AI-assisted troubleshooting sessions
- **[SECURITY_AUDIT_REPORT.md](SECURITY_AUDIT_REPORT.md)** - 🔴 Security audit findings, exposed credentials, and remediation steps
---
@ -57,4 +57,4 @@ When documenting new issues or procedures:
---
**Last Updated:** April 11, 2026
**Last Updated:** April 12, 2026

View File

@ -0,0 +1,444 @@
# Security Audit Report: Homelab Infrastructure
**Report Date:** April 12, 2026
**Auditor:** FrankGPT Security Analysis
**Scope:** Complete repository scan for exposed secrets, credentials, and security vulnerabilities
**Status:** 🔴 **CRITICAL ISSUES FOUND**
---
## Executive Summary
A comprehensive security audit of the homelab repository has identified **1 critical vulnerability** and **3 high-priority security enhancements** needed to align with industry best practices. While the infrastructure demonstrates strong GitOps practices with environment variable usage in most services, several hardcoded credentials and exposed ports present immediate security risks.
**Risk Level:** 🔴 **HIGH** (Immediate remediation required)
---
## 🔴 Critical Findings
### 1. Hardcoded Plex Claim Token in Git Repository
**Severity:** 🔴 **CRITICAL**
**File:** `nodes/waldorf/plex/compose.yaml` (Line 12)
**Issue:** Plex claim token committed directly to version control
```yaml
# CURRENT (INSECURE)
environment:
- PLEX_CLAIM=claim-sxFpsPTDzzF-9RZAxtUL
```
**Risk Assessment:**
- **Impact:** Anyone with repository access can claim/hijack your Plex server
- **Exposure:** Token visible in Git history, even if removed from HEAD
- **Validity:** Plex claim tokens typically expire after 4 minutes, but this pattern indicates potential for other secrets
**Remediation Required:**
1. **Immediate Action:**
```bash
# Revoke/invalidate this claim token in Plex
# Visit: https://www.plex.tv/claim/
```
2. **Code Fix:**
```yaml
# CORRECTED (SECURE)
environment:
- PLEX_CLAIM=${PLEX_CLAIM} # Placeholder
```
3. **Komodo Configuration:**
- Add via Komodo UI → Stack → Environment Variables
- Variable: `PLEX_CLAIM=claim-NEW_TOKEN_HERE`
4. **Git History Cleanup (Optional but Recommended):**
```bash
# WARNING: Rewriting history affects all collaborators
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch nodes/waldorf/plex/compose.yaml" \
--prune-empty --tag-name-filter cat -- --all
```
**Status:** ⏳ **PENDING REMEDIATION**
---
## 🟡 High-Priority Security Enhancements
### 2. Redis Exposed Without Authentication
**Severity:** 🟡 **HIGH**
**File:** `nodes/heimdall/core/compose.yaml` (Line 40)
**Issue:** Redis cache exposed on host port 6379 without password protection
```yaml
# CURRENT (INSECURE)
redis:
image: redis:7-alpine
ports:
- "6379:6379" # ⚠️ Publicly exposed on LAN
command: redis-server --appendonly yes
# NO PASSWORD CONFIGURED
```
**Risk Assessment:**
- **Impact:** Unauthorized access to cached session data, potential data manipulation
- **Attack Surface:** Any device on LAN (10.0.0.x) can connect to Redis
- **Exploitability:** HIGH (Redis has no default authentication)
**Remediation Options:**
**Option A: Remove Public Port Binding (Recommended)**
```yaml
redis:
image: redis:7-alpine
# ports: # REMOVED - Only accessible via Docker network
# - "6379:6379"
networks:
- proxy-net # Internal-only access
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
environment:
- REDIS_PASSWORD=${REDIS_PASSWORD}
```
**Option B: Add Password Authentication (If external access needed)**
```yaml
redis:
image: redis:7-alpine
ports:
- "127.0.0.1:6379:6379" # Bind to localhost only
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
environment:
- REDIS_PASSWORD=${REDIS_PASSWORD}
```
**Komodo Environment Variable:**
- Add `REDIS_PASSWORD=<strong-random-password>` via Komodo UI
**Status:** 🟡 **RECOMMENDED**
---
### 3. Docker Socket Proxy Configured with Broad Write Access
**Severity:** 🟡 **MEDIUM**
**File:** `nodes/heimdall/core/compose.yaml` (Lines 28-33)
**Issue:** Docker socket proxy allows POST operations and container lifecycle management
```yaml
# CURRENT
environment:
- POST=1
- ALLOW_START=1
- ALLOW_STOP=1
- ALLOW_RESTARTS=1
```
**Risk Assessment:**
- **Impact:** Compromised Traefik or Komodo could manipulate all containers
- **Mitigation:** Proxy runs as privileged (`privileged: true`), limiting lateral movement
- **Trade-off:** Required for Komodo's container orchestration functionality
**Recommendation:**
- **Accept Risk:** This configuration is **required** for Komodo Core functionality
- **Monitoring:** Enable Docker audit logging to track container lifecycle events
- **Network Isolation:** Ensure `proxy-net` is not exposed beyond trusted services
**Status:** ✅ **ACCEPTED RISK** (Required for functionality)
---
### 4. MongoDB Credentials Use Environment Variables (GOOD)
**Severity:** ✅ **LOW** (Best Practice Followed)
**File:** `nodes/heimdall/core/compose.yaml` (Lines 109-110)
```yaml
# ✅ CORRECT IMPLEMENTATION
environment:
MONGO_INITDB_ROOT_USERNAME: ${KOMODO_DATABASE_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${KOMODO_DATABASE_PASSWORD}
```
**Assessment:**
- **Status:****SECURE** - No hardcoded credentials found
- **Verification:** Confirm `.env` file is excluded from Git (see `.gitignore` section below)
---
### 5. Traefik Cloudflare API Tokens Use Environment Variables (GOOD)
**Severity:** ✅ **LOW** (Best Practice Followed)
**File:** `nodes/heimdall/core/compose.yaml` (Lines 66-67)
```yaml
# ✅ CORRECT IMPLEMENTATION
environment:
- CLOUDFLARE_DNS_API_TOKEN=${CF_API_TOKEN}
- CLOUDFLARE_ZONE_API_TOKEN=${CF_ZONE_TOKEN}
```
**Assessment:**
- **Status:****SECURE** - No hardcoded tokens found
- **Recommendation:** Rotate Cloudflare API tokens quarterly
---
## 🔒 Secret Management Options for This Environment
### Current State: Komodo UI Environment Variables
**How It Works:**
1. Define placeholders in `compose.yaml`: `${VARIABLE_NAME}`
2. Store actual secrets in Komodo UI → Stack → Environment Variables
3. Komodo injects secrets at container runtime
**Pros:**
- ✅ Simple to configure via web UI
- ✅ Secrets not committed to Git
- ✅ Supports per-stack secret isolation
**Cons:**
- ⚠️ No centralized secret rotation
- ⚠️ Manual backup of secrets required
- ⚠️ No audit trail for secret access
---
### Recommended Enhancements
#### Option 1: `.env` File (Quick Win)
**Implementation:**
1. Create `.env` file in stack directory:
```bash
# /nodes/heimdall/core/.env
CF_API_TOKEN=your_cloudflare_api_token_here
CF_ZONE_TOKEN=your_zone_token_here
KOMODO_DATABASE_USERNAME=komodo_admin
KOMODO_DATABASE_PASSWORD=strong_random_password_here
KOMODO_ONBOARDING_KEY_HEIMDALL=onboarding_key_here
REDIS_PASSWORD=another_strong_password
```
2. Update `compose.yaml`:
```yaml
services:
komodo-core:
env_file: .env
# Individual environment vars still supported
```
3. **Critical:** Add to `.gitignore`:
```bash
# Create/update .gitignore at repository root
echo "**/.env" >> .gitignore
echo "**/*.env" >> .gitignore
git add .gitignore
git commit -m "chore(security): prevent .env file commits"
```
**Pros:**
- ✅ Quick to implement
- ✅ Standard Docker Compose pattern
- ✅ Easy to backup (manual copy)
**Cons:**
- ⚠️ File must exist on host (NFS or local)
- ⚠️ No encryption at rest
- ⚠️ Risk of accidental Git commit
---
#### Option 2: Docker Secrets (Recommended for Production)
**Implementation:**
1. Create secrets on each node:
```bash
# On Heimdall
echo "your_cloudflare_token" | docker secret create cf_api_token -
echo "your_database_password" | docker secret create komodo_db_password -
```
2. Update `compose.yaml`:
```yaml
services:
traefik:
secrets:
- cf_api_token
environment:
- CLOUDFLARE_DNS_API_TOKEN_FILE=/run/secrets/cf_api_token
secrets:
cf_api_token:
external: true
```
**Pros:**
- ✅ Encrypted at rest and in transit
- ✅ Native Docker Swarm integration
- ✅ Secret rotation without container restart
**Cons:**
- ⚠️ Requires Docker Swarm mode (or transition to Kubernetes)
- ⚠️ More complex to configure
- ⚠️ May not integrate seamlessly with Komodo
---
#### Option 3: HashiCorp Vault (Enterprise-Grade)
**Implementation:**
1. Deploy Vault container:
```yaml
vault:
image: hashicorp/vault:latest
ports:
- "8200:8200"
environment:
- VAULT_DEV_ROOT_TOKEN_ID=myroot # CHANGE THIS
```
2. Store secrets in Vault:
```bash
vault kv put secret/homelab/cloudflare api_token=xxx zone_token=yyy
```
3. Use Vault Agent for injection or API calls in startup scripts
**Pros:**
- ✅ Centralized secret management
- ✅ Audit logging and access control
- ✅ Automatic secret rotation
- ✅ Encryption at rest
**Cons:**
- ⚠️ Significant operational overhead
- ⚠️ Requires learning curve
- ⚠️ Another service to maintain
---
#### Option 4: Ansible Vault (Hybrid Approach)
**Implementation:**
1. Encrypt variables file:
```bash
ansible-vault create ansible/vars/secrets.yml
```
2. Store secrets:
```yaml
# ansible/vars/secrets.yml (encrypted)
cf_api_token: your_token_here
plex_claim: your_claim_here
```
3. Deploy with Ansible playbook:
```bash
ansible-playbook -i hosts deploy.yml --ask-vault-pass
```
**Pros:**
- ✅ Works with existing `ansible/` directory structure
- ✅ Encrypted at rest (AES-256)
- ✅ Can commit encrypted file to Git safely
**Cons:**
- ⚠️ Requires Ansible expertise
- ⚠️ Not integrated with Komodo workflow
- ⚠️ Manual decryption for ad-hoc changes
---
## 📋 Recommended Action Plan
### Immediate Actions (Within 24 Hours)
| Priority | Action | Effort | Impact |
|----------|--------|--------|--------|
| 🔴 **CRITICAL** | Remove hardcoded PLEX_CLAIM from Git | 15 min | HIGH |
| 🔴 **CRITICAL** | Create `.gitignore` to prevent `.env` commits | 5 min | HIGH |
| 🟡 **HIGH** | Remove Redis public port binding OR add authentication | 10 min | MEDIUM |
| 🟡 **HIGH** | Audit all compose files for other hardcoded secrets | 30 min | MEDIUM |
### Short-Term Actions (Within 1 Week)
| Priority | Action | Effort | Impact |
|----------|--------|--------|--------|
| 🟡 **MEDIUM** | Standardize on `.env` files for all stacks | 2 hours | MEDIUM |
| 🟡 **MEDIUM** | Document secret rotation procedures in SOP | 1 hour | MEDIUM |
| 🟢 **LOW** | Set calendar reminder for quarterly API token rotation | 5 min | LOW |
### Long-Term Actions (Optional)
| Priority | Action | Effort | Impact |
|----------|--------|--------|--------|
| 🟢 **LOW** | Evaluate Docker Secrets vs. Vault for centralized management | 4 hours | HIGH |
| 🟢 **LOW** | Implement automated secret scanning in CI/CD pipeline | 3 hours | MEDIUM |
---
## 🛡️ Security Best Practices Checklist
### ✅ Already Implemented
- [x] Most services use environment variable placeholders (`${VAR_NAME}`)
- [x] Komodo UI used for secret injection at runtime
- [x] Docker socket access mediated through proxy (not direct mount)
- [x] Traefik handles SSL termination with Cloudflare DNS challenge
- [x] Network segmentation via Docker networks (`proxy-net`)
### ⏳ Needs Implementation
- [ ] `.gitignore` configured to exclude `.env` files
- [ ] All hardcoded secrets removed from compose files
- [ ] Redis authentication enabled or port binding removed
- [ ] Secret rotation schedule documented
- [ ] Backup strategy for Komodo-stored environment variables
### 🔮 Future Enhancements
- [ ] Centralized secret management (Vault or similar)
- [ ] Automated secret scanning (pre-commit hooks)
- [ ] Audit logging for sensitive operations
- [ ] Encrypted backups of configuration data
---
## 📚 Related Documentation
- [SOP-001: Migrate Stack from UI to Git](SOPs/SOP-001-Migrate-Stack-from-UI-to-Git.md) - Section on Secrets Management
- [TECHNICAL_RUNBOOK.md](TECHNICAL_RUNBOOK.md) - Credential Management section
- [Repository Memory: Active Tasks](/memories/repo/active-tasks.md)
---
## 🔍 Audit Methodology
**Scan Coverage:**
- ✅ All `compose.yaml` files in `nodes/` directory
- ✅ Documentation files for exposed patterns
- ✅ README files for accidental credential leakage
- ✅ Repository structure for `.env` or secret files
**Tools Used:**
- Pattern matching for common secret keywords: `password|token|secret|api_key|claim`
- Manual inspection of environment variable usage
- Cross-reference with Komodo UI documentation
**Exclusions:**
- Scripts directory (no compose files found)
- Ansible directory (no active playbooks with secrets)
---
**Report Version:** 1.0
**Next Review Date:** July 12, 2026 (Quarterly)
**Validation Status:** Ready for Implementation ✅