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.
8.6 KiB
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
# 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
# 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:
- Browser shows "Your connection is not private" or similar
- Click "Advanced" or "Show details"
- Click "Proceed to localhost" or "Accept the risk"
- Certificate warning will appear on first visit only per browser session
Option 2: Trust Certificate in System (Recommended)
On macOS:
# 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):
- Export certificate:
kubectl get secret bakery-dev-tls-cert -n bakery-ia -o jsonpath='{.data.tls\.crt}' | base64 -d > bakery-dev-cert.crt - Double-click the
.crtfile to open Keychain Access - Find "localhost" certificate
- Double-click → Trust → "Always Trust"
- Close and enter your password
On Linux:
# 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:
# 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
# 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
- Open
https://localhost - Check for SSL/TLS padlock in address bar
- Click padlock → View certificate
- Verify:
- Issued to: localhost
- Issued by: localhost (self-signed)
- Valid for: 90 days
Test Frontend
# 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
# 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:
- Click "Proceed" (quick, temporary)
- 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_URLto use HTTPS
Certificate Expired
# 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:
- Click "Advanced" → "Proceed to localhost"
- Trust the certificate (see instructions above)
- Use curl with
-kflag for testing
Disable HTTPS (Not Recommended)
If you need to temporarily disable HTTPS:
# 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
// In your frontend
document.cookie = "session=test; Secure; SameSite=Strict";
2. Mixed Content Detection
// 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)
# Check HSTS headers
curl -I https://localhost/api/health | grep -i strict
4. TLS Version Testing
# 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:
- Deploy:
skaffold dev --profile=dev - Access:
https://localhost - Trust: Follow instructions above (optional)
- Test: Verify HTTPS works
For issues, see Troubleshooting section or check cert-manager logs.