AWSTemplateFormatVersion: "2010-09-09" Description: IAM roles needed to orchestrate the tests in the Github Actions Parameters: Repository: Type: String Description: "Fully qualified repository name, formatted as /" Branches: Type: String Description: "The restrictions on which branches have permission to reach out to the OIDC provider. This is useful for security hardening of your github actions as described in https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions" Regions: Type: CommaDelimitedList Default: "us-east-2,us-west-2,eu-west-1" PrometheusWorkspaceID: Type: String Description: "Prometheus workspace to forward cluster prometheus metrics to" DatabaseName: Type: String Description: "Timestream database to forward test metrics to" TableName: Type: String Description: "Timestream table to forward test metrics to" Resources: GithubOIDCProvider: Type: AWS::IAM::OIDCProvider Properties: Url: https://token.actions.githubusercontent.com ClientIdList: - sts.amazonaws.com # Relevant context for all these thumbprints can be found in the GH issue and blogpost: # https://github.com/aws-actions/configure-aws-credentials/issues/357#issuecomment-1605290219 # https://github.blog/changelog/2023-06-27-github-actions-update-on-oidc-integration-with-aws/ ThumbprintList: - 6938fd4d98bab03faadb97b34396831e3780aea1 - 1c58a3a8518e8759bf075b76b750d4f2df264fcd GithubActionsPolicy: Type: AWS::IAM::ManagedPolicy Properties: ManagedPolicyName: GithubActionsPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - iam:AttachRolePolicy - iam:CreateRole - iam:DeleteRolePolicy - iam:DetachRolePolicy - iam:PutRolePolicy Resource: - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/KarpenterNodeRole-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/eksctl-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/karpenter-irsa-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/prometheus-irsa-*" Condition: ArnEquals: "iam:PermissionsBoundary": !Ref GithubActionsPermissionsBoundary - Effect: Allow Action: iam:DeleteRole Resource: - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/KarpenterNodeRole-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/eksctl-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/karpenter-irsa-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/prometheus-irsa-*" - Effect: Allow Action: - iam:GetRole - iam:GetRolePolicy - iam:ListAttachedRolePolicies Resource: - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/KarpenterNodeRole-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/eksctl-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/karpenter-irsa-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/prometheus-irsa-*" - !GetAtt FISInterruptionRole.Arn - Effect: Allow Action: iam:PassRole Resource: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/eksctl-*" - Effect: Allow Action: - iam:AddRoleToInstanceProfile - iam:CreateInstanceProfile - iam:RemoveRoleFromInstanceProfile - iam:DeleteInstanceProfile - iam:GetInstanceProfile Resource: - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:instance-profile/KarpenterNodeInstanceProfile-*" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/KarpenterNodeRole-*" - Effect: Allow Action: - iam:CreateOpenIDConnectProvider - iam:DeleteOpenIDConnectProvider - iam:GetOpenIDConnectProvider - iam:TagOpenIDConnectProvider Resource: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/*" - Effect: Allow Action: - iam:CreatePolicy - iam:DeletePolicy - iam:GetPolicy - iam:CreatePolicyVersion - iam:DeletePolicyVersion - iam:ListPolicyVersions Resource: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/KarpenterControllerPolicy-*" - Effect: Allow Action: - cloudformation:CreateChangeSet - cloudformation:CreateStack - cloudformation:DeleteStack - cloudformation:DescribeChangeSet - cloudformation:DescribeStackEvents - cloudformation:ExecuteChangeSet - cloudformation:GetTemplate - cloudformation:GetTemplateSummary Resource: - !Sub "arn:${AWS::Partition}:cloudformation:*:${AWS::AccountId}:stack/iam-*" - !Sub "arn:${AWS::Partition}:cloudformation:*:${AWS::AccountId}:stack/eksctl-*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: - cloudformation:ListStacks - cloudformation:DescribeStacks Resource: "*" - Effect: Allow Action: - eks:CreateCluster - eks:CreateAddon - eks:CreateNodegroup - eks:DeleteCluster - eks:ListFargateProfiles - eks:TagResource - eks:DescribeCluster Resource: - !Sub "arn:${AWS::Partition}:eks:*:${AWS::AccountId}:cluster/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: - eks:DeleteAddon - eks:DescribeAddon Resource: - !Sub "arn:${AWS::Partition}:eks:*:${AWS::AccountId}:addon/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: - eks:DeleteNodegroup - eks:DescribeNodegroup Resource: - !Sub "arn:${AWS::Partition}:eks:*:${AWS::AccountId}:nodegroup/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: fis:CreateExperimentTemplate Resource: - !Sub "arn:${AWS::Partition}:fis:*:${AWS::AccountId}:action/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: - fis:CreateExperimentTemplate - fis:DeleteExperimentTemplate - fis:StartExperiment Resource: - !Sub "arn:${AWS::Partition}:fis:*:${AWS::AccountId}:experiment-template/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: - fis:GetExperiment - fis:StartExperiment Resource: - !Sub "arn:${AWS::Partition}:fis:*:${AWS::AccountId}:experiment/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: - iam:CreateServiceLinkedRole Resource: - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot" - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing" - Effect: Allow Action: - sqs:CreateQueue - sqs:AddPermission - sqs:TagQueue - sqs:SetQueueAttributes - sqs:GetQueueAttributes - sqs:GetQueueUrl - sqs:RemovePermission - sqs:DeleteQueue - sqs:UntagQueue Resource: - !Sub "arn:${AWS::Partition}:sqs:*:${AWS::AccountId}:*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: - events:PutRule - events:DeleteRule - events:DescribeRule - events:PutTargets - events:RemoveTargets - events:EnableRule Resource: !Sub "arn:${AWS::Partition}:events:*:${AWS::AccountId}:rule/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions - Effect: Allow Action: timestream:WriteRecords Resource: !Sub "arn:${AWS::Partition}:timestream:${AWS::Region}:${AWS::AccountId}:database/${DatabaseName}/table/${TableName}" - Effect: Allow Action: timestream:DescribeEndpoints Resource: "*" # GithubActionsPermissionsBoundary includes all permissions needed for all designated roles provisioned by the GithubActions # CI task. This includes the cluster ServiceRoles that are generated by EKSCTL and all roles generated with IRSA to interface from the # cluster into AWS services through IAM. # The policies that are captured inside the GithubActionsPermissionsBoundary include: # - AmazonEC2ContainerRegistryReadOnly # - AmazonEKSWorkerNodePolicy # - AmazonSSMManagedInstanceCore # - AmazonEBSCSIDriverPolicy # - EBS CSI Driver Controller Policy (used by IRSA) # - Prometheus Controller Policy (used by IRSA) # - Karpenter Controller Policy (used by IRSA) # - VPC CNI Daemonset Policy (used by IRSA) GithubActionsPermissionsBoundary: Type: AWS::IAM::ManagedPolicy Properties: ManagedPolicyName: GithubActionsPermissionsBoundary PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: # Tag Permissions - ec2:DescribeTags # Internet Gateway Permissions - ec2:DescribeEgressOnlyInternetGateways - ec2:DescribeInternetGateways # Elastic IP Permissions - ec2:DescribeAddresses # Instance Permissions - ec2:DescribeInstanceTypeOfferings - ec2:DescribeInstanceTypes - ec2:DescribeInstances - ec2:DescribeKeyPairs # Launch Template Permissions - ec2:DescribeLaunchTemplateVersions - ec2:DescribeLaunchTemplates # NAT Gateway Permissions - ec2:DescribeNatGateways # Network Interface Permissions - ec2:DescribeNetworkInterfaces # Route Table Permissions - ec2:DescribeRouteTables # Security Group Permissions - ec2:DescribeSecurityGroups # Subnet Permissions - ec2:DescribeAvailabilityZones - ec2:DescribeSubnets # Volume Permissions - ec2:DescribeVolumes - ec2:DescribeVolumesModifications - ec2:DescribeSnapshots # Network ACL Permissions - ec2:DescribeNetworkAcls # VPC Permissions - ec2:DescribeVpcs # Image Permissions - ec2:DescribeImages Resource: "*" - Effect: Allow Action: # Tag Permissions - ec2:CreateTags - ec2:DeleteTags # Internet Gateway Permissions - ec2:CreateEgressOnlyInternetGateway - ec2:DeleteEgressOnlyInternetGateway # Elastic IP Permissions - ec2:AllocateAddress - ec2:ReleaseAddress # Instance Permissions - ec2:ModifyInstanceAttribute - ec2:DescribeInstanceAttribute - ec2:RunInstances - ec2:StopInstances - ec2:TerminateInstances - ec2:AttachNetworkInterface - ec2:ModifyNetworkInterfaceAttribute - ec2:DetachNetworkInterface # Internet Gateway Permissions - ec2:AttachInternetGateway - ec2:CreateInternetGateway - ec2:DeleteInternetGateway - ec2:DetachInternetGateway # Launch Template Permissions - ec2:CreateLaunchTemplate - ec2:DeleteLaunchTemplate # Fleet Permissions - ec2:CreateFleet # NAT Gateway Permissions - ec2:CreateNatGateway - ec2:DeleteNatGateway # Network Interface Permissions - ec2:AssignPrivateIpAddresses - ec2:UnassignPrivateIpAddresses - ec2:AssignIpv6Addresses - ec2:UnassignIpv6Addresses - ec2:AttachNetworkInterface - ec2:DetachNetworkInterface - ec2:CreateNetworkInterface - ec2:ModifyNetworkInterfaceAttribute - ec2:DeleteNetworkInterface - ec2:CreateNetworkInterfacePermission # Route Table Permissions - ec2:CreateRoute - ec2:CreateRouteTable - ec2:DeleteRoute - ec2:DeleteRouteTable - ec2:AssociateRouteTable - ec2:DisassociateRouteTable # Security Group Permissions - ec2:AuthorizeSecurityGroupIngress - ec2:CreateSecurityGroup - ec2:DeleteSecurityGroup - ec2:RevokeSecurityGroupIngress # Subnet Permissions - ec2:CreateSubnet - ec2:DeleteSubnet - ec2:ModifySubnetAttribute # Volume Permissions - ec2:CreateSnapshot - ec2:DeleteSnapshot - ec2:CreateVolume - ec2:DeleteVolume - ec2:AttachVolume - ec2:ModifyVolume - ec2:DetachVolume # VPC Permissions - ec2:AssociateVpcCidrBlock - ec2:DisassociateVpcCidrBlock - ec2:CreateVpc - ec2:DeleteVpc - ec2:DescribeVpcAttribute - ec2:ModifyVpcAttribute Resource: "*" - Effect: Allow Action: ec2:RunInstances Resource: "*" - Effect: Allow Action: # Read-Only Permissions to pull ECR images needed by the NodeInstanceRole - ecr:GetAuthorizationToken - ecr:BatchCheckLayerAvailability - ecr:GetDownloadUrlForLayer - ecr:GetRepositoryPolicy - ecr:DescribeRepositories - ecr:ListImages - ecr:DescribeImages - ecr:BatchGetImage - ecr:GetLifecyclePolicy - ecr:GetLifecyclePolicyPreview - ecr:ListTagsForResource - ecr:DescribeImageScanFindings Resource: "*" - Effect: Allow Action: # EKS ServiceRole permissions needed for AutoScalingGroups - autoscaling:DescribeAutoScalingGroups - autoscaling:UpdateAutoScalingGroup Resource: "*" - Effect: Allow Action: # EKS ServiceRole permissions needed to handle LoadBalancer - elasticloadbalancing:AddTags - elasticloadbalancing:ApplySecurityGroupsToLoadBalancer - elasticloadbalancing:AttachLoadBalancerToSubnets - elasticloadbalancing:ConfigureHealthCheck - elasticloadbalancing:CreateListener - elasticloadbalancing:CreateLoadBalancer - elasticloadbalancing:CreateLoadBalancerListeners - elasticloadbalancing:CreateLoadBalancerPolicy - elasticloadbalancing:CreateTargetGroup - elasticloadbalancing:DeleteListener - elasticloadbalancing:DeleteLoadBalancer - elasticloadbalancing:DeleteLoadBalancerListeners - elasticloadbalancing:DeleteTargetGroup - elasticloadbalancing:DeregisterInstancesFromLoadBalancer - elasticloadbalancing:DeregisterTargets - elasticloadbalancing:DescribeListeners - elasticloadbalancing:DescribeLoadBalancerAttributes - elasticloadbalancing:DescribeLoadBalancerPolicies - elasticloadbalancing:DescribeLoadBalancers - elasticloadbalancing:DescribeTargetGroupAttributes - elasticloadbalancing:DescribeTargetGroups - elasticloadbalancing:DescribeTargetHealth - elasticloadbalancing:DetachLoadBalancerFromSubnets - elasticloadbalancing:ModifyListener - elasticloadbalancing:ModifyLoadBalancerAttributes - elasticloadbalancing:ModifyTargetGroup - elasticloadbalancing:ModifyTargetGroupAttributes - elasticloadbalancing:RegisterInstancesWithLoadBalancer - elasticloadbalancing:RegisterTargets - elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer - elasticloadbalancing:SetLoadBalancerPoliciesOfListener Resource: "*" - Effect: Allow Action: - kms:CreateGrant - kms:GenerateDataKeyWithoutPlaintext - kms:DescribeKey Resource: "*" - Effect: Allow Action: # SSM Permissions for AmazonSSMManagedInstanceCore policy applied to the NodeInstanceRole - ssm:DescribeAssociation - ssm:GetDeployablePatchSnapshotForInstance - ssm:GetDocument - ssm:DescribeDocument - ssm:GetManifest - ssm:GetParameter - ssm:GetParameters - ssm:ListAssociations - ssm:ListInstanceAssociations - ssm:PutInventory - ssm:PutComplianceItems - ssm:PutConfigurePackageResult - ssm:UpdateAssociationStatus - ssm:UpdateInstanceAssociationStatus - ssm:UpdateInstanceInformation Resource: "*" - Effect: Allow Action: # SSM Permissions for AmazonSSMManagedInstanceCore policy applied to the NodeInstanceRole - ssmmessages:CreateControlChannel - ssmmessages:CreateDataChannel - ssmmessages:OpenControlChannel - ssmmessages:OpenDataChannel Resource: "*" - Effect: Allow Action: # SSM Permissions for AmazonSSMManagedInstanceCore policy applied to the NodeInstanceRole - ec2messages:AcknowledgeMessage - ec2messages:DeleteMessage - ec2messages:FailMessage - ec2messages:GetEndpoint - ec2messages:GetMessages - ec2messages:SendReply Resource: "*" - Effect: Allow Action: - sqs:DeleteMessage - sqs:GetQueueAttributes - sqs:GetQueueUrl - sqs:SendMessage - sqs:ReceiveMessage Resource: "*" - Effect: Allow Action: iam:PassRole Resource: - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/KarpenterNodeRole-*" - !GetAtt FISInterruptionRole.Arn - Effect: Allow Action: - pricing:GetProducts - ec2:DescribeSpotPriceHistory Resource: "*" - Effect: Allow Action: eks:DescribeCluster Resource: "*" - Effect: Allow Action: - aps:RemoteWrite - aps:GetSeries - aps:GetLabels - aps:GetMetricMetadata Resource: !Sub "arn:${AWS::Partition}:aps:${AWS::Region}:${AWS::AccountId}:workspace/${PrometheusWorkspaceID}" GithubActionsRole: Type: AWS::IAM::Role Properties: RoleName: GithubActionsRole ManagedPolicyArns: - !Ref GithubActionsPolicy - !Ref GithubActionsPermissionsBoundary MaxSessionDuration: 21600 # 6 hours is the max session for GHA AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Federated: !Ref GithubOIDCProvider Action: "sts:AssumeRoleWithWebIdentity" Condition: StringEquals: token.actions.githubusercontent.com:aud: sts.amazonaws.com StringLike: token.actions.githubusercontent.com:sub: !Sub "repo:${Repository}:ref:${Branches}" - Effect: Allow Principal: AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root" Action: "sts:AssumeRole" FISInterruptionRole: Type: AWS::IAM::Role Properties: RoleName: FISInterruptionRole ManagedPolicyArns: - !Ref FISInterruptionPolicy MaxSessionDuration: 3600 AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: "fis.amazonaws.com" Action: "sts:AssumeRole" FISInterruptionPolicy: Type: AWS::IAM::ManagedPolicy Properties: ManagedPolicyName: FISInterruptionPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: ec2:SendSpotInstanceInterruptions Resource: - !Sub "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:instance/*" Condition: StringEquals: aws:RequestedRegion: Ref: Regions