Inhaltsverzeichnis

Kubernetes Cert-Manager

Složenost: Visoka
Trajanje: 2-3 sata postavljanja
Preduvjet: Kubernetes 1.25+, Helm

Automatsko upravljanje certifikatima u Kubernetesu s cert-managerom i vlastitom PKI.


Arhitektura

flowchart TB subgraph K8S["KUBERNETES CLUSTER"] subgraph CM["cert-manager"] I[Issuer/ClusterIssuer] C[Certificate] CR[CertificateRequest] end subgraph APP["Aplikacija"] P[Pod] S[Secret] ING[Ingress] end C --> CR --> I I --> S S --> P S --> ING end subgraph EXTERNAL["VANJSKI CA"] CA[Interni CA] V[Vault PKI] LE[Let's Encrypt] end I --> CA I --> V I --> LE style CM fill:#e3f2fd style I fill:#fff3e0


Instalacija

# Dodavanje Helm repozitorija
helm repo add jetstack https://charts.jetstack.io
helm repo update
 
# Instalacija cert-managera
helm install cert-manager jetstack/cert-manager \
    --namespace cert-manager \
    --create-namespace \
    --set installCRDs=true \
    --set prometheus.enabled=true
 
# Provjera instalacije
kubectl get pods -n cert-manager

Tipovi Issuera

Tip Issuera Primjena PQ podrška
————-———-————
SelfSigned Testiranje, Bootstrapping Ne
CA Interna PKI Da (s WvdS)
Vault HashiCorp Vault PKI Djelomično
ACME Let's Encrypt, javni CA-ovi Ne
Venafi Enterprise PKI Djelomično

ClusterIssuer s vlastitim CA

Korak 1: Stvaranje CA Secreta

# CA certifikat i ključ kao Secret
kubectl create secret tls ca-key-pair \
    --cert=intermediate-ca.pem \
    --key=intermediate-ca.key \
    --namespace cert-manager

Ili kao YAML:

# ca-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ca-key-pair
  namespace: cert-manager
type: kubernetes.io/tls
data:
  tls.crt: <base64-encoded-ca-cert>
  tls.key: <base64-encoded-ca-key>

Korak 2: Definiranje ClusterIssuera

# cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: internal-ca-issuer
spec:
  ca:
    secretName: ca-key-pair
kubectl apply -f cluster-issuer.yaml
 
# Provjera statusa
kubectl get clusterissuer internal-ca-issuer

Certificate resurs

# certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: app-tls
  namespace: production
spec:
  # Secret koji se stvara
  secretName: app-tls-secret
 
  # Trajanje valjanosti
  duration: 2160h    # 90 dana
  renewBefore: 360h  # 15 dana prije isteka obnoviti
 
  # Subject
  subject:
    organizations:
      - EMSR DATA
  commonName: app.example.com
 
  # Konfiguracija ključa
  privateKey:
    algorithm: ECDSA
    size: 384
    rotationPolicy: Always
 
  # Namjena
  usages:
    - server auth
    - client auth
 
  # DNS/IP SAN-ovi
  dnsNames:
    - app.example.com
    - app.production.svc.cluster.local
  ipAddresses:
    - 10.0.0.100
 
  # Referenca na Issuer
  issuerRef:
    name: internal-ca-issuer
    kind: ClusterIssuer
kubectl apply -f certificate.yaml
 
# Provjera statusa
kubectl get certificate -n production
kubectl describe certificate app-tls -n production
 
# Prikaz Secreta
kubectl get secret app-tls-secret -n production -o yaml

Ingress anotacija (automatski)

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  namespace: production
  annotations:
    # cert-manager automatski stvara certifikat
    cert-manager.io/cluster-issuer: "internal-ca-issuer"
spec:
  tls:
    - hosts:
        - app.example.com
      secretName: app-ingress-tls
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app-service
                port:
                  number: 80

Vault PKI integracija

# vault-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: vault-issuer
spec:
  vault:
    server: https://vault.example.com
    path: pki/sign/server-role
    caBundle: <base64-encoded-vault-ca>
    auth:
      kubernetes:
        role: cert-manager
        mountPath: /v1/auth/kubernetes
        secretRef:
          name: vault-token
          key: token

Vault konfiguracija:

# Aktiviranje PKI Engine
vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki
 
# Generiranje Root CA (ili import)
vault write pki/root/generate/internal \
    common_name="Internal Root CA" \
    ttl=87600h
 
# Uloga za cert-manager
vault write pki/roles/server-role \
    allowed_domains="example.com,svc.cluster.local" \
    allow_subdomains=true \
    max_ttl=720h
 
# Kubernetes Auth
vault auth enable kubernetes
vault write auth/kubernetes/config \
    kubernetes_host="https://kubernetes.default.svc"

Nadzor

Prometheus metrike

# ServiceMonitor za cert-manager
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: cert-manager
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: cert-manager
  endpoints:
    - port: http-metrics

Važne metrike:

Metrika Opis Prag za alert
——————————
certmanager_certificate_expiration_timestamp_seconds Vrijeme isteka < 7 dana
certmanager_certificate_ready_status Ready status != 1
certmanager_certificate_renewal_timestamp_seconds Posljednja obnova -

Alert pravila

# PrometheusRule
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: cert-manager-alerts
  namespace: monitoring
spec:
  groups:
    - name: cert-manager
      rules:
        - alert: CertificateExpiringSoon
          expr: |
            certmanager_certificate_expiration_timestamp_seconds - time() < 604800
          for: 1h
          labels:
            severity: warning
          annotations:
            summary: "Certifikat {{ $labels.name }} istječe za < 7 dana"

        - alert: CertificateNotReady
          expr: |
            certmanager_certificate_ready_status != 1
          for: 10m
          labels:
            severity: critical
          annotations:
            summary: "Certifikat {{ $labels.name }} nije spreman"

Rješavanje problema

# Status certifikata
kubectl get certificate -A
kubectl describe certificate <name> -n <namespace>
 
# Provjera CertificateRequest
kubectl get certificaterequest -A
kubectl describe certificaterequest <name>
 
# Logovi cert-managera
kubectl logs -n cert-manager -l app=cert-manager -f
 
# Događaji
kubectl get events -n cert-manager --sort-by='.lastTimestamp'

Česti problemi:

Problem Uzrok Rješenje
—————-———-
Issuer not found ClusterIssuer vs. Issuer Provjeriti Kind
Secret not found CA Secret nije stvoren Stvoriti Secret
Failed to generate CSR Algoritam ključa Provjeriti Algorithm/Size
Challenge failed ACME problem Provjeriti DNS/HTTP Challenge

Post-Quantum s vlastitim CA

PQ certifikati s cert-managerom:

Cert-manager sam ne podržava PQ algoritme, ali možete koristiti PQ-sposobni CA i ručno stvarati certifikate.

// Stvaranje Kubernetes Secreta s PQ certifikatom
using var intermediate = new X509Certificate2("intermediate.pfx", "password");
 
// Učitavanje CSR iz Kubernetesa
var csr = CertificateRequest.LoadSigningRequest(csrBytes, HashAlgorithmName.SHA384);
 
// Izdavanje PQ-Hybrid certifikata
var cert = csr.Create(
    intermediate,
    DateTimeOffset.UtcNow,
    DateTimeOffset.UtcNow.AddDays(90),
    Guid.NewGuid().ToByteArray(),
    CryptoMode.Hybrid);
 
// Spremanje kao Kubernetes Secret
var secret = new V1Secret
{
    Metadata = new V1ObjectMeta { Name = "pq-tls-secret" },
    Type = "kubernetes.io/tls",
    Data = new Dictionary<string, byte[]>
    {
        ["tls.crt"] = Encoding.UTF8.GetBytes(cert.ExportCertificatePem()),
        ["tls.key"] = Encoding.UTF8.GetBytes(cert.GetECDsaPrivateKey().ExportPkcs8PrivateKeyPem())
    }
};

Kontrolna lista

# Točka provjere Gotovo
—————-——–
1 cert-manager instaliran
2 ClusterIssuer konfiguriran
3 CA Secret stvoren
4 Test-Certificate funkcionira
5 Prometheus nadzor aktivan
6 Alerti konfigurirani

Povezana dokumentacija


« <- CI/CD potpisivanje koda | -> Zakazana obnova »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional