mirror of
https://github.com/Sea-Haven-Industries/sh-openswe-traces.git
synced 2026-09-30 08:03:18 +00:00
Some checks failed
Deploy / deploy (push) Has been cancelled
The dedicated CFN exec role hit AccessDenied on CreateChangeSet against arn:...:aws:transform/Serverless-2016-10-31 during the first CI deploy (template uses Transform: AWS::Serverless-2016-10-31). Scoped grant on that transform ARN only. Cross-review: APPROVE (non-escalating).
209 lines
9.1 KiB
YAML
209 lines
9.1 KiB
YAML
AWSTemplateFormatVersion: "2010-09-09"
|
|
Description: >
|
|
Bootstrap IAM for the sh-openswe-traces app stack. Deployed ONCE, manually, under
|
|
admin (CAPABILITY_NAMED_IAM). Creates two named roles so CI never touches the shared
|
|
github-cfn-execution-role:
|
|
- DeployRole (githubdeploy-sh-openswe-traces): assumed by this repo's GitHub
|
|
Actions via OIDC (main branch only); can drive CloudFormation for THIS stack and
|
|
pass the exec role.
|
|
- ExecRole (sh-openswe-traces-cfn-exec-role): assumed by CloudFormation to create
|
|
the app stack's resources; least-privilege to exactly this stack's resource set.
|
|
|
|
Resources:
|
|
ExecRole:
|
|
Type: AWS::IAM::Role
|
|
Properties:
|
|
RoleName: sh-openswe-traces-cfn-exec-role
|
|
Description: CloudFormation execution role for the sh-openswe-traces app stack.
|
|
AssumeRolePolicyDocument:
|
|
Version: "2012-10-17"
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Service: cloudformation.amazonaws.com
|
|
Action: sts:AssumeRole
|
|
Condition:
|
|
StringEquals:
|
|
"aws:SourceAccount": !Ref "AWS::AccountId"
|
|
Policies:
|
|
- PolicyName: manage-sh-openswe-traces-resources
|
|
PolicyDocument:
|
|
Version: "2012-10-17"
|
|
Statement:
|
|
# Defense-in-depth: this role can create sh-openswe-traces-* users, so
|
|
# explicitly forbid the actions that would turn one into a usable/escalated
|
|
# principal (credentials, console login, extra policies, boundary removal).
|
|
- Sid: DenyUserCredentialAndEscalation
|
|
Effect: Deny
|
|
Action:
|
|
- "iam:CreateAccessKey"
|
|
- "iam:CreateLoginProfile"
|
|
- "iam:UpdateLoginProfile"
|
|
- "iam:AttachUserPolicy"
|
|
- "iam:CreateServiceSpecificCredential"
|
|
- "iam:PutUserPermissionsBoundary"
|
|
- "iam:DeleteUserPermissionsBoundary"
|
|
Resource: "*"
|
|
- Sid: Buckets
|
|
Effect: Allow
|
|
Action:
|
|
- "s3:CreateBucket"
|
|
- "s3:DeleteBucket"
|
|
- "s3:PutBucketPolicy"
|
|
- "s3:DeleteBucketPolicy"
|
|
- "s3:GetBucketPolicy"
|
|
- "s3:PutEncryptionConfiguration"
|
|
- "s3:GetEncryptionConfiguration"
|
|
- "s3:PutBucketVersioning"
|
|
- "s3:GetBucketVersioning"
|
|
- "s3:PutBucketPublicAccessBlock"
|
|
- "s3:GetBucketPublicAccessBlock"
|
|
- "s3:PutBucketOwnershipControls"
|
|
- "s3:GetBucketOwnershipControls"
|
|
- "s3:PutLifecycleConfiguration"
|
|
- "s3:GetLifecycleConfiguration"
|
|
- "s3:PutBucketLogging"
|
|
- "s3:GetBucketLogging"
|
|
- "s3:PutBucketTagging"
|
|
- "s3:GetBucketTagging"
|
|
- "s3:GetBucketLocation"
|
|
- "s3:GetBucketAcl"
|
|
Resource:
|
|
- "arn:aws:s3:::sh-openswe-traces"
|
|
- "arn:aws:s3:::sh-openswe-traces-logs"
|
|
# CreateKey/CreateAlias cannot be resource-scoped (the key does not yet
|
|
# exist). Only CloudFormation can assume this role, and only to deploy this
|
|
# stack, so the blast radius is bounded to this stack's deployments.
|
|
- Sid: Kms
|
|
Effect: Allow
|
|
Action:
|
|
- "kms:CreateKey"
|
|
- "kms:CreateAlias"
|
|
- "kms:DeleteAlias"
|
|
- "kms:UpdateAlias"
|
|
- "kms:PutKeyPolicy"
|
|
- "kms:GetKeyPolicy"
|
|
- "kms:EnableKeyRotation"
|
|
- "kms:DisableKeyRotation"
|
|
- "kms:GetKeyRotationStatus"
|
|
- "kms:DescribeKey"
|
|
- "kms:TagResource"
|
|
- "kms:UntagResource"
|
|
- "kms:ListResourceTags"
|
|
- "kms:ScheduleKeyDeletion"
|
|
- "kms:EnableKey"
|
|
Resource: "*"
|
|
- Sid: Secret
|
|
Effect: Allow
|
|
Action:
|
|
- "secretsmanager:CreateSecret"
|
|
- "secretsmanager:DeleteSecret"
|
|
- "secretsmanager:DescribeSecret"
|
|
- "secretsmanager:UpdateSecret"
|
|
- "secretsmanager:TagResource"
|
|
- "secretsmanager:UntagResource"
|
|
- "secretsmanager:GetResourcePolicy"
|
|
- "secretsmanager:PutResourcePolicy"
|
|
Resource: !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:sh-openswe/*"
|
|
- Sid: ExportUser
|
|
Effect: Allow
|
|
Action:
|
|
- "iam:CreateUser"
|
|
- "iam:DeleteUser"
|
|
- "iam:GetUser"
|
|
- "iam:TagUser"
|
|
- "iam:UntagUser"
|
|
- "iam:PutUserPolicy"
|
|
- "iam:DeleteUserPolicy"
|
|
- "iam:GetUserPolicy"
|
|
- "iam:ListUserPolicies"
|
|
- "iam:ListUserTags"
|
|
- "iam:ListAttachedUserPolicies"
|
|
- "iam:ListGroupsForUser"
|
|
Resource: !Sub "arn:aws:iam::${AWS::AccountId}:user/sh-openswe-traces-*"
|
|
# Required because template.yaml uses Transform: AWS::Serverless-2016-10-31.
|
|
# CloudFormation (as this exec role) must CreateChangeSet on the AWS-managed
|
|
# SAM transform macro. Scoped to only that transform ARN.
|
|
- Sid: SamTransform
|
|
Effect: Allow
|
|
Action: "cloudformation:CreateChangeSet"
|
|
Resource: !Sub "arn:aws:cloudformation:${AWS::Region}:aws:transform/Serverless-2016-10-31"
|
|
|
|
DeployRole:
|
|
Type: AWS::IAM::Role
|
|
Properties:
|
|
RoleName: githubdeploy-sh-openswe-traces
|
|
Description: GitHub Actions OIDC deploy role for the sh-openswe-traces app stack.
|
|
MaxSessionDuration: 3600
|
|
AssumeRolePolicyDocument:
|
|
Version: "2012-10-17"
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Federated: !Sub "arn:aws:iam::${AWS::AccountId}: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:Sea-Haven-Industries/sh-openswe-traces:ref:refs/heads/main"
|
|
Policies:
|
|
- PolicyName: deploy-sh-openswe-traces
|
|
PolicyDocument:
|
|
Version: "2012-10-17"
|
|
Statement:
|
|
- Sid: AppStack
|
|
Effect: Allow
|
|
Action:
|
|
- "cloudformation:CreateChangeSet"
|
|
- "cloudformation:ExecuteChangeSet"
|
|
- "cloudformation:DescribeChangeSet"
|
|
- "cloudformation:DeleteChangeSet"
|
|
- "cloudformation:CreateStack"
|
|
- "cloudformation:UpdateStack"
|
|
- "cloudformation:DescribeStacks"
|
|
- "cloudformation:DescribeStackEvents"
|
|
- "cloudformation:DescribeStackResource"
|
|
- "cloudformation:DescribeStackResources"
|
|
- "cloudformation:ListStackResources"
|
|
- "cloudformation:GetTemplate"
|
|
- "cloudformation:GetTemplateSummary"
|
|
Resource:
|
|
- !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/sh-openswe-traces/*"
|
|
- !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:changeSet/*/*"
|
|
# SAM's --resolve-s3 looks up (does not recreate) the pre-existing managed
|
|
# artifact stack + bucket.
|
|
- Sid: SamManagedStackRead
|
|
Effect: Allow
|
|
Action:
|
|
- "cloudformation:DescribeStacks"
|
|
Resource: !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/aws-sam-cli-managed-default/*"
|
|
- Sid: SamArtifactBucket
|
|
Effect: Allow
|
|
Action:
|
|
- "s3:GetObject"
|
|
- "s3:PutObject"
|
|
- "s3:GetBucketLocation"
|
|
- "s3:ListBucket"
|
|
Resource:
|
|
- "arn:aws:s3:::aws-sam-cli-managed-default-*"
|
|
- "arn:aws:s3:::aws-sam-cli-managed-default-*/*"
|
|
- Sid: CfnValidate
|
|
Effect: Allow
|
|
Action:
|
|
- "cloudformation:ValidateTemplate"
|
|
Resource: "*"
|
|
- Sid: PassExecRoleToCfn
|
|
Effect: Allow
|
|
Action: "iam:PassRole"
|
|
Resource: !GetAtt ExecRole.Arn
|
|
Condition:
|
|
StringEquals:
|
|
"iam:PassedToService": cloudformation.amazonaws.com
|
|
|
|
Outputs:
|
|
DeployRoleArn:
|
|
Description: Set as the repo secret AWS_DEPLOY_ROLE_ARN.
|
|
Value: !GetAtt DeployRole.Arn
|
|
ExecRoleArn:
|
|
Description: Set as cfn-role-arn in .github/workflows/deploy.yaml.
|
|
Value: !GetAtt ExecRole.Arn
|