Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 205 additions & 0 deletions deploy/eks-ci/eks-ci-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# The AWS-side identity the ksail "System Test - EKS" workflow assumes via
# GitHub Actions OIDC (step 2 of the rollout documented in kustomization.yaml;
# platform#2326 child 2). Trust is scoped to exactly one GitHub environment —
# repo:devantler-tech/ksail:environment:ci — through the account's GitHub OIDC
# provider (github-oidc-provider.yaml), so no long-lived key exists anywhere.
# maxSessionDuration is 7200s because the smoke job may run up to 120 min
# including cluster cleanup.
#
# Permissions are an INLINE policy (platform#2564: Policy/RolePolicyAttachment
# MRDs are deliberately not activated) modeled on eksctl's documented minimum
# policies, name-scoped to the workflow's st-eks-*/eksctl-st-eks-* naming
# wherever IAM supports resource-level scoping (CloudFormation stacks, IAM
# roles/instance profiles, EKS clusters). EC2/autoscaling/SSM-AMI actions are
# account-wide because eksctl drives them through CloudFormation with the
# caller's credentials and their create-time actions do not support name
# scoping; the blast radius remains bounded by the single-environment trust.
# iam:CreateRole is conditioned on the eks-ci-smoke-boundary permissions
# boundary (eks-ci-smoke-boundary.yaml) and no *PermissionsBoundary action is
# granted, so roles this principal creates (and can pass to EC2) are capped at
# the smoke-test compute plane even if an arbitrary policy is written to them.
apiVersion: iam.aws.m.upbound.io/v1beta1
kind: Role
metadata:
name: eks-ci
spec:
forProvider:
description: >-
GitHub OIDC role for the ksail System Test - EKS smoke workflow
(repo:devantler-tech/ksail:environment:ci). Creates and deletes
throwaway st-eks-* EKS clusters via eksctl.
maxSessionDuration: 7200
assumeRolePolicy: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::939001610192: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:devantler-tech/ksail:environment:ci"
}
}
}
]
}
inlinePolicy:
- name: eks-ci-smoke
policy: |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CloudFormationScoped",
"Effect": "Allow",
"Action": "cloudformation:*",
"Resource": "arn:aws:cloudformation:*:939001610192:stack/eksctl-st-eks-*/*"
},
{
"Sid": "CloudFormationRead",
"Effect": "Allow",
"Action": [
"cloudformation:ListStacks",
"cloudformation:GetTemplateSummary"
],
"Resource": "*"
},
{
"Sid": "EksScoped",
"Effect": "Allow",
"Action": "eks:*",
"Resource": [
"arn:aws:eks:*:939001610192:cluster/st-eks-*",
"arn:aws:eks:*:939001610192:nodegroup/st-eks-*/*/*",
"arn:aws:eks:*:939001610192:addon/st-eks-*/*/*",
"arn:aws:eks:*:939001610192:access-entry/st-eks-*/*/*/*/*",
"arn:aws:eks:*:939001610192:accessEntry/st-eks-*/*/*/*/*"
]
},
{
"Sid": "EksRead",
"Effect": "Allow",
"Action": [
"eks:DescribeAddonVersions",
"eks:DescribeAddonConfiguration",
"eks:ListClusters"
],
"Resource": "*"
},
{
"Sid": "Ec2AndAutoscaling",
"Effect": "Allow",
"Action": [
"ec2:*",
"autoscaling:*",
"elasticloadbalancing:*"
],
"Resource": "*"
},
{
"Sid": "SsmAmiLookup",
"Effect": "Allow",
"Action": "ssm:GetParameter",
"Resource": [
"arn:aws:ssm:*::parameter/aws/service/eks/optimized-ami/*",
"arn:aws:ssm:*::parameter/aws/service/bottlerocket/*"
]
},
{
"Sid": "IamCreateRoleBounded",
"Effect": "Allow",
"Action": "iam:CreateRole",
"Resource": "arn:aws:iam::939001610192:role/eksctl-st-eks-*",
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::939001610192:policy/eks-ci-smoke-boundary"
}
}
},
{
"Sid": "IamScopedRoleLifecycle",
"Effect": "Allow",
"Action": [
"iam:DeleteRole",
"iam:GetRole",
"iam:TagRole",
"iam:UntagRole",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:PutRolePolicy",
Comment thread
devantler marked this conversation as resolved.
"iam:GetRolePolicy",
"iam:DeleteRolePolicy",
"iam:ListRolePolicies",
"iam:ListAttachedRolePolicies",
"iam:ListInstanceProfilesForRole",
"iam:PassRole"
],
"Resource": "arn:aws:iam::939001610192:role/eksctl-st-eks-*"
},
{
"Sid": "IamScopedInstanceProfiles",
"Effect": "Allow",
"Action": [
"iam:CreateInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:GetInstanceProfile",
"iam:TagInstanceProfile",
"iam:AddRoleToInstanceProfile",
"iam:RemoveRoleFromInstanceProfile"
],
"Resource": "arn:aws:iam::939001610192:instance-profile/eksctl-st-eks-*"
},
{
"Sid": "IamServiceLinkedRoles",
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": [
"eks.amazonaws.com",
"eks-nodegroup.amazonaws.com",
"autoscaling.amazonaws.com",
"elasticloadbalancing.amazonaws.com"
]
}
}
},
{
"Sid": "IamOidcProviderLifecycle",
"Effect": "Allow",
"Action": [
"iam:CreateOpenIDConnectProvider",
"iam:DeleteOpenIDConnectProvider",
"iam:TagOpenIDConnectProvider",
"iam:UntagOpenIDConnectProvider"
],
"Resource": "arn:aws:iam::939001610192:oidc-provider/oidc.eks.*"
},
{
"Sid": "IamReadForEksctl",
"Effect": "Allow",
"Action": [
"iam:GetOpenIDConnectProvider",
Comment thread
devantler marked this conversation as resolved.
"iam:ListPolicies",
"iam:GetPolicy",
"iam:GetPolicyVersion"
],
"Resource": "*"
},
{
"Sid": "StsIdentity",
"Effect": "Allow",
"Action": "sts:GetCallerIdentity",
"Resource": "*"
}
]
}
providerConfigRef:
kind: ProviderConfig
name: default
60 changes: 60 additions & 0 deletions deploy/eks-ci/eks-ci-smoke-boundary.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Permissions boundary for every IAM role the eks-ci principal creates
# (eksctl-st-eks-* cluster/nodegroup/IRSA roles). eks-ci-role.yaml conditions
# iam:CreateRole on this boundary (iam:PermissionsBoundary), and the principal
# holds no iam:*PermissionsBoundary or role-update actions, so a workflow that
# assumes eks-ci cannot mint a role more privileged than this cap and pass it
# to EC2 to escape the smoke-test scope. The allowlist is the union of what
# eksctl-created cluster/node/IRSA roles exercise in the smoke path (EKS
# control plane, node compute/networking, ECR pulls, CNI, logs/metrics, SSM
# agent channels); deliberately NO iam:* or sts:AssumeRole* — a bounded role
# stays inside the compute plane even if an arbitrary inline policy is put on
# it. If a future smoke needs an action outside the cap, the failure names it
# and this file is the tuning point.
#
# Requires the policies.iam.aws.m.upbound.io MRD activated platform-side (the
# aws ManagedResourceActivationPolicy); merge that platform change first or
# this manifest sits Pending without error.
apiVersion: iam.aws.m.upbound.io/v1beta1
kind: Policy
metadata:
name: eks-ci-smoke-boundary
spec:
forProvider:
description: >-
Permissions boundary capping IAM roles created by the eks-ci GitHub
OIDC role for throwaway st-eks-* smoke clusters.
policy: |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SmokeComputePlaneCap",
"Effect": "Allow",
"Action": [
"autoscaling:*",
"cloudwatch:*",
"ec2:*",
"ec2messages:*",
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:GetAuthorizationToken",
"ecr:GetDownloadUrlForLayer",
"eks:*",
"eks-auth:AssumeRoleForPodIdentity",
"elasticloadbalancing:*",
"kms:CreateGrant",
"kms:DescribeKey",
"logs:*",
"ssm:GetParameter",
"ssm:GetParameters",
"ssmmessages:*",
"sts:GetCallerIdentity",
"sts:TagSession"
],
"Resource": "*"
}
]
}
providerConfigRef:
kind: ProviderConfig
name: default
21 changes: 11 additions & 10 deletions deploy/eks-ci/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@
# Two-step rollout (the role's trust policy must name the provider's EXACT
# ARN, which embeds the AWS account id — only observable after step 1
# reconciles; principal ARNs cannot be wildcarded):
# 1. (this slice) The GitHub OIDC identity provider. Reconciling it proves
# the OpenBao bootstrap credential end-to-end and surfaces the account id
# in status.atProvider.arn.
# 2. (follow-up) The `Role`: trust scoped to
# 1. (done) The GitHub OIDC identity provider. Reconciled on prod
# (Synced=True/Ready=True) after platform#2598 unblocked provider egress;
# its status.atProvider.arn is the Federated principal the role trusts.
# 2. (this slice) The `Role` (eks-ci-role.yaml): trust scoped to
# repo:devantler-tech/ksail:environment:ci, maxSessionDuration 7200 (the
# smoke job may run 120 min incl. cleanup), least-privilege permissions
# as an INLINE policy (per platform#2564: Policy/RolePolicyAttachment
# MRDs are deliberately NOT activated), scoped to the workflow's
# st-eks-*/eksctl-st-eks-* naming. Its ARN then goes to the ksail `ci`
# environment as AWS_OIDC_ROLE_ARN (child 3, the workflow's clean-skip
# gate).
# as an INLINE policy (platform#2564; the one Policy MR here is the
# permissions boundary capping roles eksctl creates), scoped to the workflow's
# st-eks-*/eksctl-st-eks-* naming. Once it reconciles, its ARN goes to
# the ksail `ci` environment as AWS_OIDC_ROLE_ARN (child 3, the
# workflow's clean-skip gate).
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github-oidc-provider.yaml

- eks-ci-smoke-boundary.yaml
- eks-ci-role.yaml