Skip to content

Brug Frostmoln Hemmeligheder med External Secrets Operator (ESO) ​

External Secrets Operator (ESO) synkroniserer hemmeligheder fra et eksternt lager ind i indbyggede Kubernetes-Secret-objekter. Dens generiske webhook-udbyder kan læse fra et hvilket som helst HTTP-API — inklusive Frostmoln Hemmeligheder — så du kan beholde dine hemmeligheder administreret i Frostmoln og lade ESO spejle dem ind i dine klynger, uden kode på ESO-siden og uden en egen udbyder.

Det virker på Frostmoln Administreret Kubernetes, hvor platformen installerer ESO for dig som en klyngetilføjelse, og på enhver anden Kubernetes-klynge med udgående internetadgang, som du selv kører — din egen eller on-prem — fordi ESO når det offentlige API-kantlag (api.frostmoln.cloud) over HTTPS.

Hvad dette gør ​

Du gemmer en hemmelighed i Frostmoln én gang. Ved hvert opdateringsinterval kalder ESO Frostmolns opslags-endpoint, læser værdien og skriver den ind i en Kubernetes-Secret, som dine arbejdslaster bruger som sædvanligt (miljøvariabel eller monteret fil). Når du roterer værdien i Frostmoln, tager ESO den nye værdi med ved næste opdatering.

Forudsætninger ​

  • ESO installeret i klyngen.
    • Frostmoln Administreret Kubernetes: vælg klyngetilføjelsen External Secrets Operator (external-secrets), når du opretter klyngen, eller føj den til en klynge, der kører. Installer ikke chartet selv. Se På Frostmoln Administreret Kubernetes.
    • Enhver anden klynge: installer standard-chartet —
      bash
      helm repo add external-secrets https://charts.external-secrets.io
      helm install external-secrets external-secrets/external-secrets \
        -n external-secrets --create-namespace --set installCRDs=true
  • En Frostmoln-API-nøgle. Opret en under Konto → API-nøgler i portalen (eller med fm account api-key create --name eso --scopes secrets:read). På Frostmoln Administreret Kubernetes skal du i stedet bruge Arbejdslastidentitet.
  • Dit tenant-ID — fra fm auth whoami eller portalen.

Begræns API-nøglen til hemmeligheder

Når du opretter nøglen, så giv den kun adgangen secrets:read. Frostmoln håndhæver API-nøglers adgange på serversiden, så en nøgle uden secrets:read afvises (403) af Secrets-tjenesten på anmodningstidspunktet — at begrænse nøglen indskrænker altså reelt, hvad den kan gøre, ikke bare som en konvention. Behandl nøglen som følsom; ESO gemmer den i en Kubernetes-Secret.

På Frostmoln Administreret Kubernetes ​

Platformen installerer ESO for dig i navnerummet external-secrets. Når den kører, autentificerer du den med Arbejdslastidentitet — uden API-nøgle — eller med en API-nøgle som i trin 1–3 nedenfor.

Føj den til, når du opretter klyngen, eller senere ​

  • Når du opretter en klynge — vælg External Secrets Operator i portalens oprettelsesformular, angiv --addons external-secrets til fm kubernetes cluster create, eller medtag external-secrets i addons på frostmoln_kubernetes_cluster. Klyngen rapporteres først som kører; ESO anvendes nogle minutter senere, når arbejdsknuderne har tilsluttet sig, og tilføjelsen vises som Anvendes indtil da.
  • Til en klynge, der kører —
    • Portalen — klyngens fane Tilføjelser.
    • fm CLI —
      bash
      fm kubernetes cluster add-addons <cluster-id> --addons external-secrets
    • Terraform — føj external-secrets til addons, og kør apply igen; opdateringen føjer tilføjelsen til den kørende klynge uden at erstatte den.

Når du først angiver addons i Terraform, skal nøglen blive stående der: en tilføjelse, der er føjet til fra portalen eller med fm, og som din addons ikke indeholder, fjernes ved næste apply.

At føje den til en klynge, der kører, træder ikke i kraft med det samme: tilføjelsen starter sin egen synkronisering, og ESO når klyngen typisk inden for få minutter; kan den synkronisering ikke startes, sker det først ved platformens næste synkronisering, op til en time. På en klynge, hvis kontrolplan er ældre end tilføjelsen, bliver tilføjelsen accepteret, men ESO installeres aldrig; opret en ny klynge for at bruge den.

Dine noder har brug for udgående HTTPS til ghcr.io

ESO's controller-image, ghcr.io/external-secrets/external-secrets, hentes over klyngens egen udgående HTTPS, når podden starter. Det er ikke forudindlæst på dine noder. Hvis du filtrerer udgående trafik på værtsnavn, så tillad bådeghcr.io og pkg-containers.githubusercontent.com, fordi ghcr.io omdirigerer hentningen af images dertil. ESO har desuden brug for udgående HTTPS til api.frostmoln.cloud for at læse dine hemmeligheder. Platformen kontrollerer ingen af delene; se Opret en klynge.

Autentificer med Arbejdslastidentitet (anbefalet) ​

Med Arbejdslastidentitet læser ESO et kortlivet token, som platformen holder i en Secret for dig, så der er ingen API-nøgle at oprette, gemme eller rotere. Du har brug for:

  • Begge tilføjelser på klyngen: External Secrets Operator og Workload Identity.
  • En binding med secrets:read til en ServiceAccount i det navnerum, hvor SecretStore ligger:
    bash
    fm kubernetes workload-identity binding create \
      --cluster <cluster-id> --namespace default --service-account eso \
      --scope secrets:read
  • Den ServiceAccount, annoteret, så tokenet holdes i en Secret ved navn frostmoln-token:
    yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: eso
      namespace: default
      annotations:
        frostmoln.cloud/workload-identity-secret: frostmoln-token

Secret'en bærer allerede etiketten external-secrets.io/type: webhook, så spring Trin 1 over. I Trin 2 bruger du i stedet denne SecretStore — samme URL, med tokenet som bearer-header:

yaml
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: frostmoln
  namespace: default
spec:
  provider:
    webhook:
      url: 'https://api.frostmoln.cloud/api/v1/tenants/<TENANT_ID>/secrets/lookup?name={{ .remoteRef.key }}'
      headers:
        Authorization: 'Bearer {{ .auth.token }}'
      result:
        jsonPath: '$.secretValue'
      secrets:
        - name: auth
          secretRef:
            name: frostmoln-token
            key: token

Trin 3 er uændret. Sådan holdes Secret'en, og hvornår den fjernes: Legitimationsoplysning i en Secret.

Forskelle fra en ESO, du selv har installeret ​

  • Du kan ikke se ESO's pods eller logs. external-secrets er et beskyttet platformsnavnerum: din kubeconfig kan hverken læse eller skrive noget i det, så kubectl -n external-secrets get pods og kubectl logs dér afvises. Læs i stedet status og hændelser for dine egne objekter med kubectl -n <namespace> describe externalsecret <name> og kubectl -n <namespace> describe secretstore <name>.

  • Kun navnerumsbundne ressourcer. SecretStore og ExternalSecret er tilgængelige. ClusterSecretStore, ClusterExternalSecret og PushSecret er ikke aktiveret.

  • ESO kan læse alle Secrets i klyngen. Ligesom standard-ESO har tilføjelsens controller læseadgang til Secrets i hele klyngen, også i dine navnerum. Platformen begrænser, hvad den må skrive, ikke hvad den må læse.

  • Servicekonto-tokens afvises bevidst. ESO må ikke skrive Secrets i platformens navnerum. I alle navnerum må den ikke oprette eller opdatere en Secret af typen kubernetes.io/service-account-token eller en, der bærer annotationen kubernetes.io/service-account.name, og den må ikke anmode om tokens til platformens servicekonti. En ExternalSecret, hvis mål ville blive sådan en Secret — via target.template eller med creationPolicy: Merge ind i en eksisterende — synkroniseres ikke, og fejlen i kubectl describe externalsecret indeholder:

    text
    the external-secrets add-on may not create or update a service-account token Secret
  • Fjern din egen ESO først, i denne rækkefølge:

    1. Mens din egen ESO stadig kører, slet eller frigør hver ExternalSecret som beskrevet i Fjern tilføjelsen.
    2. Afinstaller din ESO.
    3. Slet dens CRD'er.

    Hold rækkefølgen. At slette en CRD sletter alle ExternalSecret af den type og med creationPolicy: Owner også deres Secrets; uden en controller til at fjerne deres finalizers bliver CRD'en hængende i Terminating, og tilføjelsen kan ikke installere sine egne. CRD'er, du lader blive liggende, overtages, som de er, inklusive felter, du har tilføjet.

Fjern tilføjelsen ​

Når tilføjelsen fjernes, bliver navnerummet external-secrets også liggende. Det forbliver reserveret til platformen, så din kubeconfig stadig ikke kan bruge det, og tilføjer du tilføjelsen igen, genbruges det.

Håndter hver ExternalSecret, FØR du fjerner tilføjelsen

ESO sætter en oprydnings-finalizer på hver ExternalSecret. Når tilføjelsen fjernes, slettes ESO-controlleren og dens webhooks, men CRD'erne bliver liggende, og uden controlleren er der intet, der fjerner den finalizer. En ExternalSecret, der stadig er i klyngen, kan så ikke slettes, og det kan et navnerum, der indeholder en, heller ikke.

  1. List ExternalSecret-objekterne i hvert navnerum. En liste på tværs af alle navnerum afvises, så kør den én gang pr. navnerum:

    bash
    kubectl -n <namespace> get externalsecrets
  2. For hver ExternalSecret, hvis Secret du vil beholde, skal du gøre alt dette i rækkefølge. Vent ikke på, at ESO opgiver ejerskabet ved en synkronisering: det sker kun ved en vellykket synkronisering, og en mislykket hentning, et tomt resultat med Retain eller visse opdateringsindstillinger springer det over. <target> er den Secret, der er angivet i spec.target.name, eller ExternalSecret'ens eget navn, hvis feltet ikke er sat.

    1. Sæt creationPolicy: Orphan først; med Owner tilføjer ESO ejerreferencen igen ved næste synkronisering:
      bash
      kubectl -n <namespace> patch externalsecret <name> \
        --type=merge -p '{"spec":{"target":{"creationPolicy":"Orphan"}}}'
    2. Kontroller, om Secret'en stadig har en ejerreference:
      bash
      kubectl -n <namespace> get secret <target> -o jsonpath='{.metadata.ownerReferences}'
    3. Kun hvis det udskrev noget, så fjern den, og kør derefter trin 2.2 igen, indtil intet udskrives. Et 422 (Unprocessable Entity) fra patchen er ikke en fejl: Secret'en har ingen ejerreference at fjerne og er allerede sikker.
      bash
      kubectl -n <namespace> patch secret <target> \
        --type=json -p '[{"op":"remove","path":"/metadata/ownerReferences"}]'
    4. Slet ExternalSecret'en; Secret'en bevares:
      bash
      kubectl -n <namespace> delete externalsecret <name>
  3. For hver ExternalSecret, hvis Secret du ikke har brug for, så slet ExternalSecret'en, mens ESO stadig kører. Med standardværdien creationPolicy: Owner slettes dens synkroniserede Secret med den, og alt, der stadig bruger den Secret, holder op med at virke: pods, der henviser til den, fejler, næste gang de starter, og er det en pull secret til images, kan nye noder ikke længere hente imaget.

  4. Først derefter fjerner du tilføjelsen — fra fanen Tilføjelser, med fm kubernetes cluster remove-addons <cluster-id> --addons external-secrets eller ved at fjerne nøglen fra addons i Terraform.

Hvis du allerede har fjernet tilføjelsen ​

Fjerner du finalizeren, kan den synkroniserede Secret blive slettet

Med standardværdien creationPolicy: Owner ejes den synkroniserede Secret af sin ExternalSecret. Når finalizeren er væk, og ExternalSecret er slettet, sletter Kubernetes' garbage collection også Secret'en — også med deletionPolicy: Retain.

For hver resterende ExternalSecret:

  1. Hvis selve navnerummet er ved at blive slettet, kan du ikke beholde Secret'en: alle Secrets i det slettes også, uanset deres ejerreferencer. Genskab den et andet sted ud fra Frostmoln Hemmeligheder. Ellers skal du, for at beholde dens Secret, først kontrollere, om der er en ejerreference, og i så fald fjerne den (trin 2.2 og 2.3 ovenfor).
  2. Fjern finalizeren:
    bash
    kubectl -n <namespace> patch externalsecret <name> \
      --type=merge -p '{"metadata":{"finalizers":null}}'
  3. Hvis ExternalSecret'en ikke allerede er ved at blive slettet, så slet den.

På Frostmoln-klynger er det kun ExternalSecret, der har denne finalizer, fordi PushSecret og ClusterExternalSecret ikke er aktiveret.

Trin 1 — Gem API-nøglen som en mærket Secret ​

API-nøgle: andre klynger end Frostmoln Administreret Kubernetes

Trin 1 og 2 bruger en API-nøgle. På Frostmoln Administreret Kubernetes skal du i stedet bruge Arbejdslastidentitet.

ESO's webhook-udbyder læser API-nøglen fra en Kubernetes-Secret. Secret'en skal bære etiketten external-secrets.io/type: webhook — webhook-udbyderen nægter at læse en umærket Secret.

Gem nøglen i en lokal fil, der kun indeholder nøglen, uden afsluttende linjeskift. Opret Secret'en ud fra filen, mærk den, og slet derefter filen:

bash
kubectl -n default create secret generic frostmoln-api-key --from-file=apikey=./apikey
# PÅKRÆVET — webhook-udbyderen ignorerer en umærket Secret
kubectl -n default label secret frostmoln-api-key external-secrets.io/type=webhook
rm ./apikey

Brug kubectl create, ikke kubectl apply med et manifest: apply gemmer hele manifestet, inklusive nøglen, i klartekst i Secret'ens annotation kubectl.kubernetes.io/last-applied-configuration. Tjek ikke nøglen ind i git. Kun SecretStore- og ExternalSecret-manifesterne nedenfor er sikre at gemme i versionsstyring.

Hold nøglen i sit eget navnerum

En SecretStore læser API-nøglens Secret fra sit eget navnerum, så nøglen, lageret og de ExternalSecret-objekter, der bruger det, deler navnerum. Nøglen kan læse alle hemmeligheder i din tenant, og det kan alle, der kan læse Secrets i det navnerum, også. Brug et dedikeret navnerum til dem, og hold dets RBAC stramt. Eksemplerne på denne side bruger default.

Trin 2 — Opret SecretStore ​

SecretStore peger ESO mod Frostmolns opslags-endpoint. Brug CRD-gruppen external-secrets.io/v1 (ikke den ældre v1beta1). Erstat <TENANT_ID> med dit tenant-ID.

yaml
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: frostmoln
  namespace: default
spec:
  provider:
    webhook:
      url: 'https://api.frostmoln.cloud/api/v1/tenants/<TENANT_ID>/secrets/lookup?name={{ .remoteRef.key }}'
      headers:
        # KORT pr. hemmelighed: <secrets-entry-name>.<data-key>.
        # {{ .apikey }} gengiver hele kortet, og API'et returnerer 401 — brug nøglen .apikey.
        X-API-Key: '{{ .apikey.apikey }}'
      result:
        jsonPath: '$.secretValue'
      secrets:
        - name: apikey
          secretRef:
            name: frostmoln-api-key
            key: apikey

{{ .remoteRef.key }} i URL'en udfyldes pr. ExternalSecret med Frostmolns hemmelighedsnavn (Trin 3), så én SecretStore betjener alle dine hemmeligheder.

Trin 3 — Opret en ExternalSecret ​

Hver ExternalSecret knytter én Frostmoln-hemmelighed til én Kubernetes-Secret. remoteRef.key er Frostmolns hemmelighedsnavn; target.name er den Kubernetes-Secret, ESO opretter og holder synkroniseret.

yaml
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-secret
  namespace: default
spec:
  refreshInterval: 1m
  secretStoreRef: { name: frostmoln, kind: SecretStore }
  target: { name: my-secret-synced }
  data:
    - secretKey: value # nøglen inde i den synkroniserede Kubernetes-Secret
      remoteRef: { key: my-secret-name } # Frostmolns hemmelighedsnavn

ESO opretter Secret'en my-secret-synced med en value-nøgle, der indeholder den hentede hemmelighedsværdi. Monter den, eller referer til den fra din Pod som enhver anden Secret.

Opdateringsinterval ​

refreshInterval styrer, hvor ofte ESO henter på ny. Et kort interval udbreder rotationer hurtigere, men giver flere API-kald; et længere er lettere. Vælg pr. hemmelighed ud fra, hvor hurtigt en rotation skal nå dine arbejdslaster — et minut eller nogle få minutter er typisk.

Fastlås en bestemt version ​

Frostmoln-hemmeligheder er versionerede. Vil du fastlåse en version, så tilføj &version=N til SecretStore-URL'en (opret en ekstra SecretStore til den fastlåste hemmelighed):

yaml
url: 'https://api.frostmoln.cloud/api/v1/tenants/<TENANT_ID>/secrets/lookup?name={{ .remoteRef.key }}&version=2'

Uden &version læser ESO altid den nyeste version.

Det er fejlsikkert at slette en hemmelighed ​

Kører du fm secrets delete på en hemmelighed, som ESO synkroniserer, begynder opslaget at returnere en fejl (hemmeligheden går i afventende sletning). ESO's opdatering mislykkes (SecretSyncedError), og den lader det senest synkroniserede Kubernetes-Secret stå uændret — den tømmer det ikke. Dine arbejdslaster kører videre på den senest kendte fungerende værdi.

Gendan for at genoptage synkroniseringen

Mens hemmeligheden er slettet, kan ESO ikke opdatere den, og værdien i din klynge bliver forældet. Kør fm secrets recover <name> inden for gendannelsesvinduet for at gendanne den; ESO genoptager derefter synkroniseringen ved næste interval. Går gendannelsesvinduet, og hemmeligheden fjernes permanent, bliver opslaget ved med at mislykkes — opret hemmeligheden på ny for at genoptage.

Fejlfinding ​

Kontroller ExternalSecret-statussen med kubectl describe externalsecret <name>.

  • secret does not contain needed label — API-nøglens Secret mangler etiketten external-secrets.io/type: webhook (Trin 1).
  • 401 / uautoriseret — headerskabelonen er forkert. Den skal være {{ .apikey.apikey }} (<secrets-entry-name>.<data-key>); {{ .apikey }} gengiver hele kortet, og API'et afviser den. Kontroller også nøgleværdien, og at nøglen ikke er udløbet.
  • Arbejdslastidentitet: Secret'en frostmoln-token dukker ikke op — kontroller, at tilføjelsen Workload Identity er på klyngen, at ServiceAccount'en bærer annotationen og har en binding, og at der ikke fandtes en Secret med det navn i forvejen: tilføjelsen overskriver aldrig en Secret, den ikke selv har oprettet.
  • could not get secret data from provider — hemmelighedsnavnet eller tenant-ID'et er forkert, eller hemmeligheden er slettet / afventer sletning. Bekræft, at navnet kan slås op: fm secrets get <name>.
  • Intet synkroniseres overhovedet — kontroller, at SecretStore bruger external-secrets.io/v1, ikke v1beta1. På en klynge, du selv kører, så bekræft, at ESO kører (kubectl -n external-secrets get pods). På Frostmoln Administreret Kubernetes kan du ikke liste de pods: bekræft, at tilføjelsen er på klyngen (fm kubernetes cluster addons <cluster-id> eller fanen Tilføjelser), at den blev tilføjet for mere end nogle få minutter siden (hvis platformen meldte, at den ikke kunne starte synkroniseringen, så regn med længere tid: typisk højst en time, mere under platformsvedligeholdelse), og at dine noder kan nå ghcr.io og pkg-containers.githubusercontent.com.

Relateret ​