Secure Your Kubernetes Apps with a Self-Signed Certificate.

Create self-signed SSL certificates with OpenSSL, configure SAN, store in Kubernetes secrets, and set up Ingress TLS for AKS & EKS clusters.
SSL/TLS Certificates in Kubernetes: Complete Guide for AKS & EKS | Self-Signed Certificates

SSL/TLS certificates are essential for encrypted communication between clients and services, ensuring secure data transmission by upgrading connections from HTTP to HTTPS. Self-signed certificates are unsuitable for public-facing production environments but are ideal for testing or internal use within corporate Kubernetes clusters.

Using HTTPS in Kubernetes (AKS/EKS) is essential for:

  • Securing traffic between clients and services
  • Preventing man-in-the-middle (MITM) attacks
  • Ensuring data integrity and confidentiality
  • Meeting compliance requirements (PCI-DSS, HIPAA, etc.)

I have tested this on AKS and EKS, but the concepts apply to all Kubernetes environments including GKE, OpenShift, and self-managed clusters.

Contents
1. Generating a Self-Signed Certificate Using OpenSSL

(i) Install OpenSSL Library

Ensure that OpenSSL is installed before proceeding.

# For Ubuntu/Debian
sudo apt-get update && sudo apt-get install openssl -y

# For RHEL/CentOS/Fedora
sudo yum install openssl -y

# For macOS
brew install openssl

# Verify installation
openssl version
(ii) Generate an Encrypted Private Key
openssl genrsa -des3 -out domain.key 2048

Command breakdown:

  • genrsa: Generates an RSA private key
  • -des3: Encrypts the private key with Triple-DES encryption
  • -out domain.key: Saves the private key to a file named domain.key
  • 2048: Specifies a key length of 2048 bits (recommended for strong encryption)
(iii) Create OpenSSL Configuration File

Create a configuration file (openssl.cnf) with the necessary certificate details:

[ req ]
default_md = sha256
prompt = no
req_extensions = req_ext
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
C = IN
ST = Gujarat
L = Ahmedabad
O = YourOrganization
OU = DevOps
CN = ui-myapp
emailAddress = admin@yourcompany.com

[ req_ext ]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[ alt_names ]
IP.0 = 10.20.30.40
DNS.0 = ui.myapp.com
DNS.1 = www.ui.myapp.com

Important: The IP field is optional. If specified, you can access the service via IP (e.g., https://10.20.30.40). Use a unique CN for different subdomains to easily identify applications (e.g., ui-myapp, api-myapp).

(iv) Create Certificate Signing Request (CSR)
# Generate CSR using the config file
openssl req -key domain.key -new -out domain.csr -config openssl.cnf

# Verify the CSR content
openssl req -text -noout -verify -in domain.csr
(v) Generate Self-Signed Certificate

For self-signed certificates (development/testing):

# Generate self-signed certificate valid for 365 days
openssl x509 -req -days 365 -in domain.csr -signkey domain.key -out domain.crt -extensions req_ext -extfile openssl.cnf

# Remove passphrase from key (optional, for Kubernetes)
openssl rsa -in domain.key -out domain-unencrypted.key

For production environments, submit the CSR to a trusted Certificate Authority (CA) like DigiCert, or your internal PKI.

2. Understanding Subject Alternative Name (SAN)

The Subject Alternative Name (SAN) extension is a critical component of modern SSL/TLS certificates. It allows a single certificate to secure multiple domain names and IP addresses.

Why is SAN Important?
  • Multi-Domain Support: Secure multiple domains (e.g., myapp.com, www.myapp.com, api.myapp.com) with one certificate
  • Browser Compatibility: Modern browsers (Chrome 58+) primarily use SAN for validation, ignoring the CN field
  • Cost Efficiency: Reduce certificate management overhead by using fewer certificates
  • Microservices Ready: Perfect for Kubernetes where services have multiple endpoints
  • IP Address Support: Include IP addresses for direct IP-based access
SAN vs Common Name (CN)
Aspect Common Name (CN) Subject Alternative Name (SAN)
Domain Support Single domain only Multiple domains and IPs
Browser Support Deprecated for validation Primary validation method
Wildcard Support Yes Yes (per entry)
IP Address Not supported Fully supported
SAN Configuration Example
[ alt_names ]
# DNS entries for domain names
DNS.0 = myapp.com
DNS.1 = www.myapp.com
DNS.2 = api.myapp.com
DNS.3 = *.staging.myapp.com    # Wildcard for staging subdomains

# IP addresses (useful for internal services)
IP.0 = 10.0.0.100              # Internal load balancer IP
IP.1 = 192.168.1.50            # Development server IP

Best Practice: Always include both the bare domain (myapp.com) and www subdomain (www.myapp.com) in your SAN entries to avoid certificate mismatch errors.

3. Creating a Kubernetes Secret to Store the Certificate

Kubernetes uses Secrets to store sensitive data like TLS certificates. There are multiple ways to create TLS secrets:

Method 1: Using kubectl (Recommended)
# Create TLS secret directly from certificate files
kubectl create secret tls my-tls-secret \
  --cert=domain.crt \
  --key=domain-unencrypted.key \
  --namespace=your-namespace

# Verify the secret was created
kubectl get secret my-tls-secret -n your-namespace
kubectl describe secret my-tls-secret -n your-namespace
Method 2: Using YAML Manifest (Base64 Encoded)

First, convert your certificate and key to base64:

# Encode certificate and key to base64
base64 -w 0 domain.crt > domain.crt.b64
base64 -w 0 domain-unencrypted.key > domain.key.b64

Create the secret manifest (tls-secret.yaml):

apiVersion: v1
kind: Secret
metadata:
  name: my-tls-secret
  namespace: your-namespace
type: kubernetes.io/tls
data:
  tls.crt: <base64-encoded-certificate>
  tls.key: <base64-encoded-key>

Apply the manifest:

kubectl apply -f tls-secret.yaml

Security Warning: Never use online base64 tools for encoding certificates and private keys. Always use local command-line tools to protect sensitive data.

4. Configuring an Ingress Controller with TLS

Ingress controllers manage external access to services in a Kubernetes cluster and can terminate TLS connections. Create an Ingress resource (ingress-tls.yaml) that uses your TLS secret:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  namespace: your-namespace
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - ui.myapp.com
        - api.myapp.com
      secretName: my-tls-secret
  rules:
    - host: ui.myapp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: ui-service
                port:
                  number: 80
    - host: api.myapp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080

Apply the Ingress:

kubectl apply -f ingress-tls.yaml

Note: The TLS secret must exist in the same namespace as your Ingress resource. The ssl-redirect annotation automatically redirects HTTP traffic to HTTPS.

Conclusion

Securing your Kubernetes applications with SSL/TLS certificates is essential for protecting data in transit. Key takeaways:

  • Use SAN (Subject Alternative Name) to support multiple domains with a single certificate
  • Store certificates securely in Kubernetes Secrets
  • Configure Ingress controllers to terminate TLS at the edge

Self-signed certificates are ideal for development, testing, and internal corporate environments. For public-facing production, consider using trusted Certificate Authorities.

Post a Comment