# TLS certificates are automatically renewed before expiry

- **Pattern:** `ab-001636` (`infrastructure-hardening.network-tls.cert-auto-renewal`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001636
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001636)

## Why it matters

An expired TLS certificate produces browser warnings that users train themselves to click through — or it breaks service entirely, causing an outage with no security justification. Manual certificate rotation fails at scale: teams forget expiry dates, renewal windows get missed during vacations, and a 90-day Let's Encrypt cert can silently expire over a long weekend. NIST 800-53 SC-17 requires certificate management controls. CWE-295 covers improper certificate validation. Automated renewal removes human failure from a process that must succeed on a strict calendar.

## Severity rationale

High because a missed manual renewal causes an immediate service outage or breaks TLS validation for all clients, with no grace period after expiry.

## Remediation

Deploy cert-manager in your cluster and annotate Ingress resources for automatic renewal. Install cert-manager, then configure a ClusterIssuer and annotate your Ingress in `k8s/ingress.yaml`:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - example.com
      secretName: example-tls
  rules:
    - host: example.com
      # ...
```

cert-manager renews certificates 30 days before expiry automatically. For cloud-managed load balancers, use ACM (AWS) or managed certificates (GKE) to delegate renewal entirely to the provider.

## Detection

- **ID:** `cert-auto-renewal`
- **Severity:** `high`
- **What to look for:** Count all TLS certificate references across Ingress manifests, Certificate resources, and cloud provider configurations. For each certificate, determine whether it is managed by an automated renewal system (cert-manager, ACM, Cloud Armor) or is manually provisioned. List all certificate sources found.
- **Pass criteria:** 100% of TLS certificates used by the project are automatically renewed before expiry via cert-manager, a cloud provider service (ACM, Cloud Armor), or equivalent automation. No manually managed certificates exist in production. Report the count: "X certificates found, all Y managed by automated renewal."
- **Fail criteria:** Any certificate is self-signed or statically provided with no renewal mechanism, or expiry dates require manual rotation.
- **Skip (N/A) when:** The project is in development-only or staging without production TLS.
- **Detail on fail:** Quote the certificate reference. Example: `"Kubernetes Ingress references TLS secret 'tls-secret' with no cert-manager annotation. Certificate has no renewal mechanism."` or `"Manual SSL certificate in use with no automation for renewal"`
- **Remediation:** Use cert-manager with Let's Encrypt for automatic renewal:

  ```yaml
  apiVersion: cert-manager.io/v1
  kind: Certificate
  metadata:
    name: app-cert
  spec:
    secretName: tls-secret
    issuerRef:
      name: letsencrypt-prod
    commonName: example.com
    dnsNames:
      - example.com
      - www.example.com
  ```

  Or annotate your Ingress directly:

  ```yaml
  metadata:
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
  spec:
    tls:
      - hosts:
          - example.com
        secretName: tls-secret
  ```

## External references

- cwe CWE-295
- nist SC-17
- external CIS-Kubernetes-5.4.2 — https://www.cisecurity.org/benchmark/kubernetes

Taxons: cryptography-and-secrets, operational-readiness

HTML version: https://auditbuffet.com/patterns/ab-001636
