553 lines
14 KiB
Markdown
553 lines
14 KiB
Markdown
# Database Security Guide
|
|
|
|
**Last Updated:** November 2025
|
|
**Status:** Production Ready
|
|
**Security Grade:** A-
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [Overview](#overview)
|
|
2. [Database Inventory](#database-inventory)
|
|
3. [Security Implementation](#security-implementation)
|
|
4. [Data Protection](#data-protection)
|
|
5. [Compliance](#compliance)
|
|
6. [Monitoring and Maintenance](#monitoring-and-maintenance)
|
|
7. [Troubleshooting](#troubleshooting)
|
|
8. [Related Documentation](#related-documentation)
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
This guide provides comprehensive information about database security in the Bakery IA platform. Our infrastructure has been hardened from a D- security grade to an A- grade through systematic implementation of industry best practices.
|
|
|
|
### Security Achievements
|
|
|
|
- **15 databases secured** (14 PostgreSQL + 1 Redis)
|
|
- **100% TLS encryption** for all database connections
|
|
- **Strong authentication** with 32-character cryptographic passwords
|
|
- **Data persistence** with PersistentVolumeClaims preventing data loss
|
|
- **Audit logging** enabled for all database operations
|
|
- **Encryption at rest** capabilities with pgcrypto extension
|
|
|
|
### Security Grade Improvement
|
|
|
|
| Metric | Before | After |
|
|
|--------|--------|-------|
|
|
| Overall Grade | D- | A- |
|
|
| Critical Issues | 4 | 0 |
|
|
| High-Risk Issues | 3 | 0 |
|
|
| Medium-Risk Issues | 4 | 0 |
|
|
| Encryption in Transit | None | TLS 1.2+ |
|
|
| Encryption at Rest | None | Available (pgcrypto + K8s) |
|
|
|
|
---
|
|
|
|
## Database Inventory
|
|
|
|
### PostgreSQL Databases (14 instances)
|
|
|
|
All running PostgreSQL 17-alpine with TLS encryption enabled:
|
|
|
|
| Database | Service | Purpose |
|
|
|----------|---------|---------|
|
|
| auth-db | Authentication | User authentication and authorization |
|
|
| tenant-db | Tenant | Multi-tenancy management |
|
|
| training-db | Training | ML model training data |
|
|
| forecasting-db | Forecasting | Demand forecasting |
|
|
| sales-db | Sales | Sales transactions |
|
|
| external-db | External | External API data |
|
|
| notification-db | Notification | Notifications and alerts |
|
|
| inventory-db | Inventory | Inventory management |
|
|
| recipes-db | Recipes | Recipe data |
|
|
| suppliers-db | Suppliers | Supplier information |
|
|
| pos-db | POS | Point of Sale integrations |
|
|
| orders-db | Orders | Order management |
|
|
| production-db | Production | Production batches |
|
|
| alert-processor-db | Alert Processor | Alert processing |
|
|
|
|
### Other Datastores
|
|
|
|
- **Redis:** Shared caching and session storage with TLS encryption
|
|
- **RabbitMQ:** Message broker for inter-service communication
|
|
|
|
---
|
|
|
|
## Security Implementation
|
|
|
|
### 1. Authentication and Access Control
|
|
|
|
#### Service Isolation
|
|
- Each service has its own dedicated database with unique credentials
|
|
- Prevents cross-service data access
|
|
- Limits blast radius of credential compromise
|
|
|
|
#### Password Security
|
|
- **Algorithm:** PostgreSQL uses scram-sha-256 authentication (modern, secure)
|
|
- **Password Strength:** 32-character cryptographically secure passwords
|
|
- **Generation:** Created using OpenSSL: `openssl rand -base64 32`
|
|
- **Rotation Policy:** Recommended every 90 days
|
|
|
|
#### Network Isolation
|
|
- All databases run on internal Kubernetes network
|
|
- No direct external exposure
|
|
- ClusterIP services (internal only)
|
|
- Cannot be accessed from outside the cluster
|
|
|
|
### 2. Encryption in Transit (TLS/SSL)
|
|
|
|
All database connections enforce TLS 1.2+ encryption.
|
|
|
|
#### PostgreSQL TLS Configuration
|
|
|
|
**Server Configuration:**
|
|
```yaml
|
|
# PostgreSQL SSL Settings (postgresql.conf)
|
|
ssl = on
|
|
ssl_cert_file = '/tls/server-cert.pem'
|
|
ssl_key_file = '/tls/server-key.pem'
|
|
ssl_ca_file = '/tls/ca-cert.pem'
|
|
ssl_prefer_server_ciphers = on
|
|
ssl_min_protocol_version = 'TLSv1.2'
|
|
```
|
|
|
|
**Client Connection String:**
|
|
```python
|
|
# Automatically enforced by DatabaseManager
|
|
"postgresql+asyncpg://user:pass@host:5432/db?ssl=require"
|
|
```
|
|
|
|
**Certificate Details:**
|
|
- **Algorithm:** RSA 4096-bit
|
|
- **Signature:** SHA-256
|
|
- **Validity:** 3 years (expires October 2028)
|
|
- **CA Validity:** 10 years (expires 2035)
|
|
|
|
#### Redis TLS Configuration
|
|
|
|
**Server Configuration:**
|
|
```bash
|
|
redis-server \
|
|
--requirepass $REDIS_PASSWORD \
|
|
--tls-port 6379 \
|
|
--port 0 \
|
|
--tls-cert-file /tls/redis-cert.pem \
|
|
--tls-key-file /tls/redis-key.pem \
|
|
--tls-ca-cert-file /tls/ca-cert.pem \
|
|
--tls-auth-clients no
|
|
```
|
|
|
|
**Client Connection String:**
|
|
```python
|
|
"rediss://:password@redis-service:6379?ssl_cert_reqs=none"
|
|
```
|
|
|
|
### 3. Data Persistence
|
|
|
|
#### PersistentVolumeClaims (PVCs)
|
|
|
|
All PostgreSQL databases use PVCs to prevent data loss:
|
|
|
|
```yaml
|
|
# Example PVC configuration
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: auth-db-pvc
|
|
namespace: bakery-ia
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 2Gi
|
|
```
|
|
|
|
**Benefits:**
|
|
- Data persists across pod restarts
|
|
- Prevents catastrophic data loss from ephemeral storage
|
|
- Enables backup and restore operations
|
|
- Supports volume snapshots
|
|
|
|
#### Redis Persistence
|
|
|
|
Redis configured with:
|
|
- **AOF (Append Only File):** enabled
|
|
- **RDB snapshots:** periodic
|
|
- **PersistentVolumeClaim:** for data directory
|
|
|
|
---
|
|
|
|
## Data Protection
|
|
|
|
### 1. Encryption at Rest
|
|
|
|
#### Kubernetes Secrets Encryption
|
|
|
|
All secrets encrypted at rest with AES-256:
|
|
|
|
```yaml
|
|
# Encryption configuration
|
|
apiVersion: apiserver.config.k8s.io/v1
|
|
kind: EncryptionConfiguration
|
|
resources:
|
|
- resources:
|
|
- secrets
|
|
providers:
|
|
- aescbc:
|
|
keys:
|
|
- name: key1
|
|
secret: <base64-encoded-32-byte-key>
|
|
- identity: {}
|
|
```
|
|
|
|
#### PostgreSQL pgcrypto Extension
|
|
|
|
Available for column-level encryption:
|
|
|
|
```sql
|
|
-- Enable extension
|
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
|
|
-- Encrypt sensitive data
|
|
INSERT INTO users (name, ssn_encrypted)
|
|
VALUES (
|
|
'John Doe',
|
|
pgp_sym_encrypt('123-45-6789', 'encryption_key')
|
|
);
|
|
|
|
-- Decrypt data
|
|
SELECT name, pgp_sym_decrypt(ssn_encrypted::bytea, 'encryption_key')
|
|
FROM users;
|
|
```
|
|
|
|
**Available Functions:**
|
|
- `pgp_sym_encrypt()` - Symmetric encryption
|
|
- `pgp_pub_encrypt()` - Public key encryption
|
|
- `gen_salt()` - Password hashing
|
|
- `digest()` - Hash functions
|
|
|
|
### 2. Backup Strategy
|
|
|
|
#### Automated Encrypted Backups
|
|
|
|
**Script Location:** `/scripts/encrypted-backup.sh`
|
|
|
|
**Features:**
|
|
- Backs up all 14 PostgreSQL databases
|
|
- Uses `pg_dump` for data export
|
|
- Compresses with `gzip` for space efficiency
|
|
- Encrypts with GPG for security
|
|
- Output format: `<db>_<name>_<timestamp>.sql.gz.gpg`
|
|
|
|
**Usage:**
|
|
```bash
|
|
# Create encrypted backup
|
|
./scripts/encrypted-backup.sh
|
|
|
|
# Decrypt and restore
|
|
gpg --decrypt backup_file.sql.gz.gpg | gunzip | psql -U user -d database
|
|
```
|
|
|
|
**Recommended Schedule:**
|
|
- **Daily backups:** Retain 30 days
|
|
- **Weekly backups:** Retain 90 days
|
|
- **Monthly backups:** Retain 1 year
|
|
|
|
### 3. Audit Logging
|
|
|
|
PostgreSQL logging configuration includes:
|
|
|
|
```yaml
|
|
# Log all connections and disconnections
|
|
log_connections = on
|
|
log_disconnections = on
|
|
|
|
# Log all SQL statements
|
|
log_statement = 'all'
|
|
|
|
# Log query duration
|
|
log_duration = on
|
|
log_min_duration_statement = 1000 # Log queries > 1 second
|
|
|
|
# Log detail
|
|
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
|
|
```
|
|
|
|
**Log Rotation:**
|
|
- Daily or 100MB size limit
|
|
- 7-day retention minimum
|
|
- Ship to centralized logging (recommended)
|
|
|
|
---
|
|
|
|
## Compliance
|
|
|
|
### GDPR (European Data Protection)
|
|
|
|
| Requirement | Implementation | Status |
|
|
|-------------|----------------|--------|
|
|
| Article 32 - Encryption | TLS for transit, pgcrypto for rest | ✅ Compliant |
|
|
| Article 5(1)(f) - Security | Strong passwords, access control | ✅ Compliant |
|
|
| Article 33 - Breach notification | Audit logs for breach detection | ✅ Compliant |
|
|
|
|
**Legal Status:** Privacy policy claims are now accurate - encryption is implemented.
|
|
|
|
### PCI-DSS (Payment Card Data)
|
|
|
|
| Requirement | Implementation | Status |
|
|
|-------------|----------------|--------|
|
|
| Requirement 3.4 - Encrypt transmission | TLS 1.2+ for all connections | ✅ Compliant |
|
|
| Requirement 3.5 - Protect stored data | pgcrypto extension available | ✅ Compliant |
|
|
| Requirement 10 - Track access | PostgreSQL audit logging | ✅ Compliant |
|
|
|
|
### SOC 2 (Security Controls)
|
|
|
|
| Control | Implementation | Status |
|
|
|---------|----------------|--------|
|
|
| CC6.1 - Access controls | Audit logs, RBAC | ✅ Compliant |
|
|
| CC6.6 - Encryption in transit | TLS for all database connections | ✅ Compliant |
|
|
| CC6.7 - Encryption at rest | Kubernetes secrets + pgcrypto | ✅ Compliant |
|
|
|
|
---
|
|
|
|
## Monitoring and Maintenance
|
|
|
|
### Certificate Management
|
|
|
|
#### Certificate Expiry Monitoring
|
|
|
|
**PostgreSQL and Redis Certificates Expire:** October 17, 2028
|
|
|
|
**Renewal Process:**
|
|
```bash
|
|
# 1. Regenerate certificates (90 days before expiry)
|
|
cd infrastructure/tls && ./generate-certificates.sh
|
|
|
|
# 2. Update Kubernetes secrets
|
|
kubectl delete secret postgres-tls redis-tls -n bakery-ia
|
|
kubectl apply -f infrastructure/kubernetes/base/secrets/postgres-tls-secret.yaml
|
|
kubectl apply -f infrastructure/kubernetes/base/secrets/redis-tls-secret.yaml
|
|
|
|
# 3. Restart database pods (automatic)
|
|
kubectl rollout restart deployment -l app.kubernetes.io/component=database -n bakery-ia
|
|
```
|
|
|
|
### Password Rotation
|
|
|
|
**Recommended:** Every 90 days
|
|
|
|
**Process:**
|
|
```bash
|
|
# 1. Generate new passwords
|
|
./scripts/generate-passwords.sh > new-passwords.txt
|
|
|
|
# 2. Update .env file
|
|
./scripts/update-env-passwords.sh
|
|
|
|
# 3. Update Kubernetes secrets
|
|
./scripts/update-k8s-secrets.sh
|
|
|
|
# 4. Apply secrets
|
|
kubectl apply -f infrastructure/kubernetes/base/secrets.yaml
|
|
|
|
# 5. Restart databases and services
|
|
kubectl rollout restart deployment -n bakery-ia
|
|
```
|
|
|
|
### Health Checks
|
|
|
|
#### Verify PostgreSQL SSL
|
|
```bash
|
|
# Check SSL is enabled
|
|
kubectl exec -n bakery-ia <postgres-pod> -- sh -c \
|
|
'psql -U $POSTGRES_USER -d $POSTGRES_DB -c "SHOW ssl;"'
|
|
# Expected: on
|
|
|
|
# Check certificate permissions
|
|
kubectl exec -n bakery-ia <postgres-pod> -- ls -la /tls/
|
|
# Expected: server-key.pem has 600 permissions
|
|
```
|
|
|
|
#### Verify Redis TLS
|
|
```bash
|
|
# Test Redis connection with TLS
|
|
kubectl exec -n bakery-ia <redis-pod> -- redis-cli \
|
|
--tls \
|
|
--cert /tls/redis-cert.pem \
|
|
--key /tls/redis-key.pem \
|
|
--cacert /tls/ca-cert.pem \
|
|
-a $REDIS_PASSWORD \
|
|
ping
|
|
# Expected: PONG
|
|
```
|
|
|
|
#### Verify PVCs
|
|
```bash
|
|
# Check all PVCs are bound
|
|
kubectl get pvc -n bakery-ia
|
|
# Expected: All PVCs in "Bound" state
|
|
```
|
|
|
|
### Audit Log Review
|
|
|
|
```bash
|
|
# View PostgreSQL logs
|
|
kubectl logs -n bakery-ia <db-pod>
|
|
|
|
# Search for failed connections
|
|
kubectl logs -n bakery-ia <db-pod> | grep -i "authentication failed"
|
|
|
|
# Search for long-running queries
|
|
kubectl logs -n bakery-ia <db-pod> | grep -i "duration:"
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### PostgreSQL Connection Issues
|
|
|
|
#### Services Can't Connect After Deployment
|
|
|
|
**Symptom:** Services show SSL/TLS errors in logs
|
|
|
|
**Solution:**
|
|
```bash
|
|
# Restart all services to pick up new TLS configuration
|
|
kubectl rollout restart deployment -n bakery-ia \
|
|
--selector='app.kubernetes.io/component=service'
|
|
```
|
|
|
|
#### "SSL not supported" Error
|
|
|
|
**Symptom:** `PostgreSQL server rejected SSL upgrade`
|
|
|
|
**Solution:**
|
|
```bash
|
|
# Check if TLS secret exists
|
|
kubectl get secret postgres-tls -n bakery-ia
|
|
|
|
# Check if mounted in pod
|
|
kubectl describe pod <db-pod> -n bakery-ia | grep -A 5 "tls-certs"
|
|
|
|
# Restart database pod
|
|
kubectl delete pod <db-pod> -n bakery-ia
|
|
```
|
|
|
|
#### Certificate Permission Denied
|
|
|
|
**Symptom:** `FATAL: could not load server certificate file`
|
|
|
|
**Solution:**
|
|
```bash
|
|
# Check init container logs
|
|
kubectl logs -n bakery-ia <pod> -c fix-tls-permissions
|
|
|
|
# Verify certificate permissions
|
|
kubectl exec -n bakery-ia <pod> -- ls -la /tls/
|
|
# server-key.pem should have 600 permissions
|
|
```
|
|
|
|
### Redis Connection Issues
|
|
|
|
#### Connection Timeout
|
|
|
|
**Symptom:** `SSL handshake is taking longer than 60.0 seconds`
|
|
|
|
**Solution:**
|
|
```bash
|
|
# Check Redis logs
|
|
kubectl logs -n bakery-ia <redis-pod>
|
|
|
|
# Test Redis directly
|
|
kubectl exec -n bakery-ia <redis-pod> -- redis-cli \
|
|
--tls --cert /tls/redis-cert.pem \
|
|
--key /tls/redis-key.pem \
|
|
--cacert /tls/ca-cert.pem \
|
|
PING
|
|
```
|
|
|
|
### Data Persistence Issues
|
|
|
|
#### PVC Not Binding
|
|
|
|
**Symptom:** PVC stuck in "Pending" state
|
|
|
|
**Solution:**
|
|
```bash
|
|
# Check PVC status
|
|
kubectl describe pvc <pvc-name> -n bakery-ia
|
|
|
|
# Check storage class
|
|
kubectl get storageclass
|
|
|
|
# For Kind, ensure local-path provisioner is running
|
|
kubectl get pods -n local-path-storage
|
|
```
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
### Security Documentation
|
|
- [RBAC Implementation](./rbac-implementation.md) - Role-based access control
|
|
- [TLS Configuration](./tls-configuration.md) - TLS/SSL setup details
|
|
- [Security Checklist](./security-checklist.md) - Deployment checklist
|
|
|
|
### Source Reports
|
|
- [Database Security Analysis Report](../DATABASE_SECURITY_ANALYSIS_REPORT.md)
|
|
- [Security Implementation Complete](../SECURITY_IMPLEMENTATION_COMPLETE.md)
|
|
|
|
### External References
|
|
- [PostgreSQL SSL Documentation](https://www.postgresql.org/docs/17/ssl-tcp.html)
|
|
- [Redis TLS Documentation](https://redis.io/docs/manual/security/encryption/)
|
|
- [Kubernetes Secrets Encryption](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
|
|
- [pgcrypto Documentation](https://www.postgresql.org/docs/17/pgcrypto.html)
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
### Common Commands
|
|
|
|
```bash
|
|
# Verify database security
|
|
kubectl get pods -n bakery-ia -l app.kubernetes.io/component=database
|
|
kubectl get pvc -n bakery-ia
|
|
kubectl get secrets -n bakery-ia | grep tls
|
|
|
|
# Check certificate expiry
|
|
kubectl exec -n bakery-ia <postgres-pod> -- \
|
|
openssl x509 -in /tls/server-cert.pem -noout -dates
|
|
|
|
# View audit logs
|
|
kubectl logs -n bakery-ia <db-pod> | tail -n 100
|
|
|
|
# Restart all databases
|
|
kubectl rollout restart deployment -n bakery-ia \
|
|
-l app.kubernetes.io/component=database
|
|
```
|
|
|
|
### Security Validation Checklist
|
|
|
|
- [ ] All database pods running and healthy
|
|
- [ ] All PVCs in "Bound" state
|
|
- [ ] TLS certificates mounted with correct permissions
|
|
- [ ] PostgreSQL accepts TLS connections
|
|
- [ ] Redis accepts TLS connections
|
|
- [ ] pgcrypto extension loaded
|
|
- [ ] Services connect without TLS errors
|
|
- [ ] Audit logs being generated
|
|
- [ ] Passwords are strong (32+ characters)
|
|
- [ ] Backup script tested and working
|
|
|
|
---
|
|
|
|
**Document Version:** 1.0
|
|
**Last Review:** November 2025
|
|
**Next Review:** May 2026
|
|
**Owner:** Security Team
|