# 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.