Gestisci certificati

Seleziona una versione della documentazione:

Le autorità di certificazione personalizzate ti consentono di gestire i certificati Transport Layer Security (TLS) sul tuo cluster di database AlloyDB Omni basato su Kubernetes.

Per impostazione predefinita, l'operatore Kubernetes di AlloyDB Omni utilizza cert-manager per eseguire il provisioning di un insieme di certificati TLS per ogni cluster di database. Oltre al certificato del server di database, l'operatore crea anche certificati per i componenti del control plane per garantire che anche le connessioni interne siano sicure. Per impostazione predefinita, ogni certificato è firmato da un emittente gestito dall'operatore.

Se preferisci che tutti i certificati, inclusi quelli per i componenti del control plane, siano concatenati alla tua autorità di certificazione radice attendibile, puoi configurare l'operatore in modo che utilizzi un emittente di tua scelta. In questo modo, puoi concatenare tutti i certificati alla tua infrastruttura a chiave pubblica (PKI), inclusi i certificati utilizzati per la funzionalità del control plane, senza esporre i dettagli di implementazione di ogni entità interna.

Durate dei certificati predefinite

Per impostazione predefinita, l'operatore AlloyDB Omni utilizza cert-manager per emettere e rinnovare automaticamente i certificati TLS per l'operatore, il control plane e le istanze di database.

La tabella seguente elenca i periodi di validità predefiniti per i certificati gestiti dall'operatore AlloyDB Omni:

Tipo di certificato Descrizione del certificato Nome secret Spazio dei nomi Durata predefinita
Certificato client mTLS dell'operatore Utilizzato dal deployment local-controller-manager per i controlli di integrità ad alta affidabilità (HA) e le connessioni tra l'operatore e gli agenti del control plane. dbs-al-cert-l2-operator Spazio dei nomi dell'operatore 1440h0m0s (60 giorni)
Certificati del server webhook dell'operatore Utilizzato dai server webhook di ammissione dell'operatore per convalidare e modificare le risorse personalizzate. fleet-webhook-server-cert

local-webhook-server-cert
Spazio dei nomi dell'operatore 1440h0m0s (60 giorni)
Certificati dell'agente del control plane per istanza Utilizzata dall'agente di database per istanza, dal Node Manager e dal daemon di backup per le connessioni del control plane. dbs-al-cert-dbd-INSTANCE_ID-DB_CLUSTER_NAME

dbs-al-cert-al-INSTANCE_ID-DB_CLUSTER_NAME-nm

dbs-al-cert-backup-daemon-BACKUP_REPO_NAME
Spazio dei nomi del cluster di database 1440h0m0s (60 giorni)
Certificati di backup Utilizzato dai servizi di backup per le connessioni di backup e ripristino. dbs-al-cert-backup-client

dbs-al-cert-backup-client-DATA_PLANE_ISSUER_NAME

dbs-al-cert-backup-server-INSTANCE_ID-DB_CLUSTER_NAME

dbs-al-cert-standby-backup-server-INSTANCE_ID-DB_CLUSTER_NAME
Spazio dei nomi del cluster di database 1440h0m0s (60 giorni)
Certificato del server di database Protegge le connessioni client del piano dati all'istanza di database. dbs-al-cert-DB_CLUSTER_NAME Spazio dei nomi del cluster di database 87600h0m0s (10 anni)
Certificato di query di autenticazione PgBouncer Certificato client del database utilizzato dal deployment PgBouncer per connettersi al database ed eseguire il pooling delle connessioni. Viene creato solo quando crei una risorsa PgBouncer. dbs-al-pgb-cert-PGBOUNCER_NAME Spazio dei nomi del cluster di database 87600h0m0s (10 anni)
Certificati CA autofirmati gestiti dall'operatore Certificati CA radice utilizzati dagli emittenti autofirmati predefiniti dell'operatore per firmare i certificati dell'operatore, dell'agente del control plane, del backup e del server di database. dbs-al-ca-l2-operator

dbs-al-ca-DB_CLUSTER_NAME

dbs-al-ca-dbd-INSTANCE_ID-DB_CLUSTER_NAME

dbs-al-ca-backup-server

dbs-al-ca-backup-daemon-BACKUP_REPO_NAME
Spazio dei nomi dell'operatore e spazio dei nomi del cluster di database 87600h0m0s (10 anni)

In questa tabella, i nomi dei secret utilizzano i seguenti segnaposto:

  • INSTANCE_ID: l'identificatore di 4 caratteri generato per l'istanza del database.
  • DB_CLUSTER_NAME: il nome della risorsa DBCluster.
  • DATA_PLANE_ISSUER_NAME: il nome dell'emittente cert-manager personalizzato configurato in spec.primarySpec.tls.dataPlaneCertIssuer.name, se specificato.
  • BACKUP_REPO_NAME: il nome della risorsa BackupRepository, se configurata.
  • PGBOUNCER_NAME: il nome della risorsa PgBouncer.

Configura emittenti personalizzati

Puoi configurare emittenti di certificati personalizzati per il cluster di database, l'operatore AlloyDB Omni e PgBouncer.

Per configurare un emittente di certificati, devi prima creare un emittente cert-manager associato alla CA che vuoi che firmi i tuoi certificati. Puoi utilizzare uno dei tipi di emittente cert-manager o un emittente esterno compatibile. L'operatore AlloyDB Omni fa riferimento a questo emittente durante la creazione dei certificati.

Le autorità di certificazione cert-manager personalizzate devono compilare il campo ca.crt nel secret del certificato generato con il certificato della CA radice.

Certificati del cluster di database

Esistono due campi di specifica del cluster di database per configurare gli emittenti dei certificati:

  • spec.primarySpec.tls.dataPlaneCertIssuer: un riferimento all'emittente cert-manager che esegue il provisioning dei certificati del piano dati. La CA emittente è quella di cui il client del database può fidarsi per verificare il database durante una connessione TLS.

  • spec.primarySpec.tls.controlPlaneAgentsCertIssuer: un riferimento all'emittente cert-manager che esegue il provisioning dei certificati del control plane. Questi certificati vengono utilizzati per le connessioni interne.

spec:
  primarySpec:
    tls:
      dataPlaneCertIssuer:
        name: DATA_PLANE_ISSUER_NAME
        kind: DATA_PLANE_ISSUER_KIND
        group: DATA_PLANE_ISSUER_GROUP
      controlPlaneAgentsCertIssuer:
        name: CONTROL_PLANE_ISSUER_NAME
        kind: CONTROL_PLANE_ISSUER_KIND
        group: CONTROL_PLANE_ISSUER_GROUP

Sostituisci quanto segue:

  • DATA_PLANE_ISSUER_NAME: il nome dell'emittente cert-manager che esegue il provisioning dei certificati del piano dati, ad esempio per il server di database.

  • DATA_PLANE_ISSUER_KIND: il tipo di API dell'emittente cert-manager. Il valore predefinito è Issuer.

  • DATA_PLANE_ISSUER_GROUP: il gruppo API dell'emittente. Il valore predefinito è cert-manager.io.

  • CONTROL_PLANE_ISSUER_NAME: il nome dell'emittente cert-manager che esegue il provisioning dei certificati del control plane per i componenti interni.

  • CONTROL_PLANE_ISSUER_KIND: il tipo di API dell'emittente cert-manager. Il valore predefinito è Issuer.

  • CONTROL_PLANE_ISSUER_GROUP: il gruppo API dell'emittente. Il valore predefinito è cert-manager.io.

Certificati operatore

I passaggi per configurare un emittente cert-manager per i certificati dell'operatore dipendono dal metodo utilizzato per installare l'operatore AlloyDB Omni.

Configura utilizzando Helm

Se stai installando l'operatore AlloyDB Omni per la prima volta, utilizza helm install e imposta i valori appropriati. Ciò presuppone che tu segua le istruzioni per eseguire il deployment dell'operatore utilizzando Helm.

helm install alloydbomni-operator alloydbomni-operator-OPERATOR_VERSION.tgz \
--create-namespace \
--namespace alloydb-omni-system \
--set operatorCertIssuer.certManagerIssuerName="OPERATOR_CERT_ISSUER_NAME" \
--set operatorCertIssuer.certManagerIssuerKind="OPERATOR_CERT_ISSUER_KIND" \
--set operatorCertIssuer.certManagerIssuerGroup="OPERATOR_CERT_ISSUER_GROUP" \
--atomic \
--timeout 5m

Se l'operatore è già installato e devi impostare l'emittente del certificato, utilizza helm upgrade per impostare i valori appropriati:

helm upgrade alloydbomni-operator alloydbomni-operator-OPERATOR_VERSION.tgz \
--create-namespace \
--namespace alloydb-omni-system \
--set operatorCertIssuer.certManagerIssuerName="OPERATOR_CERT_ISSUER_NAME" \
--set operatorCertIssuer.certManagerIssuerKind="OPERATOR_CERT_ISSUER_KIND" \
--set operatorCertIssuer.certManagerIssuerGroup="OPERATOR_CERT_ISSUER_GROUP" \
--atomic \
--timeout 5m

Sostituisci quanto segue:

  • OPERATOR_VERSION: la versione dell'operatore AlloyDB Omni da installare.

  • OPERATOR_CERT_ISSUER_NAME: il nome dell'emittente cert-manager che esegue il provisioning del certificato dell'operatore, utilizzato per le connessioni interne.

  • OPERATOR_CERT_ISSUER_KIND: il tipo di API dell'emittente cert-manager. Il valore predefinito è Issuer.

  • OPERATOR_CERT_ISSUER_GROUP: il gruppo API dell'emittente. Il valore predefinito è cert-manager.io.

Configura utilizzando Operator Lifecycle Manager

Se hai utilizzato Operator Lifecycle Manager (OLM) per installare l'operatore AlloyDB Omni, puoi modificare il campo spec.config.env della risorsa Subscription per impostare le variabili di ambiente CERT_MANAGER_ISSUER_NAME, CERT_MANAGER_ISSUER_KIND e CERT_MANAGER_ISSUER_GROUP dell'operatore Deployment.

spec:
  config:
    env:
    - name: CERT_MANAGER_ISSUER_NAME
      value: OPERATOR_CERT_ISSUER_NAME
    - name: CERT_MANAGER_ISSUER_KIND
      value: OPERATOR_CERT_ISSUER_KIND
    - name: CERT_MANAGER_ISSUER_GROUP
      value: OPERATOR_CERT_ISSUER_GROUP

Sostituisci quanto segue:

  • OPERATOR_CERT_ISSUER_NAME: il nome dell'emittente cert-manager che esegue il provisioning del certificato dell'operatore, utilizzato per le connessioni interne.

  • OPERATOR_CERT_ISSUER_KIND: il tipo di API dell'emittente cert-manager. Il valore predefinito è Issuer.

  • OPERATOR_CERT_ISSUER_GROUP: il gruppo API dell'emittente. Il valore predefinito è cert-manager.io.

Certificati PgBouncer

Per supportare gli emittenti personalizzati, il controller PgBouncer controlla il campo spec.primarySpec.tls.dataPlaneCertIssuer DBCluster e lo utilizza per eseguire il provisioning del certificato PgBouncer. Il controller PgBouncer utilizza anche gli attributi configurati in spec.primarySpec.tls.dataPlaneCertRequest per eseguire il provisioning del certificato PgBouncer. In questo modo, PgBouncer utilizza un certificato della stessa CA con gli stessi attributi del database.

Configura gli attributi dei certificati personalizzati

Puoi personalizzare gli attributi dei certificati TLS generati dall'operatore, come la durata del certificato, la finestra di rinnovo, i nomi alternativi del soggetto (SAN), il nome comune e la configurazione della chiave privata.

Puoi configurare gli attributi dei certificati personalizzati nel manifest DBCluster:

  • spec.primarySpec.tls.dataPlaneCertRequest: specifica gli attributi per i certificati del piano dati, inclusi i certificati del server pgBackRest, della query di autenticazione PgBouncer e del server di database.
  • spec.primarySpec.tls.controlPlaneAgentsCertRequest: specifica gli attributi per il provisioning dei certificati del control plane. Questi certificati vengono utilizzati per le connessioni interne.

Configura le richieste di certificati

Specifica le proprietà della richiesta nel seguente formato:

spec:
  primarySpec:
    tls:
      dataPlaneCertRequest:
        commonName: DATABASE_COMMON_NAME
        dnsNames:
        - DATABASE_DNS_NAME_1
        - DATABASE_DNS_NAME_2
        duration: DATA_PLANE_DURATION
        renewBefore: DATA_PLANE_RENEW_BEFORE
        privateKey:
          algorithm: DATA_PLANE_ALGORITHM
          size: DATA_PLANE_KEY_SIZE
          rotationPolicy: DATA_PLANE_ROTATION_POLICY
      controlPlaneAgentsCertRequest:
        duration: CONTROL_PLANE_DURATION
        renewBefore: CONTROL_PLANE_RENEW_BEFORE
        privateKey:
          algorithm: CONTROL_PLANE_ALGORITHM
          size: CONTROL_PLANE_KEY_SIZE
          rotationPolicy: CONTROL_PLANE_ROTATION_POLICY

Sostituisci quanto segue:

  • DATABASE_COMMON_NAME: (Facoltativo, solo piano dati) il nome comune del certificato del database.
  • DATABASE_DNS_NAME_1, DATABASE_DNS_NAME_2: (facoltativo, solo piano dati) un elenco di nomi alternativi del soggetto (SAN) per il certificato del database.
  • DATA_PLANE_DURATION e CONTROL_PLANE_DURATION: la durata di validità richiesta del certificato come stringa di durata, ad esempio 720h0m0s per una durata personalizzata di 30 giorni. In ogni blocco di richiesta di certificato, devi specificare sia duration sia renewBefore (con renewBefore inferiore a duration) oppure omettere entrambi i campi. Se entrambi i campi vengono omessi, la durata predefinita è 1440h0m0s, ovvero 60 giorni, per i certificati del control plane e di backup, e 87600h0m0s, ovvero 10 anni, per i certificati del server di database e della query di autenticazione PgBouncer.
  • DATA_PLANE_RENEW_BEFORE e CONTROL_PLANE_RENEW_BEFORE: la durata prima della scadenza in cui cert-manager deve avviare un tentativo di rinnovo, ad esempio 120h0m0s per cinque giorni prima della scadenza. In ogni blocco di richiesta di certificato, devi specificare sia duration sia renewBefore (con renewBefore inferiore a duration) oppure omettere entrambi i campi. Se entrambi i campi vengono omessi, la finestra di rinnovo predefinita è 120h0m0s, ovvero cinque giorni, per i certificati del control plane e di backup, e 1440h0m0s, ovvero 60 giorni, per i certificati del server di database e della query di autenticazione PgBouncer.
  • DATA_PLANE_ALGORITHM e CONTROL_PLANE_ALGORITHM: l'algoritmo della chiave privata. I valori validi sono RSA, ECDSA o Ed25519.
  • DATA_PLANE_KEY_SIZE e CONTROL_PLANE_KEY_SIZE: la dimensione della chiave privata in bit. Se l'algoritmo è RSA, i valori validi sono 4096 o 8192 (il valore predefinito è 4096). Se l'algoritmo è ECDSA, i valori validi sono 384 o 521 (il valore predefinito è 384). Se l'algoritmo è Ed25519, la dimensione viene ignorata.
  • DATA_PLANE_ROTATION_POLICY e CONTROL_PLANE_ROTATION_POLICY: la policy che controlla la rigenerazione della chiave privata. I valori validi sono Always o Never.

Certificati client operatore e di backup

Per personalizzare gli attributi del certificato per l'operatore e il client di backup (che sono condivisi tra tutte le istanze in uno spazio dei nomi e non sono gestiti da una specifica del cluster di database), modifica le risorse personalizzate Certificate. L'operatore conserva queste modifiche manuali.

Esegui la pulizia dei secret dei certificati

Quando elimini una risorsa DBCluster, l'operatore AlloyDB Omni elimina le risorse Certificate associate, ma cert-manager non pulisce le risorse Secret del certificato per impostazione predefinita. Per configurare il controller cert-manager in modo che esegua la pulizia dei secret quando i certificati vengono eliminati, consulta Pulizia dei secret quando i certificati vengono eliminati nella documentazione di cert-manager.

Se hai già eliminato una risorsa DBCluster senza configurare la pulizia automatica, elimina manualmente i secret dei certificati rimasti:

kubectl delete secret CERTIFICATE_SECRET_NAME -n NAMESPACE

Sostituisci quanto segue:

  • CERTIFICATE_SECRET_NAME: il nome del secret del certificato da eliminare.
  • NAMESPACE: lo spazio dei nomi del cluster di database.

Verifica

Per verificare che l'operatore Deployment sia integro e che le variabili di ambiente CERT_MANAGER_ISSUER_NAME, CERT_MANAGER_ISSUER_KIND e CERT_MANAGER_ISSUER_GROUP siano impostate, esegui questo comando:

kubectl get deployments local-controller-manager -n alloydb-omni-system -o yaml

Per verificare che venga utilizzato l'emittente corretto, controlla gli oggetti Certificate come segue:

kubectl get certificate -n NAMESPACE

Sostituisci NAMESPACE con lo spazio dei nomi del cluster di database o alloydb-omni-system per il certificato dell'operatore.

Controlla il campo issuerRef nell'output di ogni certificato per verificare che corrisponda all'emittente personalizzato.

Mitiga la scadenza del certificato client dell'operatore nelle versioni dell'operatore precedenti alla 1.8.2

Nelle versioni di AlloyDB Omni operator precedenti alla 1.8.2, il deployment local-controller-manager memorizza nella cache il certificato client mTLS dbs-al-cert-l2-operator di 60 giorni in memoria per le connessioni di controllo di integrità ad alta affidabilità agli agenti del control plane. Sebbene cert-manager rinnovi automaticamente il secret dbs-al-cert-l2-operator cinque giorni prima della scadenza, il deployment local-controller-manager non ricarica il certificato rinnovato fino al riavvio del pod dell'operatore. Quando il certificato memorizzato nella cache scade il giorno 60, le successive riconnessioni del controllo di integrità non vanno a buon fine con un errore tls: expired certificate e potrebbero attivare failover HA non pianificati.

Per risolvere definitivamente il problema, esegui l'upgrade dell'operatore AlloyDB Omni alla versione 1.8.2 o successive.

Se non puoi eseguire subito l'upgrade alla versione 1.8.2 o successive dell'operatore, ruota il Secret dbs-al-cert-l2-operator e riavvia il deployment local-controller-manager almeno 10 giorni prima della scadenza del certificato. Questa procedura non riavvia i pod del database né interrompe il traffico del database.

Prima di iniziare

Prima di eseguire lo script rotate_cert.sh, verifica che il tuo ambiente soddisfi i seguenti requisiti:

  • Installa bash, kubectl, openssl e base64 nel tuo PATH.
  • Configura l'accesso al tuo cluster Kubernetes e imposta il contesto kubectl attivo sul cluster di destinazione. Per confermare il contesto attivo, esegui kubectl config current-context. Ripeti questa procedura per ogni cluster che esegue una versione dell'operatore precedente alla 1.8.2.
  • Verifica che il tuo account disponga delle autorizzazioni di controllo controllo dell'accesso basato su ruoli (RBAC) di Kubernetes nello spazio dei nomi dell'operatore, che per impostazione predefinita è alloydb-omni-system:
    • get su Certificate risorse e Pod log
    • get e list su Pod risorse
    • get e delete sul secret dbs-al-cert-l2-operator (più create e patch per ripristinare un secret di cui è stato eseguito il backup)
    • get e patch sul deployment local-controller-manager
    • delete sulle risorse CertificateRequest (per ripristinare un secret di cui è stato eseguito il backup)

Ruota il certificato client dell'operatore

Lo script rotate_cert.sh supporta due modalità e un argomento facoltativo per lo spazio dei nomi, che per impostazione predefinita è alloydb-omni-system:

  • ./rotate_cert.sh check: esegue un controllo di sola lettura e stampa le seguenti informazioni:
    • Numero di serie e date di validità del certificato attuale
    • Scadenza della rotazione consigliata, impostata 10 giorni prima della scadenza
    • Ora di inizio del container local-controller-manager
    • Stato del certificato in memoria [OK] o [WARNING]
    • Un comando di backup kubectl
  • ./rotate_cert.sh rotate: esegue le seguenti azioni:
    • Elimina il secret dbs-al-cert-l2-operator
    • Attende che cert-manager emetta un nuovo numero di serie del certificato e aggiorni la risorsa dbs-al-cert-request-l2-operator Certificate
    • Riavvia il deployment local-controller-manager
    • Controlla i log del nuovo pod e stampa la nuova data di scadenza

Per controllare e ruotare il certificato client dell'operatore, segui questi passaggi:

  1. Salva il seguente script in un file denominato rotate_cert.sh, quindi rendi il file eseguibile:

    cat << 'EOF' > rotate_cert.sh
    #!/usr/bin/env bash
    set -euo pipefail
    MODE="${1:-}"
    NS="${2:-alloydb-omni-system}"
    SECRET="dbs-al-cert-l2-operator"
    CERT="dbs-al-cert-request-l2-operator"
    DEPLOY="local-controller-manager"
    get_cert_info() {
      kubectl get secret "$SECRET" -n "$NS" -o jsonpath='{.data.tls\.crt}' 2>/dev/null \
        | base64 -d 2>/dev/null | openssl x509 -noout -serial -enddate 2>/dev/null || true
    }
    calc_rotate_by() {
      date -u -d "$1 - 10 days" +"%Y-%m-%d" 2>/dev/null \
        || date -u -j -v-10d -f "%Y-%m-%dT%H:%M:%SZ" "$1" +"%Y-%m-%d" 2>/dev/null || echo "unknown"
    }
    get_container_name() {
      local names
      names="$(kubectl get pods -n "$NS" -l local-control-plane=controller-manager \
        --field-selector=status.phase=Running --sort-by=.metadata.creationTimestamp \
        -o jsonpath='{.items[-1].spec.containers[*].name}' 2>/dev/null || true)"
      if [[ " $names " == *" local-manager "* ]]; then
        echo "local-manager"
      else
        echo "manager"
      fi
    }
    case "$MODE" in
      check)
        INFO="$(get_cert_info)"
        SERIAL="$(echo "$INFO" | sed -n 's/^serial=//p')"
        ENDDATE="$(echo "$INFO" | sed -n 's/^notAfter=//p')"
        NOT_BEFORE="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.notBefore}')"
        NOT_AFTER="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.notAfter}')"
        CONTAINER="$(get_container_name)"
        STARTED_AT="$(kubectl get pods -n "$NS" -l local-control-plane=controller-manager \
          --field-selector=status.phase=Running --sort-by=.metadata.creationTimestamp \
          -o jsonpath="{.items[-1].status.containerStatuses[?(@.name==\"$CONTAINER\")].state.running.startedAt}")"
        echo "Certificate Serial      : $SERIAL"
        echo "Certificate Start Date  : $NOT_BEFORE"
        echo "Certificate End Date    : $ENDDATE ($NOT_AFTER)"
        echo "Recommended Rotate By   : $(calc_rotate_by "$NOT_AFTER") (10 days before expiry)"
        echo "Operator Started At     : $STARTED_AT"
        if [[ "$STARTED_AT" < "$NOT_BEFORE" ]]; then
          echo "[WARNING] Operator started ($STARTED_AT) BEFORE current cert was issued ($NOT_BEFORE). It is still caching the old cert in memory! Run './rotate_cert.sh rotate $NS' now."
        else
          echo "[OK] Operator is running with the current certificate in memory."
        fi
        echo "Optional Backup Command : kubectl get secret $SECRET -n $NS -o yaml > $SECRET-backup.yaml"
        ;;
      rotate)
        OLD_SERIAL="$(get_cert_info | sed -n 's/^serial=//p')"
        OLD_REV="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.revision}' 2>/dev/null || true)"
        echo "Current Certificate Serial: ${OLD_SERIAL:-none}"
        kubectl delete secret "$SECRET" -n "$NS" --ignore-not-found
        NEW_SERIAL=""
        NOT_AFTER=""
        for _ in {1..30}; do
          sleep 2
          NEW_SERIAL="$(get_cert_info | sed -n 's/^serial=//p')"
          NEW_REV="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.revision}' 2>/dev/null || true)"
          READY_COND="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || true)"
          NOT_AFTER="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.notAfter}' 2>/dev/null || true)"
          [[ -n "$NEW_SERIAL" && "$NEW_SERIAL" != "$OLD_SERIAL" && "$NEW_REV" != "$OLD_REV" && "$READY_COND" == "True" && -n "$NOT_AFTER" ]] && break
        done
        [[ -n "$NEW_SERIAL" && "$NEW_SERIAL" != "$OLD_SERIAL" && "$READY_COND" == "True" ]] || { echo "[ERROR] Timed out waiting for new cert."; exit 1; }
        kubectl rollout restart "deployment/$DEPLOY" -n "$NS"
        kubectl rollout status "deployment/$DEPLOY" -n "$NS" --timeout=180s
        NEW_POD="$(kubectl get pods -n "$NS" -l local-control-plane=controller-manager \
          --field-selector=status.phase=Running --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}')"
        CONTAINER="$(get_container_name)"
        READY=false
        for _ in {1..40}; do
          LOGS="$(kubectl logs "pod/$NEW_POD" -n "$NS" -c "$CONTAINER" 2>/dev/null || true)"
          grep -q "tls: expired certificate" <<<"$LOGS" && { echo "[ERROR] Found 'tls: expired certificate' in operator logs!"; exit 1; }
          grep -q "L2 controller cert generation completed successfully" <<<"$LOGS" && { READY=true; break; }
          sleep 3
        done
        [[ "$READY" == "true" ]] || { echo "[ERROR] Timed out waiting for L2 controller cert generation log."; exit 1; }
        echo "[SUCCESS] New Serial: $NEW_SERIAL | End Date: $NOT_AFTER | Next Rotate By: $(calc_rotate_by "$NOT_AFTER") (10 days before expiry)"
        ;;
      *)
        echo "Usage: $0 <check|rotate> [namespace]"
        echo "  check       : Validate current certificate status and operator start time."
        echo "  rotate      : Trigger immediate certificate rotation and restart the operator."
        echo "  [namespace] : Namespace of the operator (defaults to 'alloydb-omni-system')."
        exit 1 ;;
    esac
    EOF
    chmod +x rotate_cert.sh
    
  2. Esegui lo script rotate_cert.sh in modalità check per controllare la data di scadenza del certificato attuale, la data di rotazione consigliata e lo stato in memoria dell'operatore:

    ./rotate_cert.sh check
    
  3. (Facoltativo) Esegui il backup del secret dbs-al-cert-l2-operator prima di ruotare il certificato:

    kubectl get secret dbs-al-cert-l2-operator -n alloydb-omni-system \
      -o yaml > dbs-al-cert-l2-operator-backup.yaml
    
  4. Se l'output check mostra [WARNING] o se la data corrente è precedente o uguale alla data Recommended Rotate By, esegui lo script rotate_cert.sh in modalità rotate:

    ./rotate_cert.sh rotate
    

    Verifica che l'output termini con [SUCCESS] e mostri il nuovo numero di serie del certificato, la data di scadenza e la data di rotazione consigliata successiva. Se l'output mostra [ERROR] o lo script termina con uno stato diverso da zero, esegui nuovamente ./rotate_cert.sh check e controlla i log dell'operatore eseguendo kubectl logs deployment/local-controller-manager -n alloydb-omni-system -c local-manager (o -c manager nelle versioni dell'operatore precedenti alla 1.6.0).

  5. (Facoltativo) Se hai creato un file di backup nel passaggio 3, elimina il file di backup locale dopo aver confermato che la rotazione è andata a buon fine, perché il file contiene la chiave privata precedente:

    rm -f dbs-al-cert-l2-operator-backup.yaml
    

Ripristina un certificato di cui è stato eseguito il backup

Se cert-manager non riesce a emettere un nuovo certificato durante la rotazione e devi eseguire il rollback a un file dbs-al-cert-l2-operator-backup.yaml non scaduto, segui questi passaggi:

  1. Elimina la risorsa CertificateRequest in attesa o non riuscita per il certificato dbs-al-cert-request-l2-operator in modo che cert-manager non rifiuti la chiave privata ripristinata con un motivo SecretMismatch e sovrascriva il secret ripristinato:

    REV="$(kubectl get certificate dbs-al-cert-request-l2-operator -n alloydb-omni-system -o jsonpath='{.status.revision}')"
    kubectl delete certificaterequest \
      "dbs-al-cert-request-l2-operator-$((REV + 1))" \
      -n alloydb-omni-system --ignore-not-found
    
  2. Rimuovi i campi di primo livello metadata.resourceVersion e metadata.uid dal file dbs-al-cert-l2-operator-backup.yaml e applica il secret utilizzando l'applicazione lato server:

    grep -vE '^  (resourceVersion|uid):' dbs-al-cert-l2-operator-backup.yaml \
      | kubectl apply --server-side --force-conflicts -f -
    
  3. Riavvia il deployment local-controller-manager per caricare il certificato ripristinato in memoria:

    kubectl rollout restart deployment/local-controller-manager -n alloydb-omni-system
    kubectl rollout status deployment/local-controller-manager -n alloydb-omni-system --timeout=180s
    
  4. Esegui lo script rotate_cert.sh in modalità check per verificare che il valore Certificate Serial corrisponda al numero di serie del certificato di cui è stato eseguito il backup e che lo script restituisca [OK]:

    ./rotate_cert.sh check
    

    Il certificato ripristinato conserva la data di scadenza originale, quindi devi comunque ruotarlo entro il giorno Recommended Rotate By.

  5. Elimina il file di backup locale dopo aver confermato il ripristino:

    rm -f dbs-al-cert-l2-operator-backup.yaml