Hver eneste nedlastede JSON-nøkkel for en tjenestekonto i Google Cloud er en tikkende bombe i et Git-repo, en CI-variabel eller en bærbar PC. Den utløper ikke, den roterer ikke selv, og den fungerer akkurat like godt for en angriper som finner den som for utvikleren som lastet den ned. Workload Identity Federation (WIF) løser dette ved å la arbeidsbelastninger bevise sin identitet med noe de allerede har – en GitHub-token, en AWS-rolle, en Kubernetes-tjenestekonto – og bytte den mot et kortlevd Google Cloud-token i farten. Ingen fil å laste ned. Ingen hemmelighet å lagre.

I denne guiden setter vi opp Workload Identity Federation fra bunnen: vi bygger en identity pool, kobler på en OIDC-leverandør for GitHub Actions, strammer til attributtbetingelsene, binder poolen til en tjenestekonto og ruller ut en nøkkelfri pipeline til Cloud Run. Vi dekker også GKE-arbeidsbelastninger, arbeidsbelastninger i AWS og Azure, de vanligste fallgruvene, ni konkrete feilmeldinger du vil møte, hvordan du overvåker federerte identiteter i produksjon, og hvordan du migrerer eksisterende pipelines uten å miste tilgang midt i prosessen. Alt er testet mot gcloud CLI 530.0.0 og nyere, Terraform 1.9+ og Google-provideren 6.x.

Denne praksisen er ikke spesifikk for Google Cloud. Samme grunnidé, at en arbeidsbelastning beviser identiteten sin med noe den allerede har i stedet for en nedlastet hemmelighet, ligger bak OIDC-basert tillit i både AWS og Azure, og bak federasjonen mellom skytjenester som i økende grad kobles sammen. Lærer du prinsippet én gang, gjenkjenner du det raskt neste gang du setter opp tilgang mellom to systemer som ikke stoler på hverandre fra før.

Hva er Workload Identity Federation i Google Cloud?

Workload Identity Federation er Googles mekanisme for å la en ekstern identitet – altså en identitet som ikke er en Google-konto eller en nedlastet tjenestekontonøkkel – bevise hvem den er og få et kortlevd Google Cloud-tilgangstoken i retur. Prosessen går via Security Token Service (STS): arbeidsbelastningen henter et token fra sin egen identitetsleverandør (OIDC, SAML eller AWS-signerte credentials), sender det til STS, og får et federert Google-token tilbake. Dette tokenet kan brukes direkte, eller det kan brukes til å “impersonere” en tjenestekonto og få et vanlig tilgangstoken med tjenestekontoens rettigheter.

Byggeklossene er fire: en workload identity pool som samler eksterne identiteter, en provider inni poolen som definerer hvilken ekstern utsteder Google skal stole på, attributtmapping som oversetter eksterne claims (som repo-navn eller AWS-rolle) til Google-attributter, og til slutt en IAM-binding som faktisk gir rettigheter. Google dokumenterer selv at hensikten med federasjonen er å fjerne behovet for tjenestekontonøkler helt, ikke bare gjøre dem tryggere å oppbevare.

Det som skiller WIF fra en vanlig tjenestekontonøkkel, er levetiden på beviset. En JSON-nøkkel lever til du sletter den manuelt – ofte i årevis. Et WIF-token lever typisk i minutter til maks én time, og nytt bevis må hentes fra den opprinnelige identitetsleverandøren hver gang. Lekker tokenet, er skaden begrenset til et tidsvindu som allerede er i gang med å lukke seg.

Verdt å presisere: Workload Identity Federation fjerner ikke tjenestekontoer fra bildet. Google Clouds egen oversikt over tjenestekontoer sier rett ut at enkelte funksjoner, inkludert federasjon selv, krever at du har en tjenestekonto å impersonere. Det WIF fjerner er nøkkelfilen, ikke konseptet tjenestekonto. Du ender fortsatt opp med en tjenestekonto som har konkrete IAM-roller, men ingen hemmelig fil knyttet til den som kan kopieres eller lekkes.

Google Cloud støtter federasjon fra et bredt sett av eksterne identitetstyper, ikke bare GitHub. Tabellen under oppsummerer hvilke du vil møte mest i praksis, og hva hver av dem typisk brukes til.

IdentitetstypeTypisk brukstilfelleProtokoll
GitHub ActionsNøkkelfri utrulling fra CI/CD-pipelineOIDC
GitLab CINøkkelfri utrulling fra selvhostet eller GitLab.com-runnerOIDC
AWS IAM-rolleArbeidsbelastning i AWS som skal nå Google Cloud-ressurserAWS-signerte credentials
Azure-identitetArbeidsbelastning på en Azure VM som skal nå Google CloudAzure-token
Kubernetes/GKEPoder som skal nå Google Cloud-API-er uten montert nøkkelfilKubernetes service account-token
Generisk identitetsleverandørEgen IdP, lokalt Active Directory eller annen SAML/OIDC-kildeOIDC eller SAML 2.0

Hvorfor tjenestekontonøkler er et sikkerhetsproblem

Google Clouds egen sikkerhetsdokumentasjon er tydelig på risikomodellen: en nedlastet tjenestekontonøkkel er et langlevd hemmelig passord som kan kopieres, limes inn i feil fil, eller havne i en offentlig commit-historie uten at noen merker det før skaden er skjedd. En community-artikkel fra Google Cloud selv beskriver nettopp dette som kjernen i problemet med CI/CD-pipelines: hemmeligheter som ligger lagret som variabler, i secrets-managere eller i konfigurasjonsfiler, er alle angrepsflater som ikke eksisterer når identiteten i stedet bevises på flukt, som beskrevet i Google Cloud Communitys gjennomgang av CI/CD-sikkerhet.

Problemet forsterkes av at nøkler sjelden roteres i praksis. En nøkkel opprettet for tre år siden til et midlertidig skript, kjører ofte fortsatt, ubrukt og uovervåket, med fulle rettigheter intakt. Ingen varsles når den brukes fra et nytt sted, fordi den ikke er bundet til noen bestemt maskin, pipeline eller tidsramme. Med Workload Identity Federation forsvinner dette scenarioet: det finnes ingen fil å glemme, fordi det aldri eksisterte en fil i utgangspunktet. Spør deg selv hvor mange nøkler som faktisk ligger i prosjektene dine akkurat nå, og hvor mange av dem du egentlig husker hva de blir brukt til. For de fleste team er svaret ubehagelig høyt på det første spørsmålet, og ubehagelig lavt på det andre.

Google har i flere år aktivt presset utviklere mot federasjon i stedet for nøkler, særlig for GitHub Actions. Google Cloud publiserte en egen kunngjøring om nøkkelfri autentisering fra GitHub Actions, og budskapet har holdt seg uendret siden: eksporter aldri en langlevd JSON-nøkkel når du kan bruke OIDC og federasjon i stedet, se Googles kunngjøring om nøkkelfri GitHub Actions-autentisering. Dette er altså ikke en ny idé, men en praksis som har fått økt tyngde etter hvert som flere organisasjoner har blitt hacket via lekkede CI-hemmeligheter i andre skyer.

Forutsetninger: verktøy, versjoner og tilganger

Før du starter trenger du følgende på plass. Dette er ikke en liste du kan hoppe over halvveis, fordi flere steg senere forutsetter at IAM-rollene under faktisk er tildelt.

  • gcloud CLI versjon 530.0.0 eller nyere, logget inn med en konto som har roles/iam.workloadIdentityPoolAdmin eller eier-rettigheter på prosjektet.
  • Et Google Cloud-prosjekt med fakturering aktivert, samt IAM-, IAM Credentials- og Security Token Service-API-ene tilgjengelige for aktivering.
  • Terraform 1.9 eller nyere med Google-provideren (hashicorp/google) versjon 6.x, hvis du følger den infrastruktur-som-kode-varianten senere i guiden.
  • Et GitHub-repo med tilgang til å redigere workflow-filer under .github/workflows/, og admin-rettigheter til å sette opp secrets om nødvendig.
  • En eksisterende tjenestekonto i prosjektet (eller rettigheter til å opprette en), som skal impersoneres av den federerte identiteten.
  • Grunnleggende kjennskap til IAM-roller og -bindinger i Google Cloud. Hvis du er vant til å sette opp sikker tilgang til Cloud Storage, er mye av IAM-logikken gjenkjennelig her.

Sett av 45-60 minutter til hele oppsettet første gang, inkludert verifisering og en testkjøring av CI-pipelinen. Andre gang tar det deg under ti minutter, fordi du da kan kopiere Terraform-modulen fra det komplette eksemplet senere i artikkelen. Har du flere repoer eller team som skal migreres, kan du regne hele prosjektet som en halv arbeidsdag totalt, inkludert testing av hver enkelt pipeline etter at den er byttet om fra nøkkelbasert til federert autentisering.

Et praktisk poeng mange glemmer: du trenger prosjektets prosjektnummer, ikke prosjekt-ID-en, i ressursstien til poolen når du refererer til den fra en workflow-fil eller fra en IAM-binding. Prosjektnummeret finner du med gcloud projects describe mitt-prosjekt-id --format="value(projectNumber)", og det er verdt å lime inn i egne notater før du starter, siden feil her gir forvirrende feilmeldinger senere i prosessen.

Steg 1-2: Aktiver API-ene og opprett en identity pool

Start med å aktivere API-ene som Workload Identity Federation er avhengig av. Mangler en av disse, får du kryptiske PERMISSION_DENIED-feil lenger ned i prosessen, ikke en tydelig melding om at API-et er avslått.

# Steg 1: aktiver nodvendige API-er
gcloud services enable \
  iamcredentials.googleapis.com \
  sts.googleapis.com \
  iam.googleapis.com \
  --project=mitt-prosjekt-id

# Steg 2: opprett en workload identity pool
gcloud iam workload-identity-pools create "github-pipeline-pool" \
  --project="mitt-prosjekt-id" \
  --location="global" \
  --display-name="GitHub Actions pool" \
  --description="Nokkelfri CI/CD for produksjonsutrulling"

Poolen lever alltid i global-lokasjonen, uansett hvilken region tjenestene dine ellers kjører i. Det tar vanligvis noen minutter fra poolen er opprettet til den er synlig overalt i systemet, så vent litt før du går videre hvis du får en “ikke funnet”-feil i neste steg. Verifiser at poolen faktisk ligger der du tror før du går videre, slik at du ikke feilsøker et navneoppslag som egentlig er riktig:

gcloud iam workload-identity-pools describe "github-pipeline-pool" \
  --project="mitt-prosjekt-id" \
  --location="global" \
  --format="value(name,state)"

Får du ACTIVE tilbake i state-feltet, er poolen klar til bruk, og du kan gå videre til å opprette provideren.

Steg 3-4: Opprett en OIDC-leverandør for GitHub Actions

Inni poolen må du nå opprette en provider som peker til GitHubs egen OIDC-utsteder. Dette er punktet hvor mange kopierer eksempler uten å forstå hva de faktisk stoler på, og det er her du bestemmer hvem som i praksis får lov til å late som de er dette repoet.

# Steg 3-4: opprett OIDC-provideren med attributtbetingelse
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
  --project="mitt-prosjekt-id" \
  --location="global" \
  --workload-identity-pool="github-pipeline-pool" \
  --issuer-uri="https://token.actions.githubusercontent.com" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.ref=assertion.ref" \
  --attribute-condition="assertion.repository=='mitt-org/mitt-repo'"

Legg merke til --attribute-condition i kommandoen over. Uten den vil provideren stole på alle GitHub-repoer som bruker GitHubs OIDC-utsteder, ikke bare ditt eget. Det er den vanligste og mest alvorlige feilen i hele oppsettet, og vi kommer tilbake til den under fallgruver.

Steg 5-6: Attributtmapping og attributtbetingelser

Attributtmappingen over oversetter GitHubs JWT-claims til Google-attributter du senere kan bruke i IAM-bindinger og betingelser. assertion.sub inneholder typisk noe som repo:mitt-org/mitt-repo:ref:refs/heads/main, mens assertion.repository er det rene repo-navnet. Du kan mappe flere felter samtidig, blant annet miljønavn og workflow-navn, hvis du vil ha finere kontroll per gren eller per jobb. Vil du for eksempel bare tillate kjøringer fra et navngitt GitHub-miljø (som production i repoets egne miljøinnstillinger), kan du legge til attribute.environment=assertion.environment i mappingen og referere til det samme attributtet i betingelsen.

Neste skritt er å stramme til betingelsen ytterligere hvis du drifter flere miljøer fra samme repo. Et typisk mønster er å kreve at kun main-grenen får lov til å utrulle til produksjon, mens andre grener kun får tilgang til et test-prosjekt:

# Stram til betingelsen til kun main-grenen
--attribute-condition="assertion.repository=='mitt-org/mitt-repo' && assertion.ref=='refs/heads/main'"

Denne logikken speiler det du kanskje allerede kjenner fra OIDC-tillit i AWS EKS, hvor klyngens OIDC-utsteder på samme måte brukes til å bevise identiteten til en pod uten langlevde nøkler. Prinsippet er identisk, bare leverandøren er en annen.

Steg 7-8: Bind poolen til en tjenestekonto med IAM

Nå har du en federert identitet, men den har fortsatt ingen rettigheter i Google Cloud. Neste del er å gi den federerte identiteten lov til å impersonere en konkret tjenestekonto, og deretter gi selve tjenestekontoen de rollene den trenger (for eksempel roles/run.admin hvis du skal rulle ut til Cloud Run).

# Steg 7: tillat den federerte identiteten a impersonere tjenestekontoen
gcloud iam service-accounts add-iam-policy-binding \
  "[email protected]" \
  --project="mitt-prosjekt-id" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/PROSJEKT_NUMMER/locations/global/workloadIdentityPools/github-pipeline-pool/attribute.repository/mitt-org/mitt-repo"

# Steg 8: gi tjenestekontoen rettighetene den trenger
gcloud projects add-iam-policy-binding "mitt-prosjekt-id" \
  --member="serviceAccount:[email protected]" \
  --role="roles/run.admin"

Her finner du den samme feilkilden som i steg 3-4, bare i IAM-bindingen: principalSet:// gir tilgang til alle identiteter som matcher attributtet, mens principal:// binder til en spesifikk, enkelt verdi. Bruk principalSet når du vil tillate alle grener i ett repo, og principal når du vil låse til én bestemt kombinasjon av repo og gren.

Steg 9-10: Sett opp GitHub Actions-workflowen

Workflow-filen trenger to ting for å fungere med WIF: tillatelsen id-token: write, og handlingen google-github-actions/auth, som ber om et OIDC-token fra GitHub og bytter det mot et Google-token bak kulissene.

name: Deploy til Cloud Run
on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - id: auth
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: "projects/PROSJEKT_NUMMER/locations/global/workloadIdentityPools/github-pipeline-pool/providers/github-provider"
          service_account: "[email protected]"

      - uses: google-github-actions/deploy-cloudrun@v2
        with:
          service: min-tjeneste
          region: europe-north1
          image: europe-north1-docker.pkg.dev/mitt-prosjekt-id/app/min-tjeneste:${{ github.sha }}

Legg merke til permissions: id-token: write i toppen av filen. Uten denne linjen nekter GitHub jobben å be om et OIDC-token i det hele tatt, og du får en feilmelding lenge før forespørselen når Google. Som Googles egen dokumentasjon for bruk av GitHub Actions mot skyleverandører også påpeker, må API-ene IAM Credentials og STS være aktivert på prosjektsiden for at denne utvekslingen skal gå gjennom.

Test gjerne hele kjeden med en egen test-workflow som kun kjører gcloud auth list etter autentiseringssteget, før du kobler på selve utrullingskommandoen. Dette isolerer federasjonsdelen fra resten av pipelinen, slik at du vet om problemet ligger i selve WIF-oppsettet eller i noe annet, som mangler byggerettigheter eller en feil image-tag, hvis noe skulle gå galt.

Steg 11-12: Utvid til GKE-arbeidsbelastninger

Samme prinsipp gjelder inni en GKE-klynge, bare at identitetsleverandøren nå er klyngens egen Kubernetes-API, ikke GitHub. GKE har en innebygd variant kalt Workload Identity Federation for GKE, der en pod bruker sin Kubernetes-tjenestekonto til å få et Google-token, uten å montere en nøkkelfil i det hele tatt.

# Steg 11: koble en Kubernetes-tjenestekonto til en Google-tjenestekonto
gcloud iam service-accounts add-iam-policy-binding \
  "[email protected]" \
  --role="roles/iam.workloadIdentityUser" \
  --member="serviceAccount:mitt-prosjekt-id.svc.id.goog[min-navnerom/min-k8s-sa]"

# Steg 12: annoter Kubernetes-tjenestekontoen
kubectl annotate serviceaccount min-k8s-sa \
  --namespace min-navnerom \
  iam.gke.io/gcp-service-account=gke-app-sa@mitt-prosjekt-id.iam.gserviceaccount.com

Poden refererer deretter bare til min-k8s-sa i sin spec, og klientbibliotekene for Google Cloud finner automatisk det federerte tokenet uten ekstra konfigurasjon i applikasjonskoden. Hvis du har lest om hvordan feilkonfigurert IAM i GKE kan føre til privilegie-eskalering, er dette nøyaktig stedet du må være nøye: en for bred binding her gir i praksis alle poder i et navnerom samme rettigheter som tjenestekontoen.

Standard-tjenestekontoen til en nyopprettet klynge har ofte videre rettigheter enn den trenger, nettopp fordi den ble opprettet før noen tenkte gjennom hva akkurat denne arbeidsbelastningen faktisk skal gjøre. Lag derfor alltid en dedikert Kubernetes-tjenestekonto per applikasjon eller team, i stedet for å gjenbruke default-kontoen i navnerommet til alt. Dette gjør det også langt enklere å se i IAM-policyen hvilken arbeidsbelastning som faktisk står bak en gitt handling, i stedet for en uendelig liste av poder som alle deler samme identitet.

AWS- og Azure-arbeidsbelastninger uten nedlastet Google-nøkkel

Mange team har allerede arbeidsbelastninger i AWS eller Azure som også må nå Google Cloud-ressurser, for eksempel en EC2-instans som skriver til BigQuery, eller en Azure-funksjon som leser fra Cloud Storage. Her gjelder akkurat samme prinsipp som for GitHub Actions: i stedet for å laste ned en Google-nøkkel og lime den inn i AWS Secrets Manager, lar du AWS-rollen eller Azure-identiteten bevise seg selv direkte mot Googles STS.

# Opprett en AWS-provider inni samme pool-monster som for GitHub
gcloud iam workload-identity-pools providers create-aws "aws-provider" \
  --project="mitt-prosjekt-id" \
  --location="global" \
  --workload-identity-pool="aws-pipeline-pool" \
  --account-id="123456789012" \
  --attribute-mapping="google.subject=assertion.arn,attribute.aws_role=assertion.arn"

Når AWS-rollen eller Azure-identiteten er bundet til poolen på samme måte som i steg 7-8, trenger EC2-instansen eller Azure-VM-en aldri en nedlastet JSON-fil for å autentisere mot Google Cloud. Dette gjelder like godt for Azure VM-er, der Googles dokumentasjon for federasjon fra andre skyer beskriver en tilsvarende providertype basert på Azures egen identitetstoken. Fordelen er den samme uansett sky: ett sted mindre å lagre en hemmelighet, og ett sted mindre en angriper kan stjele den fra.

Vanlige misforståelser om hva Workload Identity Federation faktisk fjerner

Den første misforståelsen er at WIF gjør tjenestekontoer overflødige. Det gjør det ikke. Du trenger fortsatt en tjenestekonto med konkrete IAM-roller, akkurat som før. Det som endres, er at ingen lenger laster ned en fil for å bruke den. Identiteten bevises hver gang, direkte fra kilden.

Den andre misforståelsen er at federasjon automatisk betyr minste privilegium. Det gjør det ikke. Hvis du binder en hel organisasjons GitHub-kontoer til en tjenestekonto med eierrolle på prosjektet, har du bare byttet ut en lekkasjerisiko mot en konfigurasjonsrisiko. Rettighetene må fortsatt avgrenses nøye, uavhengig av om beviset er en nøkkel eller et federert token.

Den tredje er troen på at federasjon er en engangsoperasjon uten løpende vedlikehold. I praksis må attributtbetingelser oppdateres når repoer flyttes eller renames, nye miljøer legges til, og gamle providere som ikke lenger er i bruk bør ryddes vekk på samme måte som du ville ryddet opp i gamle nøkler. Federasjon fjerner én risikokilde, ikke behovet for løpende IAM-hygiene.

Komplett eksempel: nøkkelfri pipeline til Cloud Run

Sett sammen blir dette et komplett, fungerende prosjekt. Under er samme oppsett som Terraform, slik at hele poolen, provideren og bindingene ligger versjonskontrollert sammen med resten av infrastrukturen, i stedet for som løse gcloud-kommandoer noen kjørte en gang for lenge siden. Fordelen med denne tilnærmingen er at endringer i attributtbetingelser eller nye providere går gjennom samme code review-prosess som resten av koden, i stedet for å bli gjort direkte i konsollen av en enkeltperson uten spor i historikken.

resource "google_iam_workload_identity_pool" "github_pool" {
  project                   = "mitt-prosjekt-id"
  workload_identity_pool_id = "github-pipeline-pool"
  display_name              = "GitHub Actions pool"
}

resource "google_iam_workload_identity_pool_provider" "github_provider" {
  project                            = "mitt-prosjekt-id"
  workload_identity_pool_id          = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "github-provider"
  attribute_mapping = {
    "google.subject"       = "assertion.sub"
    "attribute.repository" = "assertion.repository"
    "attribute.ref"        = "assertion.ref"
  }
  attribute_condition = "assertion.repository=='mitt-org/mitt-repo'"
  oidc {
    issuer_uri = "https://token.actions.githubusercontent.com"
  }
}

resource "google_service_account_iam_member" "wif_binding" {
  service_account_id = "projects/mitt-prosjekt-id/serviceAccounts/[email protected]"
  role                = "roles/iam.workloadIdentityUser"
  member              = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github_pool.name}/attribute.repository/mitt-org/mitt-repo"
}

Denne modulen, pluss workflow-filen fra steg 9-10, utgjør hele pipelinen fra commit til kjørende tjeneste på Cloud Run: push til main, GitHub Actions ber om et OIDC-token, Google bytter det mot et federert token, tokenet impersonerer deploy-sa, og den tjenestekontoen har akkurat nok rettigheter til å bygge og rulle ut det nye imaget. På ingen tidspunkt i denne kjeden eksisterer det en nedlastet nøkkel noe sted.

Legg prosjektet i en egen mappe med tre filer: main.tf for Terraform-modulen over, .github/workflows/deploy.yml for workflow-filen, og en kort README.md som dokumenterer hvilket repo og hvilken gren som faktisk har tillatelse til å utløse utrulling. Den siste filen er lett å glemme, men den er det som gjør at neste person på teamet forstår attributtbetingelsen uten å måtte lese gjennom Terraform-koden linje for linje. Kjør terraform init og terraform apply én gang for å opprette poolen og bindingene, push deretter til main-grenen, og se utrullingen skje uten at noen person eller fil noensinne håndterte en hemmelig nøkkel.

Vanlige fallgruver ved oppsett av Workload Identity Federation

De fleste problemene med WIF kommer ikke fra komplisert kode, men fra små, usynlige feil i konfigurasjonen. Forskjellen fra en vanlig kodefeil er at disse feilene ofte ikke gir deg et varsel i det hele tatt: systemet fungerer akkurat som forventet, bare med et videre tillitsområde enn du trodde du satte opp. Her er de som dukker opp oftest, rangert etter hvor alvorlig konsekvensen er hvis du går på dem.

  • Manglende attributtbetingelse. Uten --attribute-condition stoler provideren på alle repoer som bruker samme OIDC-utsteder, ikke bare ditt eget. Dette er den klart farligste fallgruven, fordi den ikke gir noen feilmelding – alt fungerer helt fint, bare for feil personer også.
  • Forveksling av principal og principalSet. Den første binder til nøyaktig én identitet, den andre til alle som matcher et attributt. Bruker du principal der du mente principalSet, får du en konstant “permission denied” selv om alt annet ser riktig ut.
  • For bred service account-impersonering. Å gi hele organisasjonen tilgang til å impersonere en tjenestekonto med eierrettigheter, gjør WIF like risikabelt som den nøkkelen du prøvde å fjerne.
  • Glemt id-token: write i workflow-filen. Uten denne tillatelsen får GitHub Actions aldri lov til å be om et OIDC-token i utgangspunktet.
  • Gamle nøkler blir liggende aktive. Mange setter opp federasjon parallelt med den gamle nøkkelen “for sikkerhets skyld”, og glemmer så å deaktivere og slette den gamle nøkkelen. Da har du løst null av det opprinnelige problemet.
  • Feil forventning til tokenets levetid. GitHubs egne OIDC-tokener lever typisk rundt fem minutter og har et dokumentert maksimum på ti minutter som ikke kan endres. En jobb som tar lengre tid enn det før den faktisk bruker tokenet, vil mislykkes.
  • Ventetid etter oppretting. En nyopprettet pool eller provider er ikke alltid synlig momentant i hele systemet. Noen minutters forsinkelse før første forsøk sparer deg for unødvendig feilsøking.

Feilsøking: typiske feilmeldinger og løsninger

Når noe går feil, er meldingene fra Google ofte korte og generiske, og de forteller sjelden hvilket av de fire byggeklossene (pool, provider, attributtmapping eller IAM-binding) som faktisk er feilkonfigurert. Strategien som fungerer best, er å verifisere hvert lag isolert, fra poolen og utover, i stedet for å gjette basert på feilteksten alene. Her er de du mest sannsynlig møter, og hva de egentlig betyr.

FeilmeldingSannsynlig årsakLøsning
permission_denied: The caller does not have permissionManglende eller feil IAM-binding på tjenestekontoenSjekk at roles/iam.workloadIdentityUser er bundet til riktig principalSet
failed to generate Google Cloud federated tokenWorkflow-filen mangler id-token: writeLegg til tillatelsen i toppen av workflow-filen
invalid_grant: Invalid JWT / audience mismatchProvider-ressursnavnet i workflowen matcher ikke faktisk providerKopier full ressursstien på nytt fra gcloud iam workload-identity-pools providers describe
NOT_FOUND: Requested entity was not foundPoolen eller provideren er for nyopprettet til å ha propagertVent 2-5 minutter og prøv igjen
Attribute condition evaluation failedSyntaksfeil i uttrykket for attributtbetingelsenTest uttrykket isolert og sjekk at feltnavn matcher attributtmappingen
403 fra Cloud Run eller Cloud Build under utrullingTjenestekontoen mangler den spesifikke rollen som trengs, for eksempel run.adminLegg til riktig rolle med minste nødvendige omfang
Token expired before useJobben brukte lenger tid enn tokenets levetid på 5-10 minutterFlytt autentiseringssteget nærmere der tokenet faktisk brukes
Pod i GKE får 403 mot Google API-erKubernetes-tjenestekontoen mangler riktig annotasjon eller bindingVerifiser iam.gke.io/gcp-service-account-annotasjonen og IAM-bindingen
principalSet-binding virker ikke etter endringIAM-policyer kan ta litt tid å propagere i store prosjekterVent noen minutter, verifiser med get-iam-policy at bindingen faktisk er lagret

Avanserte tips for innstramming og skalering

Når grunnoppsettet fungerer, er neste skritt å gjøre det vanskeligere å misbruke, ikke bare lettere å bruke. Google Cloud Identitys egen oversikt over beste praksis for WIF legger vekt på nøyaktig dette: federasjon er bare så trygg som attributtbetingelsene du setter, se Googles anbefalinger for beste praksis med Workload Identity Federation. Tenk på selve federasjonsoppsettet som en tillitsgrense du må forsvare på samme måte som en brannmurregel, ikke som en engangskonfigurasjon du setter og glemmer.

  • Egne providere per miljø. Lag separate providere for staging og produksjon, med egne attributtbetingelser, slik at en kompromittert test-pipeline aldri kan nå produksjonens tjenestekonto.
  • Kortere tokenlevetid enn standarden. Standard levetid på en impersonert tjenestekontos tilgangstoken er 3600 sekunder (én time) når ingenting annet er spesifisert. Sett den lavere for høyrisiko-jobber med SERVICE_ACCOUNT_TOKEN_LIFETIME.
  • Overvåk impersonering i Cloud Audit Logs. Sett opp varsler på GenerateAccessToken-hendelser fra uventede prinsipaler, så du fanger opp misbruk nær sanntid i stedet for i et kvartalsvis sikkerhetsmøte.
  • Kombiner med VPC Service Controls hvis tjenestekontoen har tilgang til sensitive data, slik at selv et gyldig, federert token ikke kan hente data utenfor den definerte perimeteren.
  • Håndtér nøkkelsperring organisasjonsvidt. Organisasjonspolicyen iam.disableServiceAccountKeyCreation kan tvinge gjennom at ingen nye tjenestekontonøkler kan opprettes i det hele tatt, slik at federasjon blir den eneste veien inn, ikke bare den foretrukne.
  • Automatiser opprydding av gamle nøkler. Skriv et lite skript som lister alle tjenestekontonøkler eldre enn 90 dager og flagger dem for sletting, i stedet for å stole på at noen husker å gjøre det manuelt.

Overvåking og revisjon av federerte identiteter i produksjon

Et oppsett som fungerer i dag, kan stille feil spørsmål om seks måneder, når et repo er omdøpt, et team er lagt ned eller en gammel provider aldri ble ryddet bort. Derfor bør du behandle overvåking av federerte identiteter som en like naturlig del av driften som overvåking av CPU-bruk eller diskplass, ikke som en engangsoppgave du gjør ferdig på installasjonsdagen.

Cloud Audit Logs fanger opp hver gang en federert identitet ber om et token, inkludert hvilket attributt som ble matchet og hvilken tjenestekonto som ble impersonert. Et enkelt filter i Cloud Logging lar deg se nøyaktig hvilke repoer, grener eller eksterne roller som faktisk har brukt federasjonen den siste måneden, og dermed også hvilke providere som aldri er brukt og trygt kan fjernes.

# Filtrer Cloud Audit Logs for tokengenerering via federerte identiteter
gcloud logging read \
  'protoPayload.methodName="GenerateAccessToken" AND
   protoPayload.authenticationInfo.principalSubject:"workloadIdentityPools"' \
  --project="mitt-prosjekt-id" \
  --limit=50 \
  --format="table(timestamp, protoPayload.authenticationInfo.principalSubject)"

Sett opp en logg-basert varsling i Cloud Monitoring på denne typen hendelser utenfor normal arbeidstid, eller fra en attributtkombinasjon du ikke forventer å se. En GitHub Actions-jobb som trigger utrulling til produksjon klokken fire om natten en søndag, er sjelden et normalt mønster, og bør flagges for gjennomgang selv om selve autentiseringen var teknisk gyldig. Kombiner dette med en enkel kvartalsvis gjennomgang av alle providere og attributtbetingelser i hver pool, slik at konfigurasjonen holder seg i sync med hvilke team og repoer som faktisk er aktive.

Denne typen revisjon er spesielt verdt å prioritere i organisasjoner som jevnlig slår sammen eller legger ned repoer, siden en attributtbetingelse som pekte på et repo som senere ble slettet eller omdøpt, i praksis blir en død binding som bare roter til IAM-policyen uten å utgjøre en reell risiko i seg selv. Rydd den vekk likevel, av samme grunn som du rydder bort en ubrukt brannmurregel: en konfigurasjon ingen lenger forstår hensikten med, er vanskelig å stole på neste gang noe faktisk går galt.

Workload Identity Federation mot tjenestekontonøkler

Satt opp mot hverandre blir forskjellen tydelig på nesten alle punkter som betyr noe for sikkerhet og drift.

EgenskapTjenestekontonøkkel (JSON)Workload Identity Federation
Levetid på bevisetUbegrenset til manuell slettingMinutter til maks én time
LagringsstedFil, secrets-manager eller CI-variabelIngen – bevises på forespørsel
RotasjonManuell, sjelden gjort i praksisAutomatisk, hver forespørsel
Eksponering ved lekkasjeFull tilgang til kontoen inntil nøkkelen slettesBegrenset til tokenets korte levetid
SporbarhetVanskelig å spore til kilde ved misbrukHver utveksling er knyttet til en identitet fra ekstern IdP
OppsettskompleksitetLav (last ned, lim inn)Moderat (pool, provider, attributtbetingelser)

Den eneste reelle fordelen nøkler har, er at de er raskere å sette opp første gang. Den fordelen forsvinner fort når du regner inn tiden du bruker på å rotere, overvåke og til slutt rydde opp etter dem over flere år, sammenlignet med en engangskostnad på under en time for Workload Identity Federation. Legg også merke til at oppsettskompleksiteten med WIF er en engangskost per repo eller miljø, mens risikoen ved nøkler øker jevnt og trutt for hver dag nøkkelen forblir aktiv og ubrukt i et skap et sted.

Slik migrerer du eksisterende pipelines bort fra nøkler

Migrering bør aldri skje som et stort kutt der du sletter alle nøkler samme dag. Gjør det trinnvis, slik at du alltid har en fallback mens du verifiserer at det nye oppsettet faktisk virker i produksjon. Et team med ti mikrotjenester og like mange nøkler bør regne med flere uker fra første migrerte tjeneste til siste nøkkel er slettet, ikke én enkelt helg, selv om selve WIF-oppsettet for hver tjeneste bare tar minutter.

  • Kartlegg alle aktive tjenestekontonøkler i prosjektet, inkludert de du har glemt, med gcloud iam service-accounts keys list for hver konto.
  • Bygg og test WIF-oppsettet parallelt med eksisterende nøkkelbasert autentisering, på en gren eller et miljø som ikke påvirker produksjon.
  • Rull ut den nye pipelinen til ett team eller én tjeneste først, og overvåk Cloud Audit Logs for å bekrefte at autentiseringen faktisk går via federasjon.
  • Når du har bekreftet stabil drift i minst én uke, deaktiver (ikke slett ennå) den gamle nøkkelen for den tjenesten.
  • Vent en ny driftsperiode uten feilmeldinger knyttet til den deaktiverte nøkkelen, før du sletter den permanent.
  • Gjenta for neste team, og aktiver til slutt iam.disableServiceAccountKeyCreation på organisasjonsnivå når alle er migrert.

Denne rekkefølgen er langsommere enn å bare slette alt på en fredag, men den er også grunnen til at ingen ringer deg i helgen fordi en produksjonstjeneste plutselig mistet tilgangen sin. Samme tankegang går igjen i hvordan de fleste team i dag også hardener container-sikkerhet i Kubernetes: trinnvis innstramming, ikke et nullstill-alt-i-morgen-vedtak. Før du begynner å slette noe som helst, bør du også dokumentere hvilke nøkler som faktisk var i bruk og av hvem, slik at du har et papirspor hvis noe likevel går galt underveis i migreringen.

Ofte stilte spørsmål

Må jeg bruke Terraform, eller holder gcloud CLI?
Begge fungerer like godt teknisk. Terraform gir deg versjonskontroll og gjenbruk på tvers av prosjekter, mens gcloud CLI er raskere for et enkeltstående oppsett eller en test.

Fungerer Workload Identity Federation med GitLab CI, ikke bare GitHub Actions?
Ja. Google Cloud lister GitLab blant de støttede deployment-tjenestene, forutsatt at du konfigurerer riktig OIDC-tillit og attributtmapping mot GitLabs egen token-utsteder på samme måte som for GitHub.

Kan arbeidsbelastninger i AWS og Azure også bruke dette uten å laste ned en Google-nøkkel?
Ja, Google Cloud støtter federasjon direkte fra AWS IAM-roller og Azure-identiteter, slik at verken AWS- eller Azure-arbeidsbelastninger trenger en nedlastet JSON-nøkkel for å nå Google Cloud-ressurser.

Hva skjer hvis GitHub-tokenet lekker ut av en logg?
Skaden er begrenset til gjenværende levetid på tokenet, som normalt er rundt fem minutter og aldri mer enn ti. Det er fortsatt en risiko du skal unngå, men den er ikke i nærheten av en lekket nøkkel som er gyldig til du manuelt sletter den.

Trenger jeg en egen pool for hver applikasjon?
Nei. Du kan ha flere providere inni samme pool, og skille applikasjoner eller miljøer med egne attributtbetingelser i stedet for egne pooler. Separate pooler gir mer isolasjon, men er ikke strengt nødvendig for de fleste team.

Kan jeg bruke WIF for lokal utvikling på min egen maskin?
Det er mulig via gcloud auth application-default login, men for lokal utvikling er en personlig, kortlevd brukerautentisering normalt enklere enn å sette opp en ekstern IdP for din egen laptop.

Hvorfor får jeg “permission denied” selv om IAM-bindingen ser riktig ut?
De to vanligste årsakene er at bindingen bruker principal der den skulle brukt principalSet, eller at ressursstien til poolen eller provideren har en skrivefeil i prosjektnummeret. Verifiser alltid med gcloud iam service-accounts get-iam-policy.

Må jeg slette alle gamle tjenestekontonøkler med én gang etter migrering?
Nei, og du bør ikke. Deaktiver først, overvåk i en periode for å bekrefte at ingenting fortsatt bruker nøkkelen, og slett den permanent først etter det. Dette er tryggere enn en umiddelbar sletting som kan stoppe en skjult avhengighet du ikke visste om.

Koster Workload Identity Federation noe ekstra å bruke?
Selve federasjonstjenesten har ingen egen kostnad utover det du allerede betaler for de underliggende Google Cloud-tjenestene, som Cloud Run eller GKE. Du betaler ikke per generert token eller per provider, så oppsettet er like gratis i bruk som det er i oppsett.