Gå til hovedindhold

Udrulnings-secrets: OIDC-føderation

fremforge vil helst ikke opbevare dine produktions-secrets. Langlivede udrulningslegitimationsoplysninger (AWS_ACCESS_KEY_ID, AZURE_CLIENT_SECRET, GCP_SA_KEY, …), der gemmes i CI-systemers secret-lagre, er en evig rotationsopgave og en evig risiko ved et brud. Den moderne løsning er OIDC-føderation: dit workflow beder CI-serveren om et kortlivet identitetstoken, din clouds IAM verificerer tokenet og giver en kortlivet legitimationsoplysning tilbage. fremforge leverer det hele vejen.

Sådan virker det

Hvert CI-job, der kører på fremforge, får et nyudstedt JSON Web Token signeret af fremforges runner-OIDC-udsteder på https://frem.sh/_app/runner/oidc. Tokenet indeholder claims, der beskriver jobbets kontekst, repository, ref, workflow og eventuelt miljø, og din clouds IAM-tillidspolitik afgør ud fra de claims, om der skal udstedes legitimationsoplysninger.

    sequenceDiagram
    autonumber
    actor User
    participant FF as fremforge<br/>runner-OIDC issuer
    participant Pod as runner VM
    participant Cloud as Your cloud's<br/>IAM • STS / WIF / …

    User->>FF: git push
    FF->>Pod: dispatch job — mint OIDC JWT
    Pod->>Cloud: "Here's my JWT, give me credentials"
    Cloud->>Cloud: Verify JWT against fremforge JWKS<br/>+ check trust policy claims
    Cloud->>Pod: 1h credentials
    Pod->>Cloud: deploy / read / write
  

Claims, som din clouds tillidspolitik kan matche på:

ClaimEksempelHvad det identificerer
isshttps://frem.sh/_app/runner/oidcfremforge selv
audsts.amazonaws.comhvilken cloud du godkender dig over for
subrepo:my-org/my-repo:environment:production (når environment: er erklæret)
repo:my-org/my-repo:ref:refs/heads/main (uden miljø)
hvilken workflow-kørsel
repositorymy-org/my-reporepoets navn
repository_ownermy-orgorganisationens slug
refrefs/heads/maingit-ref
environmentproductionmiljønavn erklæret i workflowet
actoraliceForgejo-brugernavnet, der startede kørslen

De følger formen på GitHub Actions’ claims, så eksisterende tillidspolitikker og actions som actions/configure-aws-credentials / azure/login / google-github-actions/auth virker uden ændringer.

Discovery-URL

Peg din cloud på:

  • Udsteder-URL: https://frem.sh/_app/runner/oidc
  • JWKS-URL: https://frem.sh/_app/runner/oidc/.well-known/jwks.json
  • Discovery-dokument: https://frem.sh/_app/runner/oidc/.well-known/openid-configuration

Alle tre kan læses anonymt.

Mønstre for workflows

Erklæring af et miljø

jobs:
  deploy:
    runs-on: fremforge-runner
    environment: production
    permissions:
      id-token: write    # required to mint the OIDC JWT
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/fremforge-deploy-prod
          aws-region: eu-central-1
      - run: aws s3 sync ./build s3://my-prod-bucket/

environment: production ændrer OIDC-claimet sub til repo:my-org/my-repo:environment:production, så din tillidspolitik kun kan give adgang til jobs, der er erklæret som production.

Uden et miljø

Når du ikke erklærer environment:, falder sub tilbage til repo:<owner>/<repo>:ref:<ref>. Tillidspolitikker, der matcher på ref, virker på samme måde som på GitHub. fremforges miljøgate gælder ikke (den gater kun workflows, der erklærer et miljø), så tillidspolitikken på cloudsiden er dit eneste værn.

Eksempler på tillidspolitikker

AWS

IAM-tillidspolitik for en OIDC-fødereret rolle:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Federated": "arn:aws:iam::123456789012:oidc-provider/frem.sh/_app/runner/oidc"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "frem.sh/_app/runner/oidc:aud": "sts.amazonaws.com"
      },
      "StringLike": {
        "frem.sh/_app/runner/oidc:sub": "repo:my-org/my-repo:environment:production"
      }
    }
  }]
}

Opsætning én gang: registrér fremforge som OIDC-udbyder:

aws iam create-open-id-connect-provider \
  --url https://frem.sh/_app/runner/oidc \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list $(curl -s https://frem.sh/_app/runner/oidc/.well-known/jwks.json | jq -r '.keys[0].x5t')

Azure (Workload Identity Federation)

Registrér den fødererede legitimationsoplysning på en App Registration i Entra ID:

az ad app federated-credential create \
  --id $APP_OBJECT_ID \
  --parameters '{
    "name": "fremforge-prod-deploy",
    "issuer": "https://frem.sh/_app/runner/oidc",
    "subject": "repo:my-org/my-repo:environment:production",
    "audiences": ["api://AzureADTokenExchange"]
  }'

Workflow:

- uses: azure/login@v2
  with:
    client-id: ${{ vars.AZURE_CLIENT_ID }}
    tenant-id: ${{ vars.AZURE_TENANT_ID }}
    subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

GCP (Workload Identity Federation)

gcloud iam workload-identity-pools providers create-oidc fremforge-provider \
  --workload-identity-pool=fremforge-pool \
  --issuer-uri="https://frem.sh/_app/runner/oidc" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.environment=assertion.environment" \
  --attribute-condition="attribute.environment == 'production'"

Workflow:

- uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/fremforge-pool/providers/fremforge-provider
    service_account: deploy@my-project.iam.gserviceaccount.com

T Cloud Public (OTC IAM Identity Provider)

T Cloud Public bruger IAM Identity Providers og token-udveksling:

  1. Identity Provider i OTC Console → IAM → Identity Providers → Create:
    • Name: fremforge-runner-oidc
    • Protocol: OpenID Connect
    • Issuer URL: https://frem.sh/_app/runner/oidc
    • JWKS URL: https://frem.sh/_app/runner/oidc/.well-known/jwks.json
    • Client ID: iam.eu-de.otc.t-systems.com (eller dit projekts STS-audience)
  2. Mapping-regler, der oversætter claims til en fødereret bruger. Eksempel, der mapper et repo:my-org/my-repo:environment:production-subject til OTC-gruppen deploy-prod:
[
  {
    "local": [
      { "user": { "name": "{0}" } },
      { "group": { "name": "deploy-prod" } }
    ],
    "remote": [
      { "type": "sub" },
      { "type": "environment", "any_one_of": ["production"] }
    ]
  }
]
  1. Workflow: udveksl JWT’et til et OTC-token via IAM’s endpoint til token-udveksling, og brug derefter den returnerede X-Subject-Token til ethvert OTC API-kald.

Styr, hvilke refs der kan udrulle hvorhen

OIDC-føderation fjerner behovet for at GEMME langlivede secrets, men du skal stadig beslutte, hvilke branches der kan udrulle til hvilket miljø. Et workflow på en feature-branch KAN udstede et JWT, der hævder environment: production; det er gaten, der forhindrer, at JWT’et accepteres.

fremforge tilbyder to gates, og du bør bruge begge som forsvar i dybden.

Gate 1: tillidspolitik på cloudsiden (altid påkrævet)

Din clouds IAM-tillidspolitik er den endelige autoritet. Lås sub-claimet til formen repo+miljø, OG lås ref-claimet til den eller de branches, miljøet må udrulles fra. Eksempel for AWS:

{
  "Condition": {
    "StringEquals": {
      "frem.sh/_app/runner/oidc:sub": "repo:my-org/my-repo:environment:production"
    },
    "StringLike": {
      "frem.sh/_app/runner/oidc:ref": "refs/heads/main"
    }
  }
}

En feature-branch KAN udstede JWT’et, men AWS nægter at udstede legitimationsoplysninger, fordi ref er refs/heads/feature/foo i stedet for refs/heads/main. Det er det grundmønster, GitHub anbefaler, og det virker fra dag ét.

Gate 2: fremforges mønstre for udrulningsbranches pr. miljø (anbefalet)

Under Administration → Miljøer (frem.sh/<org>/_admin/environments) konfigurerer du hvert miljø på GitHub-vis. Tre sektioner pr. miljø:

Branches og tags til udrulning: glob-mønstre, der matches mod den git-ref, der startede kørslen. Eksempler (får automatisk præfikset refs/heads/ som kortform for branches):

NavnMønstreVirkning
productionmainkun main-branchen
stagingmain
develop
release/*
main, develop og release/*-branches
pr-preview*enhver branch (gaten på cloudsiden er den reelle autoritet)
releaserefs/tags/v[0-9]+.*kun versionstags (eksplicit præfiks refs/tags/)

Workflows, der erklærer environment: production, afvises ved afsendelse, når den ref, der startede dem, ikke matcher. Workflows UDEN en environment:-erklæring kører uden begrænsning, så almindelig CI på feature-branches fortsat virker.

Miljøsecrets: krypterede, afgrænset til miljøet og injiceret som workflow-${{ secrets.NAME }} OG som almindelige miljøvariabler, når workflowets environment: matcher. Dækker de secrets uden for cloud-IAM (API-nøgler til tredjeparter, signeringsnøgler, webhook-secrets), som OIDC-føderation ikke løser.

Miljøvariabler: værdier, der ikke er hemmelige, afgrænset til miljøet. Samme injektionsmodel.

Hvad med godkendelsesgates?

GitHub Actions Environments har funktionen “Required reviewers”: et job sættes på pause efter merge, indtil N personer klikker Approve i Actions-brugerfladen. fremforge leverer bevidst ikke dette, fordi Forgejo allerede har en stærkere gate på samme tidspunkt i forløbet: branch-beskyttelse på main med CODEOWNERS på .forgejo/workflows/* kræver review af en pull request, før et workflow, der kan udrulle, lander. I 99 %-tilfældet (1 pull request = 1 udrulning) ER Forgejos review af pull requesten godkendelsen af udrulningen. Kunder, der har brug for GitHub-tilfældet (1 pull request kan give N uafhængige udrulninger med separate godkendere pr. udrulning), kan oprette en issue, og vi prioriterer godkendere ved udrulning (planlagt) ud fra den faktiske efterspørgsel.

fremforges gate forhindrer, at JWT’et overhovedet udstedes. Gaten på cloudsiden forhindrer, at et udstedt JWT accepteres. Kombinér begge: selv hvis en fremtidig fejl i fremforge lod en afvist afsendelse slippe igennem, nægter cloudens IAM stadig at udstede legitimationsoplysninger. Og selv hvis en kundes tillidspolitik i cloudsiden har en tastefejl og accepterer et bredere ref-mønster end tiltænkt, har fremforge stadig nægtet at udstede JWT’et.

Doven onboarding

Når du erklærer environment: x i et workflow, men endnu ikke har konfigureret en environments-række for x, tillader fremforge afsendelsen i stedet for at afvise den. Det er bevidst, så en ny kundes workflows ikke går i stykker i det øjeblik, de erklærer et miljø; din tillidspolitik på cloudsiden er sikkerhedsnettet, indtil du tilføjer rækken i fremforge. Når en række findes, håndhæves gaten.

Låst tilstand: kun beskyttede branches

I miljøer med høje sikkerhedskrav, hvor du vil forbyde CI-kørsel på ubeskyttede refs HELT (ikke kun gate udrulningslegitimationsoplysninger), skal du slå Administration → Miljøer → Organisationsdækkende lukning → Kør kun workflows på beskyttede branches til:

Kør kun workflows på beskyttede branches

Når den er slået til, nægter platformen at sende ETHVERT workflow af sted, hvis udløsende branch IKKE står på repoets liste over beskyttede branches (konfigureret via Forgejos indbyggede Indstillinger → Grene → Tilføj ny regel). Det omfatter almindelig CI (tests, lint): intet kører på ubeskyttede branches. Nyttigt i regulerede miljøer, hvor du vil have nul kodekørsel uden for gennemgåede refs; anbefales ikke til almindelig udvikling, fordi det ødelægger test af feature-branches.

Slår du det til, vil du typisk beskytte mønstrene main, develop og release/* i Forgejo, så dine almindelige udviklingsbranches stadig kan køre CI.

Anbefalet opsætning

For typiske SaaS- og produktteams:

  1. Slå ikke udrulningsgaten med kun beskyttede branches til; lad almindelig CI køre på feature-branches.
  2. Konfigurér miljøer under Administration → Miljøer med passende mønstre for branches og tags til udrulning for hvert (production, staging osv.).
  3. Konfigurér tillidspolitikker i cloud med både sub-betingelser (låst til miljø) OG ref-betingelser (låst til branch).
  4. Branch-beskyt main i Forgejo med CODEOWNERS-dækning af .forgejo/workflows/*, så ændringer i workflows kræver review.

For regulerede miljøer og låste miljøer (bank, forsvar, sundhed):

  1. Slå udrulningsgaten med kun beskyttede branches til.
  2. Konfigurér miljøer til finkornet gating pr. miljø oven i.
  3. Samme opsætning af tillidspolitikker på cloudsiden som ovenfor.

Denne kombination svarer til den model for udrulningsgates, som GitHub Enterprise og AWS anbefaler (kræv miljøer ved udrulning + kun beskyttede branches), plus den valgfri låsekontakt for regulerede tenants.

Sammenligning: hvad fremforge gemmer, og hvad din cloud gemmer

Langlivede secretsOIDC-føderation (denne side)
Hvor udrulningslegitimationsoplysninger liggerIndstillinger → Secrets i fremforgeDin clouds IAM. fremforge ser dem aldrig.
Levetid for legitimationsoplysningerIndtil du roterer1 time (kan konfigureres pr. tillidspolitik)
Hvis fremforge kompromitteresAngriberen har dine AWS-nøglerAngriberen kan udstede OIDC-JWT’er, men tillidspolitikken på cloudsiden begrænser, hvad de JWT’er kan (pr. miljø, pr. repo, pr. ref)
RotationsopgaveHvert kvartal pr. secret pr. cloudIngen, nøgler roteres for hvert job
RevisionssporManuelt: hvem eksporterede secreten hvornårHver OIDC-udstedelse står i audit_events + din clouds CloudTrail/Activity Log

Begrænsninger

  • environment: i objektform (med name: + url:) understøttes efter navn; url: fortolkes, men vises i øjeblikket ikke som claim.
  • Miljønavne udfoldet fra en matrix (environment: ${{ matrix.target }}) opløses ikke på tidspunktet for OIDC-udstedelsen, og der udsendes intet environment-claim. Brug en hardkodet environment: pr. matrix-job, hvis du har brug for tillidspolitikker baseret på miljø-claimet.
  • Gates med påkrævede godkendere pr. miljø (som GitHub Environments’ funktion “wait for approval”) er planlagt som opfølgning i fase 2; i dag er håndhævelsen binær (beskyttet branch ja/nej).

Se også