Hoppa till huvudinnehållet

Secrets och miljövariabler

Secrets är krypterade värden som skickas in i arbetsflödets jobb som miljövariabler. De går bara att skriva efter att de har skapats. Värdet kan aldrig läsas tillbaka via gränssnittet eller API:t. Den här sidan beskriver nivåer, hur du skapar secrets, användning i arbetsflöden, rotation och gränser.

Secrets krypteras i vila med T Cloud Public DEW KMS och dekrypteras först när jobbet körs på runnern.

Secrets på organisationsnivå hanteras i organisationens administration på frem.sh/<org>/_admin/secrets. Secrets på repo-nivå finns under varje repos Inställningar → Actions → Hemligheter i Forgejo. Miljöer, med sina secrets, variabler, branch-regler och granskare, hanteras i organisationens administration på frem.sh/<org>/_admin/environments. fremforge ger ett jobb miljöns secrets när jobbet lämnas till en runner och tillämpar där företrädesordningen (miljö, sedan repo, sedan organisation).

Nivåer

NivåVar den ställs inTillgänglig för
OrganisationssecretOrganisationens administration → SecretsAlla repon i organisationen
Repo-secretRepots Inställningar → HemligheterBara det repot
Avgränsad CI-secretAPI:t /orgs/<org>/ci-secrets (sida i organisationens administration: kommer)Jobb vars arbetsflöde, jobb, branch eller tagg, händelse och miljö secretens avgränsning tillåter, och bara när jobbet hänvisar till den (nedan)
MiljösecretOrganisationens administration → Miljöer → <miljö>Jobb som deklarerar environment: <env>, på en branch eller tagg som miljön tillåter, och bara de secrets som jobbet hänvisar till (nedan)

Företrädesordning: en miljösecret går före en avgränsad secret knuten till ett repo, som går före en avgränsad secret för hela organisationen, som går före en repo-secret, som går före en organisationssecret. När samma namn finns på flera nivåer vinner den mest specifika nivån.

Skapa secrets

Via gränssnittet: gå till rätt nivå, scrolla till Lägg till eller uppdatera en secret, ange namn (enligt konventionen UPPER_SNAKE_CASE) och värde och klicka på Spara secret.

Via API:t:

# Org secret
curl -X PUT \
  -H "Authorization: Bearer <PAT>" \
  -H "Content-Type: application/json" \
  -d '{"name":"MY_SECRET","data":"the-value"}' \
  https://frem.sh/_app/api/v1/orgs/<org>/actions/secrets/MY_SECRET

# Repo secret
curl -X PUT \
  -H "Authorization: Bearer <PAT>" \
  -H "Content-Type: application/json" \
  -d '{"name":"MY_SECRET","data":"the-value"}' \
  https://frem.sh/api/v1/repos/<org>/<repo>/actions/secrets/MY_SECRET

Secrets går bara att skriva efter att de har skapats. Du kan inte läsa tillbaka värdet för en secret via API:t eller gränssnittet. Du kan bara skriva över den eller ta bort den.

Använda secrets i arbetsflöden

Hänvisa till secrets med ${{ secrets.NAME }}. Secrets är tillgängliga som miljövariabler.

env:
  DATABASE_URL: ${{ secrets.DATABASE_URL }}

steps:
  - name: Deploy
    env:
      API_KEY: ${{ secrets.DEPLOY_API_KEY }}
    run: ./deploy.sh

Secrets maskeras i loggar: all loggutdata som exakt matchar värdet för en secret ersätts med ***. Maskeringen gäller bara exakta träffar; varianter av värdet som är base64-kodade, URL-kodade eller omvandlade på annat sätt maskeras inte automatiskt.

Miljösecrets och driftsättningsgrindar

Jobb som deklarerar environment: får bara secrets som är avgränsade till den miljön (plus repo- och organisationssecrets). Det är avsiktligt: miljösecrets placerar inloggningsuppgifter för produktion bakom miljöns godkännandeflöde.

jobs:
  deploy-prod:
    runs-on: fremforge
    environment: production   # triggers approval gate if reviewers are configured
    steps:
      - name: Deploy
        env:
          DB_URL: ${{ secrets.PROD_DB_URL }}   # environment secret on 'production'
        run: ./deploy.sh

Konfigurera krav på granskare under Organisationens administration → Miljöer → <miljö>. Jobbet pausas för godkännande innan steget körs; secreten skickas inte in förrän jobbet är godkänt och körs.

Miljönamn matchas utan hänsyn till skiftläge, som i Forgejo och GitHub: environment: Production är miljön production, med dess branch-regel, granskare och secrets. Om två miljöer bara skiljer sig åt i skiftläge används den som stavas exakt som jobbet deklarerar; om ingen av dem gör det får jobbet ingen miljö, och dess driftsättningsgrind nekar det (environment_case_ambiguous). Byt namn på en av dem.

En pull_request_target-körning från en fork får ingen miljö, inga av dess secrets och inget OIDC-claim, oavsett vad jobbet deklarerar. Det är striktare än GitHub. Se Secrets räckvidd för PR från forkar.

Miljösecrets når bara de jobb som hänvisar till dem

Sedan 2026-10-26 får ett jobb en miljösecret bara när jobbet hänvisar till den: i sina egna steg, env:, with: eller if:, eller i arbetsflödets env: på toppnivå, som ${{ secrets.NAME }} eller ${{ secrets['NAME'] }}. En secret som jobbet inte hänvisar till skickas inte alls till dess runner och finns alltså inte på maskinen där jobbet körs.

${{ toJSON(secrets) }}, ett beräknat namn som ${{ secrets[format('{0}_KEY', 'DEPLOY')] }} och secrets: inherit i ett anrop av ett återanvändbart arbetsflöde hänvisar till alla miljöns secrets, som på GitHub.

Ett steg kan bara läsa en secret genom ett sådant uttryck, så ett arbetsflöde som fungerar i dag fortsätter att fungera: ändringen tar bort secrets som inget steg kunde läsa.

Om fremforge inte kan läsa jobbets arbetsflödesfil vid jobbets commit, eller inte hittar jobbet i den, får jobbet inga av miljöns secrets. Jobbet körs ändå, med sin OIDC-token och sina variabler.

Vem fick vilken secret: läsloggen

Varje CI-jobb som får en miljösecret eller avgränsad secret, eller som hänvisar till en som det nekas, skriver en post i organisationens granskningslogg, med åtgärden ci.secret.read:

FältVärde
actorden som startade körningen (organisationen, för en schemalagd körning)
repository, repository_id, workflow, jobvar det kördes
run_id, run_number, run_attempt, ref, eventvilken körning
environmentmiljön som jobbet deklarerade
secretsNAMNEN på de secrets som jobbet fick, var och en med sin nivå (environment, repo eller org)
withheldnamn som jobbet hänvisade till men inte kunde få, var och en med en orsak: workflow-unreadable eller job-not-found, och för en avgränsad secret det fält i avgränsningen som nekade den (scope-workflow, scope-job, scope-ref, scope-event, scope-environment) eller undecryptable

Värdet för en secret sparas aldrig, inte heller en hash av det. Ett jobb som inte hänvisar till någon av miljöns secrets får inga och skriver ingen post.

Posten skrivs innan secrets lämnas till runnern. Om den inte kan sparas får jobbet inga av dem: ingen secret lämnar fremforge utan att registreras. fremforges jour larmas när det händer.

Hämta posterna med API:t:

curl -H "Authorization: Bearer $FREMFORGE_TOKEN" \
  "https://frem.sh/_app/api/v1/orgs/<org>/audit?action=ci.secret.read&since=2026-10-26"

Posterna ingår i granskningsloggens hashkedja, dess lagringstid och dess SIEM-ström, som alla andra poster i granskningsloggen.

Repository- och organisationssecrets som ställs in i Forgejo omfattas inte: Forgejo lämnar fortfarande ut dem till varje jobb i repot, och läsningarna registreras inte. Använd en avgränsad CI-secret i stället och ta bort Forgejo-kopian med samma namn: så länge den finns når den fortfarande de jobb som avgränsningen nekar.

Avgränsade CI-secrets

En avgränsad CI-secret hålls av fremforge, för hela organisationen eller för ett repo, och lämnas till ett jobb bara när alla fält i avgränsningen som du har angett matchar (inom ett fält räcker det att ett av de listade värdena matchar):

FältMatcharExempel
workflowsfilnamnet för arbetsflödetdeploy.yaml, release-*.yml
jobsjobbets id (nyckeln under jobs:)deploy, publish-*
refsbranchen eller taggenrefs/heads/main, refs/tags/v*
eventsarbetsflödets triggerpush, workflow_dispatch, schedule, pull_request, pull_request_target, release
environmentjobbet deklarerar den här miljön, på en branch eller tagg som miljön tillåterproduction

* är det enda jokertecknet. Ett fält som du utelämnar släpper igenom allt, med ett undantag: när inga events är listade får en körning på en pull requests ref (refs/pull/...) aldrig secreten. För att ge kod i en pull request en avgränsad secret listar du pull_request (eller pull_request_target) uttryckligen.

Jobbet måste också hänvisa till secreten (se ovan). Varje leverans, och varje nekad secret som jobbet hänvisade till, registreras i jobbets post ci.secret.read. En pull request från en fork får aldrig någon.

Vilka fält som är en säkerhetsgräns. Den som kan pusha till repot kan skapa en branch vars arbetsflöde har ett jobb med namnet deploy i en fil med namnet deploy.yaml, och starta det. Så workflows och jobs begränsar vilka kodvägar som normalt får secreten, men de skyddar den inte mot personer med skrivåtkomst. Det gör refs (peka på skyddade branches eller taggar) och environment (med en branch-regel och krav på granskare). Det är samma sak som på GitHub.

En körning i merge-kön (refs/heads/fremforge-queue/...) är ett bygge i samma repo som en maintainer har köat, och en tom refs-avgränsning släpper igenom den, som vilken branch som helst. Begränsa refs om en secret inte får nå körningar i merge-kön.

Jobb i ett återanvändbart arbetsflöde, och, på en Forgejo-version som ännu inte skickar jobbets id, jobb med ett eget name: eller en matris, får ännu inga avgränsade secrets.

Skapa eller ersätt en (värdet går bara att skriva; varje ändring granskas, tillsammans med avgränsningen den ersatte):

curl -X PUT -H "Authorization: Bearer $FREMFORGE_TOKEN" -H 'Content-Type: application/json' \
  -d '{"value":"...","workflows":["deploy.yaml"],"jobs":["deploy"],"refs":["refs/heads/main"],"events":["push","workflow_dispatch"]}' \
  "https://frem.sh/_app/api/v1/orgs/<org>/ci-secrets/DEPLOY_KEY?repository_id=<forgejo repository id>"

Utelämna repository_id för en secret som gäller hela organisationen. Ett okänt fält, en environment som inte är ett namn och en tom post i en lista nekas (400) i stället för att ignoreras, så att ett skrivfel aldrig kan vidga en secret till alla jobb. GET /orgs/<org>/ci-secrets listar namn, avgränsningar och när var och en senast lästes; DELETE .../ci-secrets/<NAME>[?repository_id=] tar bort en. Scopes: ci-secrets:read, ci-secrets:write. Gränser: 500 per organisation, 100 per repo, 20 mönster per fält, 64 KB per värde.

Vill du hantera scoped CI-secrets som kod, använd fremforge_ci_secret i fremforge-providern (från 0.9.0). Värdet är ett write-only-argument och når aldrig Terraform-state.

Rotation av secrets

  1. Skapa först de nya inloggningsuppgifterna i det externa systemet.
  2. Skriv över secreten i fremforge med det nya värdet. Ta inte bort den och skapa den på nytt.
  3. Starta en ny körning av arbetsflödet för att kontrollera att de nya inloggningsuppgifterna fungerar hela vägen.
  4. Återkalla de gamla inloggningsuppgifterna i det externa systemet.

Att skriva över bevarar verifieringskedjan och undviker ett fönster där secreten saknas för jobb som körs mellan borttagning och nyskapande.

Gränser

ObjektGräns
Största storlek på ett värde64 KB
Organisationssecrets1 000
Repo-secrets100 per repo
Miljösecrets100 per miljö
Avgränsade CI-secrets500 per organisation, 100 per repo
Mönster för namnBokstäver, siffror och understreck; måste börja med en bokstav; får inte börja med FORGEJO_ eller GITHUB_

OIDC som alternativ till secrets

För driftsättning till molnleverantörer (T Cloud Public, AWS, Azure, GCP) bör du överväga OIDC-tokenfederation i stället för långlivade inloggningsuppgifter lagrade som secrets. OIDC utfärdar kortlivade tokens per jobb, avgränsade till den specifika körningen av arbetsflödet. Inget att rotera, inget som kan läcka.

OIDC är det rekommenderade mönstret för alla jobb som driftsätter till molninfrastruktur.

Korsreferenser