When implementing multi-tenant architectures with user-specific subdomains (e.g., user1.mysite.com
), developers often use wildcard SSL certificates (*.mysite.com) for HTTPS coverage. The critical question arises when users bring their own domains via CNAME records (e.g., user-brand.com
pointing to user1.mysite.com
).
Wildcard certificates only cover domains exactly matching their pattern. A certificate for *.test.com won't validate custom-domain.com
even if it CNAMEs to mysite.test.com
. The SSL/TLS handshake validates against the requested domain's name in the SNI field, not the resolved CNAME target.
Here are three approaches with code examples:
1. SAN Certificates
Use Subject Alternative Name certificates covering both wildcard and custom domains:
# OpenSSL config for SAN cert [ req ] distinguished_name = req_distinguished_name req_extensions = v3_req [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [ alt_names ] DNS.1 = *.test.com DNS.2 = custom-domain1.com DNS.3 = custom-domain2.com
2. Reverse Proxy with SNI Routing
Nginx example routing different domains to same backend:
server { listen 443 ssl; server_name custom-domain.com; ssl_certificate /path/to/custom-domain.crt; ssl_certificate_key /path/to/custom-domain.key; location / { proxy_pass https://user1.test.com; } }
3. Automated Certificate Management
Using Let's Encrypt with DNS challenges for dynamic domains:
# Certbot with DNS plugin certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \ -d custom-domain.com \ --preferred-challenges dns-01
Each solution has trade-offs:
- SAN certs: Single cert management but requires reissuing for new domains
- Reverse proxy: Added latency (~5-15ms per hop)
- Automated certs: Requires DNS API access and has rate limits
Always:
- Set proper certificate transparency logs
- Implement HSTS with includeSubDomains
- Rotate certificates at least quarterly
When implementing multi-tenant SaaS architectures, developers often face domain management challenges. A common pattern is:
1. Primary domain: test.com
2. User subdomains: user1.test.com (covered by *.test.com wildcard SSL)
3. Custom CNAMEs: customer.com → user1.test.com
The SSL/TLS handshake occurs before any HTTP redirection takes place. When a client connects to customer.com:
- Server presents certificate for *.test.com
- Browser verifies certificate against customer.com
- Mismatch triggers security warning
Here are three approaches with their implementation details:
Option 1: Subject Alternative Names (SAN)
openssl req -new -key domain.key \
-subj "/CN=test.com" \
-reqexts SAN \
-config <(cat /etc/ssl/openssl.cnf \
<(printf "[SAN]\nsubjectAltName=DNS:customer.com,DNS:client2.org")) \
-out domain.csr
Option 2: Reverse Proxy Configuration
Nginx example for CNAME handling:
server {
listen 443 ssl;
server_name customer.com;
ssl_certificate /path/to/custom.crt;
ssl_certificate_key /path/to/custom.key;
location / {
proxy_pass https://user1.test.com;
proxy_set_header Host $host;
}
}
Option 3: DNS-Level Solutions
For AWS Route 53 users:
resource "aws_route53_record" "alias" {
zone_id = aws_route53_zone.primary.zone_id
name = "customer.com"
type = "A"
alias {
name = "d123.cloudfront.net"
zone_id = "Z2FDTNDATAQYW2"
evaluate_target_health = false
}
}
Important factors to evaluate:
- Certificate validation time (DV vs OV vs EV)
- CDN compatibility (CloudFront, Cloudflare, Fastly)
- Automated certificate rotation processes
- HTTP/2 and HTTP/3 implications
Sample Prometheus alert for certificate expiration:
- alert: SSLCertExpirySoon
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30
for: 5m
labels:
severity: critical
annotations:
summary: "SSL certificate will expire soon (instance {{ $labels.instance }})"
description: "SSL certificate for {{ $labels.instance }} expires in {{ $value | humanizeDuration }}"