ЁЯдЦ рдзрдбрд╛ 06 тАФ Machine identities: secrets рд╢рд┐рд╡рд╛рдп рдмрд┐рд▓реНрд▓реЗ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 06 ┬╖ рдорд╛рдЧреЗ: lesson-05-roles-sts ┬╖ рдкреБрдвреЗ: lesson-07-conditions-abac
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ05, рдЖрдгрд┐ рддреНрдпрд╛рд╕реЛрдмрдд software рд▓рд╛ рд╕рд╛рдард╡рд▓реЗрд▓реНрдпрд╛ key рд╢рд┐рд╡рд╛рдп AWS access рдХрд╕рд╛ рдорд┐рд│рддреЛ: GitHub Actions рд▓рд╛ OIDC federation рдордзреВрди (trust-github-oidc.json), рдЖрдгрд┐ рд╣реАрдЪ рдХрд▓реНрдкрдирд╛ AWS compute рд╡рд░ тАФ EC2 instance profiles, Lambda execution roles, EKS IRSA рдЖрдгрд┐ Pod Identity.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╢рд╛рд│реЗрдЪрд╛ delivery robot ЁЯдЦ рдЧрд╛рд╡рд╛рдЪреНрдпрд╛ рдкрд▓реАрдХрдбрдЪреНрдпрд╛ рдПрдХрд╛ company рдХрдбреВрди рдпреЗрддреЛ. рддреНрдпрд╛рд▓рд╛ рдорд╛рд╕реНрдЯрд░ рдЪрд╛рд╡реАрдЪреА рдкреНрд░рдд рджреЗрдгреЗ рд╣реА рд╡рд╛рдИрдЯ рдХрд▓реНрдкрдирд╛ рдЖрд╣реЗ тАФ robots рд╣рд░рд╡рддрд╛рдд, рдЪрд╛рд╡реНрдпрд╛рдВрдЪреНрдпрд╛ рдкреНрд░рддреА рдмрдирддрд╛рдд.
рддреНрдпрд╛рдРрд╡рдЬреА robot рдЪреА company рддреНрдпрд╛рд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ рдлреЗрд░реАрд╕рд╛рдареА рдПрдХ рд╕рд╣реА рдХреЗрд▓реЗрд▓реЗ рдкрддреНрд░ рджреЗрддреЗ: "рд╣рд╛ robot 7 рдЖрд╣реЗ, рдЖрдЬ main delivery рдорд╛рд░реНрдЧрд╛рд╡рд░ рдХрд╛рдо рдХрд░рддреЛ рдЖрд╣реЗ". рдУрд│рдЦрдкрддреНрд░ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рд▓рд╛ рддреНрдпрд╛ company рдЪреА рд╕рд╣реА рдорд╛рд╣реАрдд рдЕрд╕рддреЗ, рддреЗ рдкрддреНрд░ рд╡рд╛рдЪрддреЗ, рддреНрдпрд╛рд╡рд░ рд▓рд┐рд╣рд┐рд▓реЗрд▓рд╛ рдорд╛рд░реНрдЧ рддрдкрд╛рд╕рддреЗ, рдЖрдгрд┐ robot рд▓рд╛ рдПрдХрд╛ рддрд╛рд╕рд╛рдЪреА рдЯреЛрдкреА рджреЗрддреЗ. рд╡реЗрдЧрд│реНрдпрд╛ рдорд╛рд░реНрдЧрд╛рд╕рд╛рдареАрдЪреЗ рдкрддреНрд░, рдХрд┐рдВрд╡рд╛ рд╡реЗрдЧрд│реНрдпрд╛ company рдХрдбреВрди рдЖрд▓реЗрд▓реЗ рдкрддреНрд░, рдпрд╛рдВрдирд╛ рдХрд╛рд╣реАрдЪ рдорд┐рд│рдд рдирд╛рд╣реА.
рддреЗ рд╕рд╣реА рдХреЗрд▓реЗрд▓реЗ рдкрддреНрд░ рдореНрд╣рдгрдЬреЗ OIDC token. GitHub рдкреНрд░рддреНрдпреЗрдХ workflow run рд╕рд╛рдареА рдПрдХ token рд╕рд╣реА рдХрд░реВрди рджреЗрддреЛ; AWS рддреЛ role рдЪреНрдпрд╛ trust policy рд╢реА рддрдкрд╛рд╕рддреЛ рдЖрдгрд┐ рддрд╛рддреНрдкреБрд░рддреА credentials рджреЗрддреЛ. GitHub рдордзреНрдпреЗ рдХреЛрдгрддреЗрд╣реА secret рдХрдзреАрдЪ рд╕рд╛рдард╡рд▓реЗ рдЬрд╛рдд рдирд╛рд╣реА.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
gh["тЪЩя╕П GitHub Actions run<br/>id-token: write"]
tok["тЬЙя╕П signed OIDC token<br/>aud: sts.amazonaws.com<br/>sub: repo:BaluRaut/school-app:ref:refs/heads/main"]
sts["ЁЯОЯя╕П STS AssumeRoleWithWebIdentity"]
trust["ЁЯП╖я╕П trust policy<br/>Federated: token.actions.githubusercontent.com<br/>checks aud + sub"]
creds["ЁЯОй 1-hour credentials"]
gh -->|"1 asks GitHub"| tok -->|"2 presents"| sts --> trust
trust -->|"3 claims match"| creds
trust -.->|"feature branch, fork"| no["ЁЯЪл refused"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/iam/lesson-diagrams.html#l06
тЭУ рдХрд╛рдп
- OIDC federation тАФ рддреБрдореНрд╣реА IAM рдордзреНрдпреЗ рдПрдХ identity provider рдиреЛрдВрджрд╡рддрд╛
(
token.actions.githubusercontent.com); role рдЪреА trust policy рддреНрдпрд╛рдЪреЗ рдирд╛рд╡"Principal": {"Federated": "arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com"}рдЕрд╕реЗsts:AssumeRoleWithWebIdentityрд╕рд╣ рдШреЗрддреЗ. - Claims рдореНрд╣рдгрдЬреЗрдЪ conditions тАФ
тАж:audрд╣реЗsts.amazonaws.comрдЕрд╕рд╛рдпрд▓рд╛рдЪ рд╣рд╡реЗ;тАж:subрд╕рд╛рдВрдЧрддреЗ рдХреЛрдгрддрд╛ repo рдЖрдгрд┐ рдХреЛрдгрддрд╛ ref/environment:repo:OWNER/REPO:ref:refs/heads/main,repo:OWNER/REPO:pull_request,repo:OWNER/REPO:environment:prod.subрдиреЗрд╣рдореА рддреБрдордЪреНрдпрд╛ repo рд▓рд╛ рдмрд╛рдВрдзреВрди рдареЗрд╡рд╛ тАФ рддреНрдпрд╛рд╢рд┐рд╡рд╛рдп рдХреЛрдгрддреАрд╣реА GitHub repository рддреЛ role assume рдХрд░реВ рд╢рдХрддреЗ. - AWS compute рд╡рд░ platform рддреБрдордЪреНрдпрд╛рд╕рд╛рдареА role credentials рдкреЛрд╣реЛрдЪрд╡рддреЛ:
- EC2 тАФ instance profile role рд▓рд╛ рдЧреБрдВрдбрд╛рд│реВрди рдареЗрд╡рддреЛ; SDK credentials instance metadata service рдордзреВрди рд╡рд╛рдЪрддреЛ (IMDSv2 рдмрдВрдзрдирдХрд╛рд░рдХ рдХрд░рд╛).
- Lambda / ECS tasks тАФ execution role / task role.
- EKS тАФ IRSA (cluster рдЪреНрдпрд╛ OIDC provider рдордзреВрди, role рдЪреЗ annotation рдЕрд╕рд▓реЗрд▓реЗ service account) рдХрд┐рдВрд╡рд╛ EKS Pod Identity (service account рдЖрдгрд┐ role рдпрд╛рдВрдЪреНрдпрд╛рддреАрд▓ association).
- SDKs рдЪреА default credential chain рд╣реЗ рд╕рдЧрд│реЗ рдЖрдкреЛрдЖрдк рд╢реЛрдзрддреЗ тАФ code рдордзреНрдпреЗ рдХрдзреАрдЪ keys рдирд╕рддрд╛рдд.
ЁЯдФ рдХрд╛
Secret рдореНрд╣рдгреВрди рд╕рд╛рдард╡рд▓реЗрд▓реА CI access key рдореНрд╣рдгрдЬреЗ рджреАрд░реНрдШрдХрд╛рд│рд╛рдЪреА рдорд╛рд╕реНрдЯрд░ рдЪрд╛рд╡реА, рдЬреА рдкреНрд░рддреНрдпреЗрдХ workflow рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ maintainer рд▓рд╛ рдорд┐рд│реВ рд╢рдХрддреЗ, рдЖрдгрд┐ рддреА рд╣рд╛рддрд╛рдиреЗ rotate рдХрд░рд╛рд╡реА рд▓рд╛рдЧрддреЗ. Federation рддрд┐рдЪреНрдпрд╛ рдЬрд╛рдЧреА рдкреНрд░рддреНрдпреЗрдХ run рд╕рд╛рдареАрдЪреЗ credential рдЖрдгрддреЗ, рдЬреЗ рдПрдХрд╛ рддрд╛рд╕рд╛рдд рд╕рдВрдкрддреЗ рдЖрдгрд┐ рддреБрдореНрд╣реА рдирд╛рд╡ рджрд┐рд▓реЗрд▓реНрдпрд╛ repo рдЖрдгрд┐ branch рд╕рд╛рдареАрдЪ рдЪрд╛рд▓рддреЗ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
iam/demo.py рдордзрд▓рд╛ machines() token claims рдЪреЗ рддреАрди рд╕рдВрдЪ рдмрдирд╡рддреЛ тАФ
main branch, рдПрдХ feature branch рдЖрдгрд┐ рдПрдХ fork тАФ рдЖрдгрд┐ trust statement рдЪреНрдпрд╛ conditions
matches() рдордзреВрди рдЪрд╛рд▓рд╡рддреЛ. рдлрдХреНрдд main рд▓рд╛ role рдорд┐рд│рддреЛ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 iam/demo.py machines
python3 - <<'EOF'
import json, sys; sys.path.insert(0, "iam"); from evaluate import load, matches
trust = load("trust-github-oidc")["Statement"][0]
def token(sub, aud="sts.amazonaws.com"):
return {"token.actions.githubusercontent.com:aud": aud, "token.actions.githubusercontent.com:sub": sub}
A = "sts:AssumeRoleWithWebIdentity"
print("main, right audience :", matches(trust, A, "*", token("repo:BaluRaut/school-app:ref:refs/heads/main")))
print("main, wrong audience :", matches(trust, A, "*", token("repo:BaluRaut/school-app:ref:refs/heads/main", aud="my-app")))
print("pull request :", matches(trust, A, "*", token("repo:BaluRaut/school-app:pull_request")))
loose = json.loads(json.dumps(trust).replace("ref:refs/heads/main", "*"))
print("pull request, loose :", matches(loose, A, "*", token("repo:BaluRaut/school-app:pull_request")))
EOF
рдЦрд▒реНрдпрд╛ account рд╡рд░ (AWS CLI рдЖрдгрд┐ credentials рд▓рд╛рдЧрддрд╛рдд) тАФ GitHub рдЪреА рдПрдХрджрд╛ рдиреЛрдВрджрдгреА рдХрд░рд╛, рдЖрдгрд┐ рдпрд╛ trust policy рд╕рд╣ role рдмрдирд╡рд╛:
aws iam create-open-id-connect-provider --url https://token.actions.githubusercontent.com --client-id-list sts.amazonaws.com
aws iam create-role --role-name github-deployer --assume-role-policy-document file://iam/policies/trust-github-oidc.json
рдЖрдгрд┐ workflow рдордзреНрдпреЗ (GitHub рдЪреА рдмрд╛рдЬреВ):
permissions:
id-token: write # lets the job ask GitHub for an OIDC token
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::111122223333:role/github-deployer
aws-region: ap-south-1
- run: aws sts get-caller-identity
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
machines рд╣реЗ print рдХрд░рддреЛ: тЬЕ тАж refs/heads/main тЖТ role assumed, 1-hour credentials рдЖрдгрд┐
feature-x рд╕рд╛рдареА рд╡ repo:someone/fork рд╕рд╛рдареА ЁЯЪл тАж refused. рддреБрдордЪрд╛ snippet True,
False (рдЪреБрдХреАрдЪрд╛ audience), False (pull request рдореНрд╣рдгрдЬреЗ main рдирд╛рд╣реА) рдЖрдгрд┐ рд╕реИрд▓ рдХреЗрд▓реЗрд▓реНрдпрд╛
repo:BaluRaut/school-app:* рд╕рд╛рдареА True print рдХрд░рддреЛ тАФ wildcard рдЕрд╕рд▓реЗрд▓рд╛ sub рдХреЛрдгрддреНрдпрд╛рд╣реА branch рд▓рд╛ рдХрд┐рдВрд╡рд╛ pull
request рд▓рд╛ deploy рдХрд░реВ рджреЗрддреЛ. рдЦрд▒реНрдпрд╛ workflow рдордзреНрдпреЗ get-caller-identity
assumed-role/github-deployer/тАж рджрд╛рдЦрд╡рддреЛ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
Machine рд╕рд╛рдард╡рд▓реЗрд▓реНрдпрд╛ secret рдРрд╡рдЬреА рд╕рд╣реА рдХреЗрд▓реЗрд▓реНрдпрд╛, рдЕрд▓реНрдкрдХрд╛рд│рд╛рдЪреНрдпрд╛ token рдиреЗ рдЖрдкрдг рдХреЛрдг рдЖрд╣реЛрдд рд╣реЗ рд╕рд┐рджреНрдз рдХрд░реВ рд╢рдХрддреЗ
тАФ рдЖрдгрд┐ рдХреЛрдгрддреЗ runs рдкрд╛рддреНрд░ рдард░рддрд╛рдд рд╣реЗ trust policy рдЪреА sub condition рдиреЗрдордХреЗ рдард░рд╡рддреЗ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
subcondition рдирд╕рдгреЗ, рдХрд┐рдВрд╡рд╛repo:OWNER/*тАФ рддреНрдпрд╛ owner рдЪрд╛ рдХреЛрдгрддрд╛рд╣реА repo (рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рд╣реВрди рд╡рд╛рдИрдЯ) deploy рдХрд░реВ рд╢рдХрддреЛ- "PRs рдЪрд╛рд▓рд╛рд╡реЗрдд рдореНрд╣рдгреВрди" рд░реБрдВрдж
*рд╕рд╣StringLikeтАФ рддреНрдпрд╛рдРрд╡рдЬреА environment рд╡рд╛рдкрд░рд╛ - workflow рдордзреНрдпреЗ
permissions: id-token: writeрд╡рд┐рд╕рд░рдгреЗ - EC2 рд╡рд░ IMDSv1 рдЪрд╛рд▓реВ рдареЗрд╡рдгреЗ, рдХрд┐рдВрд╡рд╛ AMIs рдЖрдгрд┐ container images рдордзреНрдпреЗ keys рднрд░реВрди рдареЗрд╡рдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: "CI рдордзреНрдпреЗ рджреАрд░реНрдШрдХрд╛рд│рд╛рдЪреНрдпрд╛ keys рдирд╛рд╣реАрдд" рд╣рд╛ рдЖрддрд╛ audit рдЪрд╛ рдиреЗрд╣рдореАрдЪрд╛ рдореБрджреНрджрд╛ рдЖрд╣реЗ. CI рд╕рд╛рдареА OIDC, AWS compute рд╕рд╛рдареА instance/task/execution roles, Kubernetes рд╕рд╛рдареА IRSA рдХрд┐рдВрд╡рд╛ Pod Identity тАФ рдЖрдгрд┐ credential report рдордзрд▓реА keys рдЪреА рд╕рдВрдЦреНрдпрд╛ рд╢реВрдиреНрдпрд╛рд╡рд░ рдпреЗрддреЗ.
тПня╕П рдкреБрдвреЗ
рддреНрдпрд╛ рдХреНрд╖рдгрд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рдгрд╛рд░реЗ рдирд┐рдпрдо тАФ MFA, network, рдПрдЦрд╛рджрд╛ tag. Conditions рдЖрдгрд┐ ABAC.
git checkout lesson-07-conditions-abac