checkId: check.security.tls.certificate plugin: stellaops.doctor.security severity: fail tags: [security, tls, certificate]

TLS Certificate

What It Checks

Validates TLS certificate validity and expiration. The check only runs when a certificate path is configured (Tls:CertificatePath or Kestrel:Certificates:Default:Path). It loads the certificate file and applies the following validations:

ConditionResult
Certificate file not foundfail
Certificate cannot be loaded (corrupt, wrong password)fail
Certificate not yet valid (NotBefore in the future)fail
Certificate has expired (NotAfter in the past)fail
Certificate expires in less than 30 dayswarn
Certificate valid for 30+ dayspass

The check supports both PEM certificates and PKCS#12 (.pfx/.p12) files with optional passwords (Tls:CertificatePassword or Kestrel:Certificates:Default:Password).

Evidence collected includes: subject, issuer, NotBefore, NotAfter, days until expiry, and thumbprint.

Why It Matters

An expired or invalid TLS certificate causes all HTTPS connections to fail. Browsers display security warnings, API clients reject responses, and inter-service communication breaks. In a release control plane, TLS failures prevent:

Certificate expiration is the most common cause of production outages that is entirely preventable with monitoring.

Common Causes

How to Fix

Docker Compose

Mount the certificate and configure the path:

services:
  platform:
    environment:
      Tls__CertificatePath: "/app/certs/stellaops.pfx"
      Tls__CertificatePassword: "${TLS_CERT_PASSWORD}"
    volumes:
      - ./certs/stellaops.pfx:/app/certs/stellaops.pfx:ro

Generate a new self-signed certificate for development:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes \
  -subj "/CN=stella-ops.local"
openssl pkcs12 -export -out stellaops.pfx -inkey key.pem -in cert.pem

Bare Metal / systemd

Renew the certificate (e.g., with Let’s Encrypt):

sudo certbot renew
sudo systemctl restart stellaops-platform

Or update appsettings.json to point at a new certificate:

{
  "Tls": {
    "CertificatePath": "/etc/ssl/stellaops/cert.pfx",
    "CertificatePassword": "<password>"
  }
}

Kubernetes / Helm

Use cert-manager for automatic certificate management:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: stellaops-tls
spec:
  secretName: stellaops-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - stella-ops.yourdomain.com

Reference in Helm values:

tls:
  secretName: "stellaops-tls-secret"

Verification

stella doctor run --check check.security.tls.certificate