Enable HTTPS by default in development environment
This commit enables HTTPS in the development environment using self-signed certificates to further improve dev-prod parity and catch SSL-related issues early. Changes made: 1. Created self-signed certificate for localhost - File: infrastructure/kubernetes/overlays/dev/dev-certificate.yaml - Type: Self-signed via cert-manager - Validity: 90 days (auto-renewed) - Valid for: localhost, bakery-ia.local, *.bakery-ia.local, 127.0.0.1 - Issuer: selfsigned-issuer ClusterIssuer 2. Updated dev ingress to enable HTTPS - File: infrastructure/kubernetes/overlays/dev/dev-ingress.yaml - Enabled SSL redirect: ssl-redirect: false → true - Added TLS configuration with certificate - Updated CORS origins to prefer HTTPS (HTTPS URLs first, HTTP fallback) - Access: https://localhost (instead of http://localhost) 3. Added cert-manager resources to dev overlay - File: infrastructure/kubernetes/overlays/dev/kustomization.yaml - Added dev-certificate.yaml - Added selfsigned-issuer ClusterIssuer 4. Created comprehensive HTTPS setup guide - File: docs/DEV-HTTPS-SETUP.md - Includes certificate trust instructions for macOS, Linux, Windows - Testing procedures with curl and browsers - Troubleshooting guide - FAQ section 5. Updated dev-prod parity documentation - File: docs/DEV-PROD-PARITY-CHANGES.md - Added HTTPS as 4th improvement - Updated "What Stays Different" table (SSL/TLS → Certificates) - Added HTTPS benefits section Benefits: ✓ Matches production HTTPS-only behavior ✓ Tests SSL/TLS configurations in development ✓ Catches mixed content warnings early ✓ Tests secure cookie handling (Secure, SameSite attributes) ✓ Validates cert-manager integration ✓ Tests certificate auto-renewal ✓ Better security testing capabilities Impact: - Browser will show certificate warning (self-signed) - Users can trust certificate or click "Proceed" - No additional resource usage - Access via https://localhost (was http://localhost) Certificate details: - Type: Self-signed - Algorithm: RSA 2048-bit - Validity: 90 days - Auto-renewal: 15 days before expiration - Common Name: localhost - DNS Names: localhost, bakery-ia.local, *.bakery-ia.local - IP Addresses: 127.0.0.1, ::1 Setup required: - Optional: Trust certificate in system/browser (see DEV-HTTPS-SETUP.md) - Required: cert-manager must be installed in cluster - Access at: https://localhost What stays different from production: - Certificate type: Self-signed (dev) vs Let's Encrypt (prod) - Trust: Manual (dev) vs Automatic (prod) - Domain: localhost (dev) vs real domain (prod) This completes the dev-prod parity improvements, bringing development environment much closer to production with: 1. 2 replicas for critical services ✓ 2. Rate limiting enabled ✓ 3. Specific CORS origins ✓ 4. HTTPS enabled ✓ See docs/DEV-HTTPS-SETUP.md for complete setup and testing instructions.
This commit is contained in:
337
docs/DEV-HTTPS-SETUP.md
Normal file
337
docs/DEV-HTTPS-SETUP.md
Normal file
@@ -0,0 +1,337 @@
|
||||
# HTTPS in Development Environment
|
||||
|
||||
## Overview
|
||||
|
||||
Development environment now uses HTTPS by default to match production behavior and catch SSL-related issues early.
|
||||
|
||||
**Benefits:**
|
||||
- ✅ Matches production HTTPS behavior
|
||||
- ✅ Tests SSL/TLS configurations
|
||||
- ✅ Catches mixed content warnings
|
||||
- ✅ Tests secure cookie handling
|
||||
- ✅ Better dev-prod parity
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Deploy with HTTPS Enabled
|
||||
|
||||
```bash
|
||||
# Start development environment
|
||||
skaffold dev --profile=dev
|
||||
|
||||
# Wait for certificate to be issued
|
||||
kubectl get certificate -n bakery-ia
|
||||
|
||||
# You should see:
|
||||
# NAME READY SECRET AGE
|
||||
# bakery-dev-tls-cert True bakery-dev-tls-cert 1m
|
||||
```
|
||||
|
||||
### 2. Access Your Application
|
||||
|
||||
```bash
|
||||
# Access via HTTPS (will show certificate warning in browser)
|
||||
open https://localhost
|
||||
|
||||
# Or via curl (use -k to skip certificate verification)
|
||||
curl -k https://localhost/api/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Trust the Self-Signed Certificate
|
||||
|
||||
To avoid browser certificate warnings, you need to trust the self-signed certificate.
|
||||
|
||||
### Option 1: Accept Browser Warning (Quick & Easy)
|
||||
|
||||
When you visit `https://localhost`:
|
||||
1. Browser shows "Your connection is not private" or similar
|
||||
2. Click "Advanced" or "Show details"
|
||||
3. Click "Proceed to localhost" or "Accept the risk"
|
||||
4. Certificate warning will appear on first visit only per browser session
|
||||
|
||||
### Option 2: Trust Certificate in System (Recommended)
|
||||
|
||||
#### On macOS:
|
||||
|
||||
```bash
|
||||
# 1. Export the certificate from Kubernetes
|
||||
kubectl get secret bakery-dev-tls-cert -n bakery-ia -o jsonpath='{.data.tls\.crt}' | base64 -d > /tmp/bakery-dev-cert.crt
|
||||
|
||||
# 2. Add to Keychain
|
||||
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /tmp/bakery-dev-cert.crt
|
||||
|
||||
# 3. Verify
|
||||
security find-certificate -c localhost -a
|
||||
|
||||
# 4. Cleanup
|
||||
rm /tmp/bakery-dev-cert.crt
|
||||
```
|
||||
|
||||
**Alternative (GUI):**
|
||||
1. Export certificate: `kubectl get secret bakery-dev-tls-cert -n bakery-ia -o jsonpath='{.data.tls\.crt}' | base64 -d > bakery-dev-cert.crt`
|
||||
2. Double-click the `.crt` file to open Keychain Access
|
||||
3. Find "localhost" certificate
|
||||
4. Double-click → Trust → "Always Trust"
|
||||
5. Close and enter your password
|
||||
|
||||
#### On Linux:
|
||||
|
||||
```bash
|
||||
# 1. Export the certificate
|
||||
kubectl get secret bakery-dev-tls-cert -n bakery-ia -o jsonpath='{.data.tls\.crt}' | base64 -d | sudo tee /usr/local/share/ca-certificates/bakery-dev.crt
|
||||
|
||||
# 2. Update CA certificates
|
||||
sudo update-ca-certificates
|
||||
|
||||
# 3. For browsers (Chromium/Chrome)
|
||||
mkdir -p $HOME/.pki/nssdb
|
||||
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n "Bakery Dev" -i /usr/local/share/ca-certificates/bakery-dev.crt
|
||||
```
|
||||
|
||||
#### On Windows:
|
||||
|
||||
```powershell
|
||||
# 1. Export the certificate
|
||||
kubectl get secret bakery-dev-tls-cert -n bakery-ia -o jsonpath='{.data.tls.crt}' | Out-File -Encoding ASCII bakery-dev-cert.crt
|
||||
|
||||
# 2. Import to Trusted Root
|
||||
Import-Certificate -FilePath .\bakery-dev-cert.crt -CertStoreLocation Cert:\LocalMachine\Root
|
||||
|
||||
# Or use GUI:
|
||||
# - Double-click bakery-dev-cert.crt
|
||||
# - Install Certificate
|
||||
# - Store Location: Local Machine
|
||||
# - Place in: Trusted Root Certification Authorities
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing HTTPS
|
||||
|
||||
### Test with curl
|
||||
|
||||
```bash
|
||||
# Without certificate verification (quick test)
|
||||
curl -k https://localhost/api/health
|
||||
|
||||
# With certificate verification (after trusting cert)
|
||||
curl https://localhost/api/health
|
||||
|
||||
# Check certificate details
|
||||
curl -vI https://localhost/api/health 2>&1 | grep -A 10 "Server certificate"
|
||||
|
||||
# Test CORS with HTTPS
|
||||
curl -H "Origin: https://localhost:3000" \
|
||||
-H "Access-Control-Request-Method: POST" \
|
||||
-X OPTIONS https://localhost/api/health
|
||||
```
|
||||
|
||||
### Test with Browser
|
||||
|
||||
1. Open `https://localhost`
|
||||
2. Check for SSL/TLS padlock in address bar
|
||||
3. Click padlock → View certificate
|
||||
4. Verify:
|
||||
- Issued to: localhost
|
||||
- Issued by: localhost (self-signed)
|
||||
- Valid for: 90 days
|
||||
|
||||
### Test Frontend
|
||||
|
||||
```bash
|
||||
# Update your frontend .env to use HTTPS
|
||||
echo "VITE_API_URL=https://localhost/api" > frontend/.env.local
|
||||
|
||||
# Frontend should now make HTTPS requests
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Certificate Details
|
||||
|
||||
### Certificate Specifications
|
||||
|
||||
- **Type**: Self-signed (for development)
|
||||
- **Algorithm**: RSA 2048-bit
|
||||
- **Validity**: 90 days (auto-renews 15 days before expiration)
|
||||
- **Common Name**: localhost
|
||||
- **DNS Names**:
|
||||
- localhost
|
||||
- bakery-ia.local
|
||||
- api.bakery-ia.local
|
||||
- *.bakery-ia.local
|
||||
- **IP Addresses**: 127.0.0.1, ::1
|
||||
|
||||
### Certificate Issuer
|
||||
|
||||
- **Issuer**: `selfsigned-issuer` (cert-manager ClusterIssuer)
|
||||
- **Auto-renewal**: Managed by cert-manager
|
||||
- **Secret Name**: `bakery-dev-tls-cert`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Certificate Not Issued
|
||||
|
||||
```bash
|
||||
# Check certificate status
|
||||
kubectl describe certificate bakery-dev-tls-cert -n bakery-ia
|
||||
|
||||
# Check cert-manager logs
|
||||
kubectl logs -n cert-manager deployment/cert-manager
|
||||
|
||||
# Check if cert-manager is installed
|
||||
kubectl get pods -n cert-manager
|
||||
|
||||
# If cert-manager is not installed:
|
||||
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
|
||||
```
|
||||
|
||||
### Certificate Warning in Browser
|
||||
|
||||
**Normal for self-signed certificates!** Choose one:
|
||||
1. Click "Proceed" (quick, temporary)
|
||||
2. Trust the certificate in your system (permanent)
|
||||
|
||||
### Mixed Content Warnings
|
||||
|
||||
If you see "mixed content" errors:
|
||||
- Ensure all API calls use HTTPS
|
||||
- Check for hardcoded HTTP URLs
|
||||
- Update `VITE_API_URL` to use HTTPS
|
||||
|
||||
### Certificate Expired
|
||||
|
||||
```bash
|
||||
# Check expiration
|
||||
kubectl get certificate bakery-dev-tls-cert -n bakery-ia -o jsonpath='{.status.notAfter}'
|
||||
|
||||
# Force renewal
|
||||
kubectl delete certificate bakery-dev-tls-cert -n bakery-ia
|
||||
kubectl apply -k infrastructure/kubernetes/overlays/dev
|
||||
|
||||
# cert-manager will automatically recreate it
|
||||
```
|
||||
|
||||
### Browser Shows "NET::ERR_CERT_AUTHORITY_INVALID"
|
||||
|
||||
This is expected for self-signed certificates. Options:
|
||||
1. Click "Advanced" → "Proceed to localhost"
|
||||
2. Trust the certificate (see instructions above)
|
||||
3. Use curl with `-k` flag for testing
|
||||
|
||||
---
|
||||
|
||||
## Disable HTTPS (Not Recommended)
|
||||
|
||||
If you need to temporarily disable HTTPS:
|
||||
|
||||
```bash
|
||||
# Edit dev-ingress.yaml
|
||||
vim infrastructure/kubernetes/overlays/dev/dev-ingress.yaml
|
||||
|
||||
# Change:
|
||||
# nginx.ingress.kubernetes.io/ssl-redirect: "true" → "false"
|
||||
# nginx.ingress.kubernetes.io/force-ssl-redirect: "true" → "false"
|
||||
|
||||
# Comment out the tls section:
|
||||
# tls:
|
||||
# - hosts:
|
||||
# - localhost
|
||||
# secretName: bakery-dev-tls-cert
|
||||
|
||||
# Redeploy
|
||||
skaffold dev --profile=dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Differences from Production
|
||||
|
||||
| Aspect | Development | Production |
|
||||
|--------|-------------|------------|
|
||||
| Certificate Type | Self-signed | Let's Encrypt |
|
||||
| Validity | 90 days | 90 days |
|
||||
| Auto-renewal | cert-manager | cert-manager |
|
||||
| Trust | Manual trust needed | Automatically trusted |
|
||||
| Domains | localhost | Real domains |
|
||||
| Browser Warning | Yes (self-signed) | No (CA-signed) |
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
### Q: Why am I seeing certificate warnings?
|
||||
**A:** Self-signed certificates aren't trusted by browsers by default. Trust the certificate or click "Proceed."
|
||||
|
||||
### Q: Do I need to trust the certificate?
|
||||
**A:** No, but it makes development easier. You can click "Proceed" on each browser session.
|
||||
|
||||
### Q: Will this affect my frontend development?
|
||||
**A:** Slightly. Update `VITE_API_URL` to use `https://`. Otherwise works the same.
|
||||
|
||||
### Q: Can I use HTTP instead?
|
||||
**A:** Yes, but not recommended. It reduces dev-prod parity and won't catch HTTPS issues.
|
||||
|
||||
### Q: How often do I need to re-trust the certificate?
|
||||
**A:** Only when the certificate is recreated (every 90 days or when you delete the cluster).
|
||||
|
||||
### Q: Does this work with bakery-ia.local?
|
||||
**A:** Yes! The certificate is valid for both `localhost` and `bakery-ia.local`.
|
||||
|
||||
---
|
||||
|
||||
## Additional Security Testing
|
||||
|
||||
With HTTPS enabled, you can now test:
|
||||
|
||||
### 1. Secure Cookies
|
||||
```javascript
|
||||
// In your frontend
|
||||
document.cookie = "session=test; Secure; SameSite=Strict";
|
||||
```
|
||||
|
||||
### 2. Mixed Content Detection
|
||||
```javascript
|
||||
// This will show warning in dev (good - catches prod issues!)
|
||||
fetch('http://api.example.com/data') // ❌ Mixed content
|
||||
fetch('https://api.example.com/data') // ✅ Secure
|
||||
```
|
||||
|
||||
### 3. HSTS (HTTP Strict Transport Security)
|
||||
```bash
|
||||
# Check HSTS headers
|
||||
curl -I https://localhost/api/health | grep -i strict
|
||||
```
|
||||
|
||||
### 4. TLS Version Testing
|
||||
```bash
|
||||
# Test TLS 1.2
|
||||
curl --tlsv1.2 https://localhost/api/health
|
||||
|
||||
# Test TLS 1.3
|
||||
curl --tlsv1.3 https://localhost/api/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
✅ **Enabled**: HTTPS in development by default
|
||||
✅ **Certificate**: Self-signed, auto-renewed
|
||||
✅ **Access**: `https://localhost`
|
||||
✅ **Trust**: Optional but recommended
|
||||
✅ **Benefit**: Better dev-prod parity
|
||||
|
||||
**Next Steps:**
|
||||
1. Deploy: `skaffold dev --profile=dev`
|
||||
2. Access: `https://localhost`
|
||||
3. Trust: Follow instructions above (optional)
|
||||
4. Test: Verify HTTPS works
|
||||
|
||||
For issues, see Troubleshooting section or check cert-manager logs.
|
||||
Reference in New Issue
Block a user