Appearance
Kubernetes TLS Certificate Guide
Overview
This document outlines different approaches to obtain and deploy TLS certificates for Call Telemetry webhook services running on Kubernetes. We cover two main methods:
- Automated Method: Using Let's Encrypt with cert-manager for automatic certificate issuance and renewal
- Manual Method: Generating certificates manually, either using an Enterprise CA (for production) or self-signed certificates (for testing)
This guide uses domain naming patterns like ct-teams-webhook-dev.example.com
and ct-teams-webhook-prod.example.com
for development and production environments, respectively, and demonstrates implementation in both development (ct-dev
) and production (ct-prod
) namespaces.
Namespace and Resource Naming Conventions
For clarity and consistency, we recommend using namespace prefixes for all certificate-related resources:
Environment | Namespace | Certificate Name Prefix | Secret Name Prefix |
---|---|---|---|
Development | ct-dev | ct-dev- | ct-dev- |
Production | ct-prod | ct-prod- | ct-prod- |
For example:
- Development certificate:
ct-dev-teams-webhook-tls
- Production certificate:
ct-prod-teams-webhook-tls
Method 1: Automated Certificates with Let's Encrypt
Let's Encrypt provides free, automated certificates that are trusted by all major browsers. When combined with cert-manager in Kubernetes, this provides a fully automated solution for certificate management.
Prerequisites
Requirement | Details |
---|---|
cert-manager | Installed in your Kubernetes cluster |
kubectl | Cluster admin access to the target namespace |
Public DNS record | ct-teams-webhook-prod.example.com -> public LoadBalancer/Ingress IP |
Internet access | Let's Encrypt servers must be able to reach your service for validation |
Prerequisites and Assumptions
This guide assumes:
- cert-manager is already installed in your cluster
- ClusterIssuers or Issuers are already configured via Helm charts
- You have the necessary permissions to create Certificate resources
Creating Certificate Resources
Request Certificates for Development and Production
Create Certificate resources for both environments:
Development Environment
yaml
# ct-dev-teams-webhook-cert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ct-dev-teams-webhook-tls
namespace: ct-dev
spec:
secretName: ct-dev-teams-webhook-tls
issuerRef:
name: letsencrypt-prod # This should match your pre-configured issuer
kind: ClusterIssuer
dnsNames:
- ct-teams-webhook-dev.example.com
- ct-teams-webhook.ct-dev.svc.cluster.local
Apply the development certificate request:
bash
kubectl apply -f ct-dev-teams-webhook-cert.yaml
Production Environment
yaml
# ct-prod-teams-webhook-cert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ct-prod-teams-webhook-tls
namespace: ct-prod
spec:
secretName: ct-prod-teams-webhook-tls
issuerRef:
name: letsencrypt-prod # This should match your pre-configured issuer
kind: ClusterIssuer
dnsNames:
- ct-teams-webhook-prod.example.com
- ct-teams-webhook.ct-prod.svc.cluster.local
Apply the production certificate request:
bash
kubectl apply -f ct-prod-teams-webhook-cert.yaml
Verify Certificate Status
Check if the certificates were issued successfully:
Development Environment
bash
kubectl get certificate -n ct-dev
kubectl get certificaterequest -n ct-dev
kubectl describe certificate ct-dev-teams-webhook-tls -n ct-dev
Production Environment
bash
kubectl get certificate -n ct-prod
kubectl get certificaterequest -n ct-prod
kubectl describe certificate ct-prod-teams-webhook-tls -n ct-prod
Once the certificates are issued, cert-manager will store them in the specified Secrets, which can be used by your Helm charts for Ingress or Gateway resources.
Method 2: Manual Certificate Generation
For environments where automated certificate management is not possible or when you need more control over the certificate issuance process, you can manually generate certificates.
Option A: Enterprise CA Certificates (Production)
This option is suitable for production environments where certificates need to be trusted by clients without additional configuration.
Prerequisites
Requirement | Details |
---|---|
Enterprise CA | e.g. Microsoft AD CS, DigiCert Private CA, Entrust, etc. |
openssl | Installed on a workstation, jump-box, or Kubernetes Job image |
kubectl | Cluster admin access to the target namespace |
DNS record | ct-teams-webhook-prod.example.com -> public or internal LoadBalancer/Ingress IP |
Certificate Generation Process
The following examples show how to generate certificates for both development and production environments.
Development Environment
1. Generate the Private Key & CSR
bash
# === 1.1 Private key ===
openssl genrsa -out ct-dev-teams-webhook.key 4096
# === 1.2 CSR configuration ===
cat > ct-dev-csr.conf <<'EOF'
[ req ]
default_bits = 4096
prompt = no
default_md = sha256
req_extensions = req_ext
[ req_distinguished_name ]
CN = ct-teams-webhook-dev.example.com
O = CallTelemetry
[ req_ext ]
subjectAltName = @alts
[ alts ]
DNS.1 = ct-teams-webhook-dev.example.com
DNS.2 = ct-teams-webhook.ct-dev.svc.cluster.local
EOF
# === 1.3 CSR ===
openssl req -new -key ct-dev-teams-webhook.key \
-config ct-dev-csr.conf \
-out ct-dev-teams-webhook.csr
2. Submit the CSR to the Enterprise CA
- Open your CA's enrollment portal (e.g. https://ca.example.local/certsrv/).
- Choose Request a certificate → Advanced certificate request.
- Paste the content of
ct-dev-teams-webhook.csr
. - Select a Web Server template (allows Server Auth EKU).
- Download the signed certificate—often
certnew.cer
.
3. Bundle the Certificate Chain
bash
cat ct-dev-teams-webhook.crt intermed-ca.crt enterprise-root.crt \
> ct-dev-teams-webhook.fullchain.crt
4. Create the Kubernetes TLS Secret
bash
kubectl create secret tls ct-dev-teams-webhook-tls \
--cert=ct-dev-teams-webhook.fullchain.crt \
--key=ct-dev-teams-webhook.key \
-n ct-dev
Production Environment
1. Generate the Private Key & CSR
bash
# === 1.1 Private key ===
openssl genrsa -out ct-prod-teams-webhook.key 4096
# === 1.2 CSR configuration ===
cat > ct-prod-csr.conf <<'EOF'
[ req ]
default_bits = 4096
prompt = no
default_md = sha256
req_extensions = req_ext
[ req_distinguished_name ]
CN = ct-teams-webhook-prod.example.com
O = CallTelemetry
[ req_ext ]
subjectAltName = @alts
[ alts ]
DNS.1 = ct-teams-webhook-prod.example.com
DNS.2 = ct-teams-webhook.ct-prod.svc.cluster.local
EOF
# === 1.3 CSR ===
openssl req -new -key ct-prod-teams-webhook.key \
-config ct-prod-csr.conf \
-out ct-prod-teams-webhook.csr
2. Submit the CSR to the Enterprise CA
- Open your CA's enrollment portal (e.g. https://ca.example.local/certsrv/).
- Choose Request a certificate → Advanced certificate request.
- Paste the content of
ct-prod-teams-webhook.csr
. - Select a Web Server template (allows Server Auth EKU).
- Download the signed certificate—often
certnew.cer
.
3. Bundle the Certificate Chain
bash
cat ct-prod-teams-webhook.crt intermed-ca.crt enterprise-root.crt \
> ct-prod-teams-webhook.fullchain.crt
4. Create the Kubernetes TLS Secret
bash
kubectl create secret tls ct-prod-teams-webhook-tls \
--cert=ct-prod-teams-webhook.fullchain.crt \
--key=ct-prod-teams-webhook.key \
-n ct-prod
Option B: Self-Signed Certificates (Testing/Development)
For testing or internal use, you can generate a self-signed certificate. This option is quick but requires clients to trust the certificate explicitly.
Prerequisites
Requirement | Details |
---|---|
openssl | Installed on a workstation or jump-box |
kubectl | Cluster admin access to the target namespace |
Certificate Generation Process
Development Environment
bash
# Generate private key
openssl genrsa -out ct-dev-teams-webhook.key 4096
# Create a configuration file for the certificate
cat > ct-dev-cert.conf <<'EOF'
[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
x509_extensions = v3_ca
[dn]
CN = ct-teams-webhook-dev.example.com
O = CallTelemetry
[req_ext]
subjectAltName = @alt_names
[v3_ca]
subjectAltName = @alt_names
basicConstraints = critical, CA:false
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = ct-teams-webhook-dev.example.com
DNS.2 = ct-teams-webhook.ct-dev.svc.cluster.local
EOF
# Generate self-signed certificate
openssl req -new -x509 -key ct-dev-teams-webhook.key \
-out ct-dev-teams-webhook.crt \
-config ct-dev-cert.conf \
-days 365
# Create the Kubernetes TLS Secret
kubectl create secret tls ct-dev-teams-webhook-tls \
--cert=ct-dev-teams-webhook.crt \
--key=ct-dev-teams-webhook.key \
-n ct-dev
Next Steps
After generating the certificates using either method, the resulting Kubernetes Secrets (ct-dev-teams-webhook-tls
and ct-prod-teams-webhook-tls
) will be used by your Helm charts to configure TLS for Ingress or Gateway resources. The actual usage of these certificates in Ingress or Gateway resources is handled by the Helm charts and is not covered in this document.
Certificate Renewal and Maintenance
- Let's Encrypt: cert-manager automatically renews certificates before they expire (every 90 days)
- Enterprise CA: Manually renew before expiration (typically 1-2 years)
- Self-Signed: Manually regenerate and update the secret before expiration