GitHub Actions без ключоў AWS: адна ўмова не пусціць чужы рэпазіторый

|Аўтар: Рэдакцыя QUASA|5 хв чытання| 1
GitHub Actions без ключоў AWS: адна ўмова не пусціць чужы рэпазіторый

Каб GitHub Actions атрымліваў часовы доступ да AWS без пастаянных ключоў у GitHub Secrets, стварыце OIDC-правайдара ў IAM, ролю з праверкамі aud і sub і дазвольце workflow запытваць токен. Дакументацыя дзеяння AWS паказвае, як яно абменьвае токен GitHub на часовыя ўліковыя даныя ролі.

Для гэтай ролі вырашальная ўмова — дакладнае супадзенне sub з дазволеным рэпазіторыем і галінай. aud правярае, што токен прызначаны AWS STS, але не адрознівае ваш рэпазіторый ад чужога. Ніжэй — мінімальная канфігурацыя для запуску з галіны main і спосаб праверыць, што іншы запуск не атрымае ролю.

Стварыце правайдара і ролю ў IAM

У патрэбным акаўнце AWS адкрыйце IAM → Identity providers → Add provider і выберыце OpenID Connect. Увядзіце https://token.actions.githubusercontent.com як Provider URL і sts.amazonaws.com як Audience. Калі правайдар з такім URL ужо ёсць у акаўнце, выкарыстоўвайце яго: IAM патрабуе, каб правайдар і роля, якая яму давярае, належалі аднаму акаўнту.

Пасля гэтага стварыце IAM-ролю для Web identity і выберыце правайдара GitHub. Калі кансоль прапануе палі для арганізацыі, рэпазіторыя і галіны, запоўніце ўсе патрэбныя значэнні: пакінутае пустым поле рэпазіторыя або галіны можа ператварыцца ў маску. Перад выкарыстаннем ролі адкрыйце яе trust policy і звярце поўны радок sub, асабліва калі GitHub выкарыстоўвае фармат з нязменнымі ID.

Trust policy адказвае за тое, хто можа прыняць ролю; permissions policy — за тое, што прынятая роля можа зрабіць у AWS. Для праверкі ідэнтычнасці дастаткова выкліку AWS STS. Дазволы на S3, разгортванне ці іншыя дзеянні прызначайце ролі паводле рэальнай задачы workflow, а не для самога абмену OIDC-токена.

Абмяжуйце trust policy дакладным sub

Інструкцыя AWS для роляў OIDC патрабуе ўмову token.actions.githubusercontent.com:sub пры стварэнні або змене ролі, якая давярае GitHub: пустое значэнне і значэнне, складзенае толькі з масак, IAM адхіляе. Аднак умова з назвай арганізацыі і маскай замест рэпазіторыя ўсё яшчэ прапускае запускі іншых рэпазіторыяў гэтай арганізацыі. Для доступу толькі з main выкарыстоўвайце StringEquals з поўным значэннем sub.

Гэта ўмоўны прыклад для раней створанага рэпазіторыя example-org/example-repo. Замяніце нумар акаўнта і ўвесь радок sub на свае значэнні; паказаны фармат не падыдзе рэпазіторыю, токен якога змяшчае нязменныя ID.

{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":"arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"},"Action":"sts:AssumeRoleWithWebIdentity","Condition":{"StringEquals":{"token.actions.githubusercontent.com:aud":"sts.amazonaws.com","token.actions.githubusercontent.com:sub":"repo:example-org/example-repo:ref:refs/heads/main"}}}]}

У гэтым прыкладзе запуск з test-oidc мае іншае заканчэнне sub, а запуск з чужога рэпазіторыя — іншую частку перад ref. Ні той, ні другі токен не адпавядае StringEquals, таму гэты дазвольны statement не дае прыняць ролю. Каб абмежаванне сапраўды дзейнічала, праверце ўсю trust policy: дадатковы дазвольны statement з шырэйшай умовай можа адкрыць іншы шлях да той жа ролі.

Маска repo:example-org/example-repo:* вырашае іншую задачу: яна дапускае не толькі main, але і іншыя кантэксты таго самага рэпазіторыя. Умова для aud таксама павінна застацца дакладнай — у гэтай канфігурацыі дзеянне запытвае токен для sts.amazonaws.com. Абедзве праверкі знаходзяцца ў адным statement і павінны выканацца разам.

Звярце фармат sub для галіны або environment

Даведнік GitHub па OIDC тлумачыць, што рэпазіторыі, створаныя пасля 15 ліпеня 2026 года, па змаўчанні ўключаюць у sub нязменныя ID уладальніка і рэпазіторыя. Для ранейшых рэпазіторыяў захоўваецца фармат з назвамі, калі ўладальнік не ўключыў нязменны sub; перайменаванне або перанос рэпазіторыя таксама можа змяніць фармат. Палітыка павінна супадаць з фактычным sub токена, а не толькі з назвай, якую бачна ў GitHub.

Для ўмоўнага рэпазіторыя з нязменнымі ID значэнне можа выглядаць так: repo:example-org@123456/example-repo@456789:ref:refs/heads/main. Гэтыя лічбы — толькі запаўняльнікі. Калі ўзяць ID іншага ўладальніка або рэпазіторыя, нават запуск з main атрымае адмову; пры такой памылцы звярце claims токена, перш чым замяняць дакладнае супадзенне маскай.

Калі job прывязаны да GitHub environment, стандартны sub змяшчае environment:НАЗВА замест ref:refs/heads/main. У trust policy тады патрэбна дакладная назва environment, а дазволеныя галіны і тэгі варта абмежаваць яго правіламі абароны. Інакш запуск з іншай галіны таго ж рэпазіторыя можа атрымаць той самы sub для environment. Пры запуску праз pull request без environment кантэкст sub таксама адрозніваецца ад паказанага прыкладу для push у main.

Дадайце workflow без пастаянных ключоў

Стварыце .github/workflows/aws-oidc.yml. Ніжэй YAML у кампактным flow-сінтаксісе: падзея push запускае яго ў кожнай галіне, каб можна было пабачыць і дазволены, і забаронены вынік. Замяніце ARN ролі і рэгіён; прыклад выкарыстоўвае aws-actions/[email protected].

{'name': 'AWS OIDC check', 'on': ['push'], 'permissions': {'id-token': 'write'}, 'jobs': {'identity': {'runs-on': 'ubuntu-latest', 'steps': [{'uses': 'aws-actions/[email protected]', 'with': {'role-to-assume': 'arn:aws:iam::123456789012:role/github-oidc-check', 'aws-region': 'eu-central-1'}}, {'run': 'aws sts get-caller-identity'}]}}}

Параметр id-token: write дазваляе job запытаць OIDC-токен у GitHub; сам па сабе ён не дае дазволаў на запіс у AWS. Дзеянне перадае токен у AWS STS, спрабуе прыняць пазначаную ролю і толькі пасля паспяховага абмену робіць часовыя ўліковыя даныя даступнымі наступнаму кроку. У гэтым workflow няма AWS_ACCESS_KEY_ID і AWS_SECRET_ACCESS_KEY, а checkout не патрэбны: каманда толькі высвятляе ідэнтычнасць, пад якой працуе job.

Для рэальнага разгортвання дадайце патрэбныя крокі пасля configure-aws-credentials і адпаведныя дазволы ў permissions policy ролі. Калі workflow будзе выкарыстоўваць actions/checkout, яму асобна спатрэбіцца дазвол contents: read. Не блытайце яго з id-token: write: першы патрэбны для чытання змесціва рэпазіторыя, другі — для атрымання OIDC-токена.

Праверце дазволены і забаронены запускі

Адпраўце змяненне ў main. Пры адпаведным sub крок configure-aws-credentials павінен прыняць ролю, а aws sts get-caller-identity — вярнуць акаўнт і ARN прынятай ролі. Звярце іх з ARN у workflow: паспяховы запуск сам па сабе не паказвае, якую менавіта ролю атрымаў job.

Затым стварыце ад main умоўную галіну test-oidc з тым самым файлам workflow і адпраўце ў яе змяненне. Паколькі policy дазваляе толькі refs/heads/main, крок configure-aws-credentials павінен спыніцца на прыняцці ролі; каманда get-caller-identity пасля яго не выканаецца. Гэта чаканы вынік адмоўнага тэсту, а не вынік запуску, праведзенага рэдакцыяй.

Каб праверыць мяжу рэпазіторыя, запусціце эквівалентны job у іншым рэпазіторыі з тым самым ARN ролі. Яго sub будзе адрознівацца, таму пры паказанай trust policy абмен таксама павінен скончыцца адмовай. Калі забаронены запуск усё ж атрымаў уліковыя даныя, звярце поўную trust policy, фактычны sub і тое, ці не выкарыстаў job іншы спосаб аўтэнтыфікацыі. Пасля абедзвюх адмоў і паспяховага запуску з main можна падключаць патрэбныя дзеянні AWS да гэтай ролі.

Чытайце таксама:

Падзяліцца:

Падпішыцеся на нашу рассылку

Атрымлівайце свежыя навіны пра Web3, ШІ і крыптавалюты проста на пошту.

0