Secrets og miljøvariabler
Secrets er krypterede værdier, der sendes ind i workflow-jobs som miljøvariabler. De kan kun skrives, når de først er oprettet: værdien kan aldrig læses tilbage via brugerfladen eller API’et. Denne side dækker scopes, oprettelse, brug i workflows, rotation og grænser.
Secrets krypteres i hvile med T Cloud Public DEW KMS og dekrypteres først, når jobbet kører på runneren.
Secrets på organisationsniveau administreres i organisationens administration på frem.sh/<org>/_admin/secrets. Secrets på repo-niveau ligger under hvert repositorys Indstillinger → Handlinger → Hemmeligheder i Forgejo. Miljøer administreres med deres secrets, variabler, branch-regler og godkendere i organisationens administration på frem.sh/<org>/_admin/environments. fremforge giver et job dets miljøs secrets, når jobbet tildeles en runner, og anvender rækkefølgen (miljø, derefter repo, derefter organisation) dér.
Scopes
| Scope | Hvor den sættes | Tilgængelig for |
|---|---|---|
| Organisations-secret | Administration → Secrets | Alle repositorier i organisationen |
| Repo-secret | Repo-indstillinger → Hemmeligheder | Kun det pågældende repo |
| Scoped CI-secret | API’et /orgs/<org>/ci-secrets (side i organisationsadministrationen: på vej) | Jobs, hvis workflow, job, branch eller tag, hændelse og miljø secretens scope tillader, og kun når jobbet refererer til den (nedenfor) |
| Miljø-secret | Administration → Miljøer → <miljø> | Jobs, der erklærer environment: <env>, på en branch eller et tag, som miljøet tillader, og kun de secrets, jobbet refererer til (nedenfor) |
Rækkefølge: en miljø-secret går forud for en scoped secret bundet til et repository, som går forud for en scoped secret for hele organisationen, som går forud for en repo-secret, som går forud for en organisations-secret. Findes det samme navn i flere scopes, vinder det mest specifikke.
Oprettelse af secrets
Via brugerfladen: gå til det relevante scope, rul ned til Tilføj eller opdatér en secret, indtast navn (konventionen er UPPER_SNAKE_CASE) og værdi, og klik på Gem secret.
Via API’et:
# 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_SECRETSecrets kan kun skrives, når de er oprettet. Du kan ikke læse en secrets værdi tilbage via API’et eller brugerfladen; du kan kun overskrive eller slette den.
Brug af secrets i workflows
Henvis til secrets med ${{ secrets.NAME }}. Secrets er tilgængelige som miljøvariabler.
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.DEPLOY_API_KEY }}
run: ./deploy.shSecrets maskeres i logs: al logoutput, der præcist matcher en secrets værdi, erstattes med ***. Maskeringen gælder kun præcise match; base64-kodede, URL-kodede eller på anden måde omformede varianter af værdien maskeres ikke automatisk.
Miljø-secrets og udrulningsgates
Jobs, der erklærer environment:, får kun de secrets, der hører til det miljø (plus repo- og organisations-secrets). Det er tilsigtet: miljø-secrets placerer produktionslegitimationsoplysninger bag miljøets godkendelsesflow.
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.shKonfigurér påkrævede godkendere under Administration → Miljøer → <miljø>. Jobbet venter på godkendelse, før trinnet kører; secreten sendes først ind, når jobbet er godkendt og kører.
Miljønavne matches uden hensyn til store og små bogstaver, som i Forgejo og GitHub: environment: Production er miljøet production med dets branch-regel, godkendere og secrets. Hvis to miljøer kun adskiller sig ved store og små bogstaver, bruges det, der er stavet præcis som i jobbets erklæring; hvis ingen af dem er, får jobbet intet miljø, og dets udrulningsgate afviser det (environment_case_ambiguous). Omdøb et af dem.
En pull_request_target-kørsel fra en fork får intet miljø, ingen af dets secrets og ingen OIDC-claim, uanset hvad jobbet erklærer. Det er strengere end GitHub. Se Fork-PR secret reach.
Miljø-secrets når kun de jobs, der refererer til dem
Siden 2026-10-26 får et job kun en miljø-secret, når jobbet refererer til den: i sine egne trin, env:, with: eller if:, eller i env: på workflow-niveau, som ${{ secrets.NAME }} eller ${{ secrets['NAME'] }}. En secret, jobbet ikke refererer til, sendes slet ikke til dets runner og findes derfor ikke på den maskine, jobbet kører på.
${{ toJSON(secrets) }}, et beregnet navn som ${{ secrets[format('{0}_KEY', 'DEPLOY')] }} og secrets: inherit ved kald af et genbrugeligt workflow refererer til alle miljøets secrets, som på GitHub.
Et trin kan kun læse en secret gennem et sådant udtryk, så et workflow, der virker i dag, bliver ved med at virke: ændringen fjerner kun secrets, som intet trin kunne læse.
Hvis fremforge ikke kan læse jobbets workflowfil i jobbets commit eller ikke kan finde jobbet i den, får jobbet ingen af miljøets secrets. Jobbet kører stadig, med sit OIDC-token og sine variabler.
Hvem fik hvilken secret: læseauditten
Hvert CI-job, der får en miljø-secret eller en scoped secret, eller som refererer til en, det bliver nægtet, skriver én post i organisationens auditlog med handlingen ci.secret.read:
| Felt | Værdi |
|---|---|
| actor | den person, der startede kørslen (organisationen, for en planlagt kørsel) |
repository, repository_id, workflow, job | hvor det kørte |
run_id, run_number, run_attempt, ref, event | hvilken kørsel |
environment | det miljø, jobbet erklærede |
secrets | NAVNENE på de secrets, jobbet fik, hver med sit scope (environment, repo eller org) |
withheld | navne, jobbet refererede til, men ikke kunne få, hver med en årsag: workflow-unreadable eller job-not-found, og for en scoped secret det scope-felt, der afviste den (scope-workflow, scope-job, scope-ref, scope-event, scope-environment), eller undecryptable |
En secrets værdi registreres aldrig, heller ikke som hash. Et job, der ikke refererer til nogen af miljøets secrets, får ingen og skriver ingen post.
Posten skrives, før secrets overdrages til runneren. Kan den ikke gemmes, får jobbet ingen af dem: ingen secret forlader fremforge uden at være registreret. fremforges vagt bliver tilkaldt, når det sker.
Forespørg posterne via API’et:
curl -H "Authorization: Bearer $FREMFORGE_TOKEN" \
"https://frem.sh/_app/api/v1/orgs/<org>/audit?action=ci.secret.read&since=2026-10-26"Posterne indgår i auditloggens hashkæde, dens opbevaring og dens SIEM-strøm, ligesom alle andre auditposter.
Repo- og organisations-secrets, der er sat i Forgejo, er ikke omfattet: Forgejo giver dem stadig til alle repositoriets jobs, og læsningen af dem registreres ikke. Brug i stedet en scoped CI-secret, og slet Forgejo-kopien med samme navn: så længe den findes, når den stadig de jobs, som scopet afviser.
Scoped CI-secrets
En scoped CI-secret opbevares af fremforge, for hele organisationen eller for ét repository, og gives kun til et job, når alle de felter i scopet, du har sat, matcher (inden for et felt er det nok, at én af de angivne værdier matcher):
| Felt | Matcher | Eksempel |
|---|---|---|
workflows | workflowfilens navn | deploy.yaml, release-*.yml |
jobs | job-id’et (nøglen under jobs:) | deploy, publish-* |
refs | branchen eller tagget | refs/heads/main, refs/tags/v* |
events | workflowets trigger | push, workflow_dispatch, schedule, pull_request, pull_request_target, release |
environment | jobbet erklærer dette miljø, på en branch eller et tag, som miljøet tillader | production |
* er det eneste jokertegn. Et felt, du udelader, tillader alt, med én undtagelse: uden angivne events får en kørsel på en pull requests ref (refs/pull/...) aldrig secreten. Vil du give kode i en pull request en scoped secret, skal du eksplicit angive pull_request (eller pull_request_target).
Jobbet skal også referere til secreten (som ovenfor). Hver levering, og hver afvisning af en secret, jobbet refererede til, registreres i jobbets ci.secret.read-post. En pull request fra en fork får aldrig en.
Hvilke felter er en sikkerhedsgrænse. Alle, der kan pushe til repositoriet, kan oprette en branch, hvis workflow har et job ved navn deploy i en fil ved navn deploy.yaml, og starte det. workflows og jobs begrænser altså, hvilke kodestier der normalt får secreten, men de beskytter den ikke mod personer med skriveadgang. Det gør refs (peg den på beskyttede branches eller tags) og environment (med en branch-regel og påkrævede godkendere). Det er det samme som på GitHub.
En kørsel i merge-køen (refs/heads/fremforge-queue/...) er et build i samme repository, som en maintainer har sat i kø, og et tomt refs-scope tillader den ligesom enhver anden branch. Begræns refs, hvis en secret ikke må nå kørsler i merge-køen.
Jobs i et genbrugeligt workflow får endnu ikke scoped secrets, og det samme gælder, på en Forgejo-version der endnu ikke sender job-id’et, jobs med deres eget name: eller en matrix.
Opret eller erstat en (værdien kan kun skrives; hver ændring auditeres sammen med det scope, den erstattede):
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>"Udelad repository_id for en secret for hele organisationen. Et ukendt felt, et environment, der ikke er et navn, og et tomt listeelement afvises (400) i stedet for at blive ignoreret, så en tastefejl aldrig kan udvide en secret til alle jobs. GET /orgs/<org>/ci-secrets viser navne, scopes og hvornår hver blev læst sidst; DELETE .../ci-secrets/<NAME>[?repository_id=] fjerner en. Token-scopes: ci-secrets:read, ci-secrets:write. Grænser: 500 pr. organisation, 100 pr. repository, 20 mønstre pr. felt, 64 KB pr. værdi.
Vil du styre scoped CI-secrets som kode, så brug fremforge_ci_secret i fremforge-provideren (fra 0.9.0). Værdien er et write-only-argument og når aldrig Terraform-state.
Rotation af secrets
- Opret først den nye legitimationsoplysning i det eksterne system.
- Overskriv secreten i fremforge med den nye værdi. Slet og genopret den ikke.
- Start en ny workflow-kørsel for at bekræfte, at den nye legitimationsoplysning virker hele vejen igennem.
- Tilbagekald den gamle legitimationsoplysning i det eksterne system.
Overskrivning bevarer audit-sporet og undgår et vindue, hvor secreten mangler for jobs, der kører mellem sletning og genoprettelse.
Grænser
| Element | Grænse |
|---|---|
| Maks. størrelse på en secrets værdi | 64 KB |
| Organisations-secrets | 1.000 |
| Repo-secrets | 100 pr. repo |
| Miljø-secrets | 100 pr. miljø |
| Scoped CI-secrets | 500 pr. organisation, 100 pr. repository |
| Mønster for secret-navne | Bogstaver, tal og understregning; skal starte med et bogstav; må ikke starte med FORGEJO_ eller GITHUB_ |
OIDC som alternativ til secrets
Til udrulning hos cloududbydere (T Cloud Public, AWS, Azure, GCP) bør du overveje OIDC-tokenføderation i stedet for langtidsholdbare legitimationsoplysninger gemt som secrets. OIDC udsteder kortlivede tokens pr. job, afgrænset til den konkrete workflow-kørsel. Intet at rotere, intet at lække.
OIDC er det anbefalede mønster for alle jobs, der udruller til cloudinfrastruktur.
Krydshenvisninger
- Actions og CI/CD, workflow-syntaks og
permissions-blokken - OIDC-tokenføderation, nøglefri cloud-legitimationsoplysninger
- Organisationsadministration, administration af secrets på organisationsniveau