AWSTemplateFormatVersion: '2010-09-09' Description: |- > Deploys the identity management for the deployment # Granulatiy cheatsheet: https://iam.cloudonaut.io/ Parameters: WebStackName: Type: String Default: privacysexy-web-stack Description: Name of the web stack. DnsStackName: Type: String Default: privacysexy-dns-stack Description: Name of the DNS stack. CertificateStackName: Type: String Default: privacysexy-certificate-stack Description: Name of the IAM stack. Resources: # ----------------------------- # ------ User & Group --------- # ----------------------------- DeploymentGroup: Type: AWS::IAM::Group Properties: # GroupName: No hardcoded naming because of easier CloudFormation management ManagedPolicyArns: - !Ref AllowValidateTemplatePolicy DeploymentUser: Type: AWS::IAM::User Properties: # # UserName: No hardcoded naming because of easier CloudFormation management # # Policies: Assing policies on group level Tags: - Key: Application Value: privacy.sexy AddDeploymentUserToDeploymentGroup: Type: AWS::IAM::UserToGroupAddition Properties: GroupName: !Ref DeploymentGroup Users: - !Ref DeploymentUser # ----------------------------- # ----------- Roles ----------- # ----------------------------- IamStackDeployRole: Type: AWS::IAM::Role Properties: Description: Allows to deploy IAM stack AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: !GetAtt DeploymentUser.Arn Action: sts:AssumeRole Tags: - Key: Application Value: privacy.sexy ManagedPolicyArns: - !Ref CloudFormationDeployPolicy - !Ref PolicyDeployPolicy - !Ref IamStackDeployPolicy CertificateStackDeployRole: Type: AWS::IAM::Role Properties: Description: Allows to deploy certificate stack AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: !GetAtt DeploymentUser.Arn Action: sts:AssumeRole Tags: - Key: Application Value: privacy.sexy ManagedPolicyArns: - !Ref CloudFormationDeployPolicy - !Ref LambdaBackedCustomResourceDeployPolicy DnsStackDeployRole: Type: AWS::IAM::Role Properties: Description: Allows to deploy DNS stack AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: !GetAtt DeploymentUser.Arn Action: sts:AssumeRole Tags: - Key: Application Value: privacy.sexy ManagedPolicyArns: - !Ref CloudFormationDeployPolicy - !Ref DnsStackDeployPolicy WebStackDeployRole: Type: AWS::IAM::Role Properties: Description: Allows to deploy web stack AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: !GetAtt DeploymentUser.Arn Action: sts:AssumeRole Tags: - Key: Application Value: privacy.sexy ManagedPolicyArns: - !Ref CloudFormationDeployPolicy - !Ref WebStackDeployPolicy S3SiteDeployRole: Type: 'AWS::IAM::Role' Properties: Description: "Allows to deploy website to S3" AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: !GetAtt DeploymentUser.Arn Action: sts:AssumeRole Tags: - Key: Application Value: privacy.sexy ManagedPolicyArns: - !Ref S3SiteDeployPolicy - !Ref StackExportReaderPolicy CloudFrontSiteDeployRole: Type: 'AWS::IAM::Role' Properties: Description: "Allows to informs to CloudFront to renew its cache from S3" AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: !GetAtt DeploymentUser.Arn Action: sts:AssumeRole Tags: - Key: Application Value: privacy.sexy ManagedPolicyArns: - !Ref CloudFrontInvalidationPolicy - !Ref StackExportReaderPolicy ResolveCertificateLambdaRole: # See certificate stack Type: AWS::IAM::Role Properties: Description: Allow deployment of certificates AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - !Ref CertificateDeployPolicy # -------------------------------- # ----------- Policies ----------- # -------------------------------- AllowValidateTemplatePolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: "No read & writes to resources, reveals just basic CloudFormation API to be used for validating templates" # ManagedPolicyName: No hardcoded naming because of easier CloudFormation management PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowCloudFormationTemplateValidation Effect: Allow Action: - cloudformation:ValidateTemplate Resource: '*' CloudFormationDeployPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: "Allows deploying CloudFormation using CLI command 'aws cloudformation deploy' (with change sets)" # ManagedPolicyName: No hardcoded naming because of easier CloudFormation management PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowCloudFormationStackOperations Effect: Allow Action: - cloudformation:GetTemplateSummary - cloudformation:DescribeStacks - cloudformation:CreateChangeSet - cloudformation:ExecuteChangeSet - cloudformation:DescribeChangeSet Resource: - !Sub arn:aws:cloudformation:*:${AWS::AccountId}:stack/${WebStackName}/* - !Sub arn:aws:cloudformation:*:${AWS::AccountId}:stack/${DnsStackName}/* - !Sub arn:aws:cloudformation:*:${AWS::AccountId}:stack/${AWS::StackName}/* - !Sub arn:aws:cloudformation:*:${AWS::AccountId}:stack/${CertificateStackName}/* IamStackDeployPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows deploying IAM CloudFormation stack. # ManagedPolicyName: No hardcoded naming because of easier CloudFormation management PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowUserArnExport Effect: Allow Action: - iam:GetUser Resource: - !GetAtt DeploymentUser.Arn - Sid: AllowTagging Effect: Allow Action: - iam:TagResource Resource: - !Sub arn:aws:cloudformation::${AWS::AccountId}:stack/${AWS::StackName}/* - !GetAtt DeploymentUser.Arn - Sid: AllowRoleDeployment Effect: Allow Action: - iam:CreateRole Resource: - !Sub arn:aws:iam::${AWS::AccountId}:role/${AWS::StackName}-* LambdaBackedCustomResourceDeployPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows deploying a lambda-backed custom resource. # ManagedPolicyName: # ManagedPolicyName: No hardcoded naming because of easier CloudFormation management PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowLambdaDeployment Effect: Allow Action: - lambda:GetFunction - lambda:DeleteFunction - lambda:CreateFunction - lambda:GetFunctionConfiguration - lambda:InvokeFunction Resource: - !Sub arn:aws:lambda:*:${AWS::AccountId}:function:${CertificateStackName}* - Sid: AllowPassingLambdaRole Effect: Allow Action: - iam:PassRole Resource: - !GetAtt ResolveCertificateLambdaRole.Arn CertificateDeployPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows deploying certifications stack. # ManagedPolicyName: # ManagedPolicyName: No hardcoded naming because of easier CloudFormation management PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowCertificateDeployment Effect: Allow Action: - acm:RequestCertificate - acm:DescribeCertificate - acm:DeleteCertificate - acm:AddTagsToCertificate - acm:ListCertificates Resource: '*' # Certificate Manager does not support resource level IAM PolicyDeployPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows deployment of policies # ManagedPolicyName: Commented out because CloudFormation requires to rename when replacing custom-named resource PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowPolicyUpdates Effect: Allow Action: - iam:ListPolicyVersions - iam:CreatePolicyVersion - iam:DeletePolicyVersion - iam:CreatePolicy - iam:DeletePolicy - iam:GetPolicy Resource: - !Sub arn:aws:iam::${AWS::AccountId}:policy/${AWS::StackName}-* # when ManagedPolicyName is not given policies get name like StackName-* - Sid: AllowPoliciesOnRoles Effect: Allow Action: - iam:AttachRolePolicy - iam:DetachRolePolicy - iam:GetRole Resource: - !Sub arn:aws:iam::${AWS::AccountId}:role/${AWS::StackName}-* - Sid: AllowPolicyAssigmentToGroup Effect: Allow Action: - iam:AttachGroupPolicy - iam:DetachGroupPolicy Resource: - !GetAtt DeploymentGroup.Arn - Sid: AllowGettingGroupInformation Effect: Allow Action: - iam:GetGroup Resource: !Sub arn:aws:iam::${AWS::AccountId}:group/${DeploymentGroup} DnsStackDeployPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows deployment of DNS stack PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowHostedZoneDeployment Effect: Allow Action: - route53:CreateHostedZone - route53:ListQueryLoggingConfigs - route53:DeleteHostedZone - route53:GetChange - route53:ChangeTagsForResource - route53:GetHostedZone - route53:ChangeResourceRecordSets Resource: '*' # Does not support resource-level permissions https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/access-control-overview.html#access-control-manage-access-intro-resource-policies WebStackDeployPolicy: # We need a role to run s3:PutBucketPolicy, IAM users cannot run it. See https://stackoverflow.com/a/48551383 Type: AWS::IAM::ManagedPolicy Properties: Description: Allows deployment of web stack PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowCloudFrontOAIDeployment Effect: Allow Action: - cloudfront:GetCloudFrontOriginAccessIdentity - cloudfront:CreateCloudFrontOriginAccessIdentity - cloudfront:GetCloudFrontOriginAccessIdentityConfig - cloudfront:DeleteCloudFrontOriginAccessIdentity Resource: '*' # Does not support resource-level permissions https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cf-api-permissions-ref.html - Sid: AllowCloudFrontDistributionDeployment Effect: Allow Action: - cloudfront:CreateDistribution - cloudfront:DeleteDistribution - cloudfront:UpdateDistribution - cloudfront:GetDistribution - cloudfront:TagResource - cloudfront:UpdateCloudFrontOriginAccessIdentity Resource: !Sub arn:aws:cloudfront::${AWS::AccountId}:* - Sid: AllowS3BucketPolicyAccess Effect: Allow Action: - s3:CreateBucket - s3:DeleteBucket - s3:PutBucketWebsite - s3:DeleteBucketPolicy - s3:PutBucketPolicy - s3:GetBucketPolicy Resource: !Sub arn:aws:s3:::${WebStackName}* - Sid: AllowRecordDeploymentToRoute53 Effect: Allow Action: - route53:GetHostedZone - route53:ChangeResourceRecordSets - route53:GetChange - route53:ListResourceRecordSets Resource: '*' # Does not support resource-level permissions https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/access-control-overview.html#access-control-manage-access-intro-resource-policies S3SiteDeployPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows listing buckets to be able to list objects in a bucket # ManagedPolicyName: Commented out because CloudFormation requires to rename when replacing custom-named resources PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowListingObjects Effect: Allow Action: - s3:ListBucket # To allow ListObjectsV2 Resource: !Sub arn:aws:s3:::${WebStackName}* - Sid: AllowUpdatingObjects Effect: Allow Action: - s3:PutObject - s3:DeleteObject Resource: !Sub arn:aws:s3:::${WebStackName}*/* CloudFrontInvalidationPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows creating invalidations on CloudFront # ManagedPolicyName: Commented out because CloudFormation requires to rename when replacing custom-named resource PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowCloudFrontInvalidations Effect: Allow Action: - cloudfront:CreateInvalidation Resource: "*" # Does not support resource-level permissions https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cf-api-permissions-ref.html StackExportReaderPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allows creating invalidations on CloudFront # ManagedPolicyName: Commented out because CloudFormation requires to rename when replacing custom-named resource PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowGettingBucketName Effect: Allow Action: - cloudformation:DescribeStacks Resource: !Sub arn:aws:cloudformation:*:${AWS::AccountId}:stack/${WebStackName}/* Outputs: ResolveCertificateLambdaRoleArn: Description: The Amazon Resource Name (ARN) of the lambda for deploying certificates. Value: !GetAtt ResolveCertificateLambdaRole.Arn Export: Name: !Join [ ':', [ !Ref 'AWS::StackName', ResolveCertificateLambdaRoleArn ] ] CertificateStackDeployRoleArn: Description: "GitHub secret: AWS_CERTIFICATE_STACK_DEPLOYMENT_ROLE_ARN" Value: !GetAtt CertificateStackDeployRole.Arn DnsStackDeployRoleArn: Description: "GitHub secret: AWS_DNS_STACK_DEPLOYMENT_ROLE_ARN" Value: !GetAtt DnsStackDeployRole.Arn IamStackDeployRoleArn: Description: "GitHub secret: AWS_IAM_STACK_DEPLOYMENT_ROLE_ARN" Value: !GetAtt IamStackDeployRole.Arn WebStackDeployRoleArn: Description: "GitHub secret: AWS_WEB_STACK_DEPLOYMENT_ROLE_ARN" Value: !GetAtt WebStackDeployRole.Arn S3SiteDeployRoleArn: Description: "GitHub secret: AWS_S3_SITE_DEPLOYMENT_ROLE_ARN" Value: !GetAtt S3SiteDeployRole.Arn CloudFrontSiteDeployRoleArn: Description: "GitHub secret: AWS_CLOUDFRONT_SITE_DEPLOYMENT_ROLE_ARN" Value: !GetAtt CloudFrontSiteDeployRole.Arn