diff --git a/ci/terraform/oidc/sandpit.tfvars b/ci/terraform/oidc/sandpit.tfvars
index 3065bfd271..9b6c1e0aec 100644
--- a/ci/terraform/oidc/sandpit.tfvars
+++ b/ci/terraform/oidc/sandpit.tfvars
@@ -65,6 +65,7 @@ orch_account_id = "816047645251"
back_channel_logout_cross_account_access_enabled = true
kms_cross_account_access_enabled = true
cmk_for_back_channel_logout_enabled = true
+spot_request_queue_cross_account_access_enabled = true
oidc_origin_domain_enabled = true
diff --git a/ci/terraform/oidc/spot-sqs.tf b/ci/terraform/oidc/spot-sqs.tf
index e3d17937c3..28a211d141 100644
--- a/ci/terraform/oidc/spot-sqs.tf
+++ b/ci/terraform/oidc/spot-sqs.tf
@@ -27,6 +27,48 @@ resource "aws_sqs_queue" "spot_request_dead_letter_queue" {
tags = local.default_tags
}
+data "aws_iam_policy_document" "cross_account_spot_request_queue_policy_document" {
+ statement {
+ sid = "AllowSpotAccountToReceive"
+ effect = "Allow"
+
+ principals {
+ type = "AWS"
+ identifiers = [aws_ssm_parameter.spot_account_number.value]
+ }
+
+ actions = [
+ "sqs:ReceiveMessage",
+ "sqs:ChangeMessageVisibility",
+ "sqs:DeleteMessage",
+ "sqs:GetQueueAttributes",
+ ]
+
+ resources = [
+ aws_sqs_queue.spot_request_queue.arn
+ ]
+ }
+
+ statement {
+ sid = "AllowOrchAccountSendSQS-${var.environment}"
+ effect = "Allow"
+
+ principals {
+ type = "AWS"
+ identifiers = [var.orch_account_id]
+ }
+
+ actions = [
+ "sqs:SendMessage",
+ "sqs:ChangeMessageVisibility",
+ "sqs:GetQueueAttributes",
+ ]
+ resources = [
+ aws_sqs_queue.spot_request_queue.arn
+ ]
+ }
+}
+
data "aws_iam_policy_document" "spot_request_queue_policy_document" {
statement {
sid = "AllowSpotAccountToReceive"
@@ -51,12 +93,8 @@ data "aws_iam_policy_document" "spot_request_queue_policy_document" {
}
resource "aws_sqs_queue_policy" "spot_request_queue_policy" {
- depends_on = [
- data.aws_iam_policy_document.spot_request_queue_policy_document,
- ]
-
queue_url = aws_sqs_queue.spot_request_queue.id
- policy = data.aws_iam_policy_document.spot_request_queue_policy_document.json
+ policy = var.spot_request_queue_cross_account_access_enabled ? data.aws_iam_policy_document.cross_account_spot_request_queue_policy_document.json : data.aws_iam_policy_document.spot_request_queue_policy_document.json
}
data "aws_iam_policy_document" "spot_request_dlq_queue_policy_document" {
@@ -119,10 +157,56 @@ data "aws_iam_policy_document" "spot_request_kms_key_policy" {
}
}
+data "aws_iam_policy_document" "cross_account_spot_request_kms_key_policy" {
+ policy_id = "cross-account-key-policy-ssm"
+
+ statement {
+ sid = "Enable IAM User Permissions for root user"
+ actions = [
+ "kms:*",
+ ]
+ effect = "Allow"
+ principals {
+ type = "AWS"
+ identifiers = [data.aws_caller_identity.current.account_id]
+ }
+ resources = ["*"]
+ }
+
+ statement {
+ sid = "Give SPOT permissions to SQS KMS key"
+ actions = [
+ "kms:Decrypt",
+ ]
+ effect = "Allow"
+ principals {
+ type = "AWS"
+ identifiers = [aws_ssm_parameter.spot_account_number.value]
+ }
+ resources = ["*"]
+ }
+
+ statement {
+ sid = "AllowOrchAccessToSpotRequestQueueEncryptionKey-${var.environment}"
+ effect = "Allow"
+
+ actions = [
+ "kms:Decrypt",
+ "kms:GenerateDataKey"
+ ]
+ resources = ["*"]
+
+ principals {
+ type = "AWS"
+ identifiers = [var.orch_account_id]
+ }
+ }
+}
+
resource "aws_kms_key" "spot_request_sqs_key" {
description = "KMS key for SPOT request SQS queue encryption"
deletion_window_in_days = 30
- policy = data.aws_iam_policy_document.spot_request_kms_key_policy.json
+ policy = var.spot_request_queue_cross_account_access_enabled ? data.aws_iam_policy_document.cross_account_spot_request_kms_key_policy.json : data.aws_iam_policy_document.spot_request_kms_key_policy.json
customer_master_key_spec = "SYMMETRIC_DEFAULT"
key_usage = "ENCRYPT_DECRYPT"
diff --git a/ci/terraform/oidc/variables.tf b/ci/terraform/oidc/variables.tf
index 40e313fe6c..b785b8a50b 100644
--- a/ci/terraform/oidc/variables.tf
+++ b/ci/terraform/oidc/variables.tf
@@ -599,6 +599,12 @@ variable "kms_cross_account_access_enabled" {
description = "Whether the service should allow cross-account access by the orchestration account to kms"
}
+variable "spot_request_queue_cross_account_access_enabled" {
+ default = false
+ type = bool
+ description = "Whether the service should allow cross-account access by orchestration to the SPoT request queue"
+}
+
variable "oidc_origin_domain_enabled" {
type = bool
default = false
diff --git a/test-template.yaml b/test-template.yaml
new file mode 100644
index 0000000000..1955509801
--- /dev/null
+++ b/test-template.yaml
@@ -0,0 +1,6615 @@
+AWSTemplateFormatVersion: "2010-09-09"
+
+Description: >
+ devplatform-deploy sam-deploy-pipeline template version: v2.52.4
+ TEST TEMPLATE, DO NOT DEPLOY BEYOND DEV.
+
+
+Metadata:
+ AWS::CloudFormation::Interface:
+ ParameterGroups:
+ - Label:
+ default: "General configuration"
+ Parameters:
+ - SAMStackName
+ - Environment
+ - VpcStackName
+ - RequireManualApproval
+ - IncludePromotion
+ - AllowedAccounts
+ - AWSOrganizationId
+ - LogRetentionDays
+ - InvokableLambdaAccounts
+ - AccessDynamoDBAccounts
+ - AbortOnCheckovFailure
+ - Label:
+ default: "Signing configuration"
+ Parameters:
+ - ContainerSignerKmsKeyArn
+ - CustomKmsKeyArns
+ - SigningProfileArn
+ - SigningProfileVersionArn
+ - AdditionalCodeSigningVersionArns
+ - Label:
+ default: "Source configuration"
+ Parameters:
+ - ArtifactSourceBucketArn
+ - ArtifactSourceBucketEventTriggerRoleArn
+ - GitHubRepositoryName
+ - OneLoginRepositoryName
+ - Label:
+ default: "Permissions Boundary Configuration"
+ Parameters:
+ - ProgrammaticPermissionsBoundary
+ - AllowedServiceOne
+ - AllowedServiceTwo
+ - AllowedServiceThree
+ - AllowedServiceFour
+ - AllowedServiceFive
+ - AllowedServiceSix
+ - AllowedServiceSeven
+ - DynamicResourcesPrefix
+ - Label:
+ default: "Test configuration"
+ Parameters:
+ - RequireTestContainerSignatureValidation
+ - TestImageRepositoryUri
+ - TestReportFormat
+ - TestCoverageReportFormat
+ - TestComputeType
+ - RunTestContainerInVPC
+ - Label:
+ default: "Canary Deployments"
+ Parameters:
+ - ECSCanaryDeployment
+ - LambdaCanaryDeployment
+ - TrafficTestImageRepositoryUri
+ - Label:
+ default: "Build notifications"
+ Parameters:
+ - SlackNotificationType
+ - BuildNotificationStackName
+ - Label:
+ default: "Log artifact write times to Grafana"
+ Parameters:
+ - ArtifactWriteTimeLoggingLambdaArn
+ - Label:
+ default: "Bucket configurations"
+ Parameters:
+ - AccessLogsCustomBucketNameEnabled
+ - Label:
+ default: "Miscellaneous"
+ Parameters:
+ - TruncatedPipelineStackName
+
+ # This rule is slowing the linting down by 20min+ as it's struggling
+ # to resolve the conditions in ProgrammaticPermissionsBoundary.
+ # This can be reconsidered in the future.
+ cfn-lint:
+ config:
+ ignore_checks:
+ - E3502
+
+Parameters:
+ SAMStackName:
+ Description: >
+ The name to use for the SAM stack that will be deployed by this
+ pipeline, passed to --stack-name to sam deploy
+ Type: "String"
+ AllowedPattern: "[a-z0-9][a-z0-9-]{0,21}[a-z0-9]"
+ ConstraintDescription: >
+ must consist of lowercase letters, numbers and hyphens;
+ with no more than 23 characters and must not start or end with hyphen
+
+ TruncatedPipelineStackName:
+ Description: >
+ Truncated Pipeline stack name to apply to IAM role names in order to comply
+ with the 64-character length limits set by AWS.
+ Type: "String"
+ Default: "none"
+ AllowedPattern: "[a-zA-Z0-9][a-zA-Z0-9-]{0,21}[a-zA-Z0-9]"
+ ConstraintDescription: >
+ must consist of uppercase, lowercase letters, numbers and hyphens;
+ with no more than 23 characters and must not start or end with hyphen
+
+ Environment:
+ Description: "The name of the environment to deploy to"
+ Type: "String"
+ AllowedValues:
+ - build
+ - staging
+ - production
+ - integration
+ - demo
+ - local
+ - dev
+
+ ProgrammaticPermissionsBoundary:
+ Description: >
+ Setting this parameter to "True" will create a programmatic
+ Permissions Boundary, enabling you to choose which services your
+ application stack needs to run. If set to "False", no services
+ need to be selected from the parameters below. The PPB has a core
+ set of services always allowed, for more information please see
+ documentation at https://govukverify.atlassian.net/wiki/x/NIBOyg.
+ Default: "False"
+ Type: "String"
+ AllowedValues:
+ - "False"
+ - "True"
+
+ AllowedServiceOne:
+ Description: >
+ Select a service your application needs permissions for (1 of 7)
+ Core services included: CloudFormation, CloudWatch, Logs, CodeBuild,
+ IAM, KMS, S3, Secrets Manager and Textract.
+ Default: "none"
+ Type: "String"
+ AllowedValues:
+ - none
+ - Athena & Glue
+ - Athena, Glue & Redshift
+ - Cognito
+ - DynamoDB
+ - ECR & ECS
+ - EC2
+ - EventBridge
+ - Firehose & Kinesis
+ - Lambda
+ - PerformanceTest
+ - QuickSight
+ - SNS
+ - SSM
+ - StepFunctions
+ - SQS
+ - Xray
+
+ AllowedServiceTwo:
+ Description: >
+ Select a service your application needs permissions for (2 of 7)
+ Core services included: CloudFormation, CloudWatch, Logs, CodeBuild,
+ IAM, KMS, S3, Secrets Manager and Textract.
+ Default: "none"
+ Type: "String"
+ AllowedValues:
+ - none
+ - Athena & Glue
+ - Athena, Glue & Redshift
+ - Cognito
+ - DynamoDB
+ - ECR & ECS
+ - EC2
+ - EventBridge
+ - Firehose & Kinesis
+ - Lambda
+ - PerformanceTest
+ - QuickSight
+ - SNS
+ - SSM
+ - StepFunctions
+ - SQS
+ - Xray
+
+ AllowedServiceThree:
+ Description: >
+ Select a service your application needs permissions for (3 of 7)
+ Core services included: CloudFormation, CloudWatch, Logs, CodeBuild,
+ IAM, KMS, S3, Secrets Manager and Textract.
+ Default: "none"
+ Type: "String"
+ AllowedValues:
+ - none
+ - Athena & Glue
+ - Athena, Glue & Redshift
+ - Cognito
+ - DynamoDB
+ - ECR & ECS
+ - EC2
+ - EventBridge
+ - Firehose & Kinesis
+ - Lambda
+ - PerformanceTest
+ - QuickSight
+ - SNS
+ - SSM
+ - StepFunctions
+ - SQS
+ - Xray
+
+ AllowedServiceFour:
+ Description: >
+ Select a service your application needs permissions for (4 of 7)
+ Core services included: CloudFormation, CloudWatch, Logs, CodeBuild,
+ IAM, KMS, S3, Secrets Manager and Textract.
+ Default: "none"
+ Type: "String"
+ AllowedValues:
+ - none
+ - Athena & Glue
+ - Athena, Glue & Redshift
+ - Cognito
+ - DynamoDB
+ - ECR & ECS
+ - EC2
+ - EventBridge
+ - Firehose & Kinesis
+ - Lambda
+ - PerformanceTest
+ - QuickSight
+ - SNS
+ - SSM
+ - StepFunctions
+ - SQS
+ - Xray
+
+ AllowedServiceFive:
+ Description: >
+ Select a service your application needs permissions for (5 of 7)
+ Core services included: CloudFormation, CloudWatch, Logs, CodeBuild,
+ IAM, KMS, S3, Secrets Manager and Textract.
+ Default: "none"
+ Type: "String"
+ AllowedValues:
+ - none
+ - Athena & Glue
+ - Athena, Glue & Redshift
+ - Cognito
+ - DynamoDB
+ - ECR & ECS
+ - EC2
+ - EventBridge
+ - Firehose & Kinesis
+ - Lambda
+ - PerformanceTest
+ - QuickSight
+ - SNS
+ - SSM
+ - StepFunctions
+ - SQS
+ - Xray
+
+ AllowedServiceSix:
+ Description: >
+ Select a service your application needs permissions for (6 of 7)
+ Core services included: CloudFormation, CloudWatch, Logs, CodeBuild,
+ IAM, KMS, S3, Secrets Manager and Textract.
+ Default: "none"
+ Type: "String"
+ AllowedValues:
+ - none
+ - Athena & Glue
+ - Athena, Glue & Redshift
+ - Cognito
+ - DynamoDB
+ - ECR & ECS
+ - EC2
+ - EventBridge
+ - Firehose & Kinesis
+ - Lambda
+ - PerformanceTest
+ - QuickSight
+ - SNS
+ - SSM
+ - StepFunctions
+ - SQS
+ - Xray
+
+ AllowedServiceSeven:
+ Description: >
+ Select a service your application needs permissions for (7 of 7)
+ Core services included: CloudFormation, CloudWatch, Logs, CodeBuild,
+ IAM, KMS, S3, Secrets Manager and Textract.
+ Default: "none"
+ Type: "String"
+ AllowedValues:
+ - none
+ - Athena & Glue
+ - Athena, Glue & Redshift
+ - Cognito
+ - DynamoDB
+ - ECR & ECS
+ - EC2
+ - EventBridge
+ - Firehose & Kinesis
+ - Lambda
+ - PerformanceTest
+ - QuickSight
+ - SNS
+ - SSM
+ - StepFunctions
+ - SQS
+ - Xray
+
+ DynamicResourcesPrefix:
+ Description: >
+ (Optional) Prefix for the name of dynamic CloudFormation stacks and any resources
+ created by them. If not using dynamic resources, leave it as "none".
+ Type: "String"
+ Default: "none"
+
+ VpcStackName:
+ Description: "The name of the VPC to deploy to"
+ Type: "String"
+ Default: "none"
+
+ ContainerSignerKmsKeyArn:
+ Type: "String"
+ Description: >
+ (Optional) This is the ARN of the KMS key that signs container images built by GitHub
+ Actions. This value is returned as the ContainerSignerKmsKeyArn output parameter
+ from the container-signer Cloudformation stack
+ Default: "none"
+ AllowedPattern: "(arn:.*:kms:.*:.*:key/.+)|(none)"
+ ConstraintDescription: must be the ARN of a KMS key or "none"
+
+ CustomKmsKeyArns:
+ Type: "CommaDelimitedList"
+ Default: ""
+ Description: >
+ (Optional) ARNs of custom KMS keys that can be used to access secrets.
+ These must be created separately before deploying the pipeline.
+
+ SigningProfileArn:
+ Type: "String"
+ Description: >
+ (Optional) The ARN of the signing profile to use for signing artifacts.
+ This value is returned as the SigningProfileArn
+ output parameter from the signer CloudFormation stack
+ AllowedPattern: "(arn:.*:signer:.*:.*:/signing-profiles/[^/]+)|(none)"
+ ConstraintDescription: must be a signing profile ARN (not the profile version ARN) or none
+
+ SigningProfileVersionArn:
+ Type: "String"
+ Description: >
+ (Optional) The versioned profile ARN of the signing profile to use for verifying
+ that Lambdas deployed by this pipeline were generated from post-merge
+ build pipeline. This value is returned as the SigningProfileVersionArn
+ output parameter from the signer CloudFormation stack
+ AllowedPattern: "(arn:.*:signer:.*:.*:/signing-profiles/.+/.+)|(none)"
+ ConstraintDescription: must be a signing profile version ARN (not the signing profile ARN) or none
+
+ AdditionalCodeSigningVersionArns:
+ Type: "String"
+ Description: >
+ (Optional) An additional set of CodeSigning profiles that we're allowing to deploy into our lambdas.
+ This could be AWS signatures for their lambda layers, Dynatrace signatures for their layers, or simply
+ other artifacts produced that are signed by a third party signing ARN.
+ Default: "none"
+ AllowedPattern: "(arn:.*:signer:.*:.*:/signing-profiles/.+/.+)|(none)"
+ ConstraintDescription: must be a signing profile version ARN (not the signing profile ARN) or none
+
+ InvokableLambdaAccounts:
+ Type: CommaDelimitedList
+ Description: >
+ (Optional) The AWS account ID where lambda's are deployed that you need to invoke from this account or none.
+ Default: ""
+
+ AccessDynamoDBAccounts:
+ Type: CommaDelimitedList
+ Description: >
+ (Optional) The AWS account ID where DynamoDB Table is.
+ Default: ""
+
+ ArtifactSourceBucketArn:
+ Description: >
+ (Optional) The ARN of the bucket to use as a pipeline source. This would
+ typically be the ArtifactPromotionBucketArn output from an upstream
+ pipeline.
+ Type: "String"
+ Default: "none"
+ AllowedPattern: "(arn:.*:s3:::.+)|(none)"
+ ConstraintDescription: "must be the ARN of an S3 bucket"
+
+ ArtifactSourceBucketEventTriggerRoleArn:
+ Description: >
+ (Optional) The ARN of the IAM role assumed by upstream environment CloudWatch events, notifying
+ any changes to the ArtifactSource bucket. This is one of the components of the event-based trigger.
+ This would typically be the `ArtifactPromotionBucketEventTriggerRoleArn` output from an upstream pipeline.
+ Type: "String"
+ Default: "none"
+ AllowedPattern: "(arn:.*:iam::.*:role/.+)|(none)"
+ ConstraintDescription: "must be an IAM Role ARN or none"
+
+ GitHubRepositoryName:
+ Description: >
+ (Optional) The name of the GitHub repository (within the govuk-one-login
+ organization) which initiates this pipeline. This parameter should only
+ be specified in the account that is called by the GitHub Actions to
+ initiate the deployment. The GitHub Identity Provider stack must have
+ been deployed in the same account.
+ Type: "String"
+ Default: "none"
+ AllowedPattern: "[^/]+"
+ ConstraintDescription: >
+ must be a GitHub repository name in the govuk-one-login organization (without the
+ govuk-one-login/ prefix)
+
+ OneLoginRepositoryName:
+ Description: >
+ (Optional) The name of the GitHub repository (within the govuk-one-login
+ organization) which initiates this pipeline. This parameter should only
+ be specified in the account that is called by the GitHub Actions to
+ initiate the deployment. The GitHub Identity Provider stack must have
+ been deployed in the same account.
+ Type: "String"
+ Default: "none"
+ AllowedPattern: "[^/]+"
+ ConstraintDescription: >
+ must be a GitHub repository name in the govuk-one-login organization (without the
+ govuk-one-login/ prefix)
+
+ RequireTestContainerSignatureValidation:
+ Description: >
+ (Optional)
+ Require test container signature to be validated before passing control to the test entrypoint?
+ Type: "String"
+ Default: "No"
+ AllowedValues:
+ - "Yes"
+ - "No"
+
+ TestImageRepositoryUri:
+ Description: |
+ (Optional)
+ A URI referring to the ECR repository containing a test image to be
+ executed within this pipeline.
+ Type: "String"
+ Default: "none"
+ AllowedPattern: "^(?!\\w+://).*"
+ ConstraintDescription: "must not contain a scheme"
+
+ TestReportFormat:
+ Description: |
+ (Optional)
+ The type of report generated during the test action of the deployment pipeline.
+ See: https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#reports-buildspec-file
+ Type: "String"
+ Default: "JUNITXML"
+ AllowedValues:
+ - CUCUMBERJSON
+ - JUNITXML
+ - NUNITXML
+ - NUNIT3XML
+ - TESTNGXML
+ - VISUALSTUDIOTRX
+ - none
+
+ TestCoverageReportFormat:
+ Description: |
+ (Optional)
+ The type of coverage report generated during the test action of the deployment pipeline.
+ See: https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#reports-buildspec-file
+ Type: "String"
+ Default: "CLOVERXML"
+ AllowedValues:
+ - CLOVERXML
+ - COBERTURAXML
+ - JACOCOXML
+ - SIMPLECOV
+
+ TestComputeType:
+ Description: |
+ (Optional)
+ The build environment used for running the tests
+ Type: "String"
+ Default: "BUILD_GENERAL1_SMALL"
+ AllowedValues:
+ - "BUILD_GENERAL1_SMALL"
+ - "BUILD_GENERAL1_MEDIUM"
+ - "BUILD_GENERAL1_LARGE"
+ - "BUILD_GENERAL1_2XLARGE"
+
+ RunTestContainerInVPC:
+ Description: |
+ (Optional)
+ Requires the testcontainers to run from within the VPC, allowing outbound configuration to be via the EIP,
+ therefore allow-listable in the WAF.
+ Any REGIONAL APIs under test will need to be accessible over the VPC NAT Gateway via public internet.
+ Trying to communicate over a VPC endpoint for Regional API gateways results in Forbbidden 403.
+ Type: "String"
+ AllowedValues:
+ - "True"
+ - "False"
+ Default: "False" # Existing behaviour is to run outside, teams need to flip this parameter to 'true' in order to benefit.
+
+ AWSOrganizationId:
+ Description: "Comma-separated IDs of AWS Organizations where this account and the target pipeline account are members."
+ Type: "CommaDelimitedList"
+ Default: "o-pjzf8d99ys,o-dpp53lco28"
+ AllowedPattern: "^[a-z0-9-]+$"
+ ConstraintDescription: "must be a valid organization ID, made of lowercase letters and numbers"
+
+ RequireManualApproval:
+ Description: >
+ Require a manual approval step before deployment?
+ Type: "String"
+ Default: "No"
+ AllowedValues:
+ - "Yes"
+ - "No"
+
+ IncludePromotion:
+ Description: >
+ Should a promote stage be included in the pipeline?
+ Type: "String"
+ Default: "Yes"
+ AllowedValues:
+ - "Yes"
+ - "No"
+
+ AllowedAccounts:
+ Description: >
+ (Optional) List of accounts that can read the promotion bucket (maximum of 2 accounts, separated by a comma)
+ Type: String
+ Default: ""
+ MaxLength: 25
+ AllowedPattern: "^([0-9]{12,12}(,[0-9]{12,12})?)?$"
+ ConstraintDescription: >
+ (Optional) must consist of a maximum of 2 AWS accounts separated by a comma. Maximum length of 25 characters
+
+ BuildNotificationStackName:
+ Description: "The name of the BuildNotificationStack, which links to the Slack channel where notifications from this pipeline are sent"
+ Type: String
+ Default: "none"
+ AllowedPattern: "[a-zA-Z0-9-]+|none"
+
+ SlackNotificationType:
+ Description: >
+ The events that should be sent to Slack. The options include no
+ notifications, only build failures, or both successful and failed builds.
+ Type: String
+ Default: None
+ AllowedValues:
+ - None
+ - Failures
+ - All
+
+ LogRetentionDays:
+ Description: "The number of days that pipeline logs should be retained"
+ Type: Number
+ Default: 7
+
+ ArtifactWriteTimeLoggingLambdaArn:
+ Description: "The ARN of the Lambda function to log artifact bucket write times to Grafana"
+ Type: String
+ Default: None
+
+ AbortOnCheckovFailure:
+ Description: "Whether to ABORT or CONTINUE the CodeBuild deployment if the pre_build checkov check fails"
+ Type: String
+ Default: CONTINUE
+ AllowedValues:
+ - CONTINUE
+ - ABORT
+
+ AccessLogsCustomBucketNameEnabled:
+ Description: >
+ Controls the S3AccessLogsBucket BucketName.
+ By default (Yes) the S3AccessLogsBucket is named as {AWS::StackName}-{Pseudo random element from stack id}. This allows the bucket name to be found programatically and avoids naming collisions within the account.
+ When set to No the bucket will be named by Cloudformation standard resource naming approach. Please seek guidance from #dev-platform before setting 'No'
+ Type: "String"
+ Default: "Yes"
+ AllowedValues:
+ - "Yes"
+ - "No"
+
+ PipelineEnvironmentNameEnabled:
+ Description: >
+ When set to default "No" the bucket will be named by Cloudformation standard resource naming approach.
+ By setting this to "Yes" the pipeline will be named as {AWS::StackName}-{Environment}-Pipeline-{Pseudo random element from stack id}.
+ This allows to easier identify the environment origin when notifications are sent that includes the pipeline name.
+ Please seek guidance from #dev-platform before setting 'Yes'
+ Type: "String"
+ Default: "No"
+ AllowedValues:
+ - "Yes"
+ - "No"
+
+ ECSCanaryDeployment:
+ Description: >
+ Canary strategy to be used with your ECS application.
+ Must be "None" if not using ecs-canary-deployment stack.
+ Type: String
+ Default: None
+ AllowedValues:
+ - None
+ - CodeDeployDefault.ECSCanary10Percent5Minutes
+ - CodeDeployDefault.ECSCanary10percent15Minutes
+ - CodeDeployDefault.ECSAllAtOnce
+ - ECSCanary50Percent5Minutes
+
+ LambdaCanaryDeployment:
+ Description: >
+ Canary strategy to be used with your Lambda applications
+ Type: String
+ Default: None
+ AllowedValues:
+ - None
+ - AllAtOnce
+ - Canary10Percent5Minutes
+ - Canary10Percent10Minutes
+ - Canary10Percent15Minutes
+ - Canary10Percent30Minutes
+
+ TrafficTestImageRepositoryUri:
+ Description: |
+ (Optional)
+ A URI referring to the ECR repository containing a image to be
+ executed along side the deployment for canary deployment testing.
+ Type: "String"
+ Default: "none"
+ AllowedPattern: "^(?!\\w+://).*"
+ ConstraintDescription: "must not contain a scheme"
+
+Rules:
+ GitHubRepositoryOmittedWhenTriggeredByUpstreamPipeline:
+ RuleCondition: !Not
+ - Fn::Equals: [ !Ref ArtifactSourceBucketArn, "none" ]
+ Assertions:
+ - Assert:
+ Fn::Equals: [ !Ref GitHubRepositoryName, "none" ]
+ AssertDescription: >
+ A GitHub repository cannot also be specified if this pipeline is
+ triggered by an upstream pipeline. It must be "none".
+
+ OneloginRepositoryOmittedWhenTriggeredByUpstreamPipeline:
+ RuleCondition: !Not
+ - Fn::Equals: [ !Ref ArtifactSourceBucketArn, "none" ]
+ Assertions:
+ - Assert:
+ !Equals [ !Ref OneLoginRepositoryName, "none" ]
+ AssertDescription: >
+ A GitHub repository cannot also be specified if this pipeline is
+ triggered by an upstream pipeline. It must be "none".
+
+ UpstreamPipelineOmittedWhenTriggeredByGitHubRepository:
+ RuleCondition: !Not
+ - Fn::And:
+ - Fn::Equals: [ !Ref GitHubRepositoryName, "none" ]
+ - Fn::Equals: [ !Ref OneLoginRepositoryName, "none" ]
+ Assertions:
+ - Assert:
+ Fn::Equals: [ !Ref ArtifactSourceBucketArn, "none" ]
+ AssertDescription: >
+ An upstream pipeline cannot also be specified if this pipeline is
+ triggered by a GitHub repository. It must be "none".
+
+ SigningKeyParameter:
+ RuleCondition: !Not
+ - Fn::Equals: [ !Ref SigningProfileArn, "none" ]
+ Assertions:
+ - Assert: !Not
+ - Fn::Equals: [ !Ref SigningProfileVersionArn, "none" ]
+ AssertDescription: >
+ When SigningProfileArn is supplied then
+ SigningProfileVersionArn must also be supplied.
+
+ SigningKeyVersionParameter:
+ RuleCondition: !Not
+ - Fn::Equals: [ !Ref SigningProfileVersionArn, "none" ]
+ Assertions:
+ - Assert: !Not
+ - Fn::Equals: [ !Ref SigningProfileArn, "none" ]
+ AssertDescription: >
+ When SigningProfileVersionArn is supplied then
+ SigningProfileArn must also be supplied.
+
+ PipelineSourceIsRequired:
+ Assertions:
+ - Assert: !Not
+ - Fn::And:
+ - !Equals [ !Ref GitHubRepositoryName, "none" ]
+ - !Equals [ !Ref OneLoginRepositoryName, "none" ]
+ - !Equals [ !Ref ArtifactSourceBucketArn, "none" ]
+ AssertDescription: The pipeline must have a source.
+
+ BuildNotificationStackNameIsRequiredWhenSlackNotificationTypeIsSelected:
+ RuleCondition: !Not
+ - Fn::Equals: [ !Ref SlackNotificationType, "None" ]
+ Assertions:
+ - Assert:
+ Fn::Not: [ !Equals [ !Ref BuildNotificationStackName, "none" ]]
+ AssertDescription: >
+ BuildNotificationStackName must be provided if a SlackNotificationType is selected.
+
+ AllowedAccountsAreRequiredWhenPromotionIsEnabled:
+ RuleCondition: !Equals [ !Ref IncludePromotion, "Yes" ]
+ Assertions:
+ - Assert: !Not
+ - Fn::Or:
+ - !Equals [ !Ref AllowedAccounts, "" ]
+ - !Equals [ !Ref AllowedAccounts, "," ]
+ AssertDescription: >
+ AllowedAccounts must be provided if IncludePromotion is enabled.
+
+ DevEnvironmentsCantPromote:
+ RuleCondition: !Equals [ !Ref IncludePromotion, "Yes" ]
+ Assertions:
+ - Assert: !Not
+ - Fn::Or:
+ - !Equals [ !Ref Environment, "dev" ]
+ - !Equals [ !Ref Environment, "local" ]
+ - !Equals [ !Ref Environment, "demo" ]
+ AssertDescription: >
+ Only build or staging supports promotion.
+
+ ProgrammaticPermissionsBoundaryParameter:
+ RuleCondition: !Equals [ !Ref ProgrammaticPermissionsBoundary, "False" ]
+ Assertions:
+ - Assert: !And
+ - !Equals [ !Ref AllowedServiceOne, "none" ]
+ - !Equals [ !Ref AllowedServiceTwo, "none" ]
+ - !Equals [ !Ref AllowedServiceThree, "none" ]
+ - !Equals [ !Ref AllowedServiceFour, "none" ]
+ - !Equals [ !Ref AllowedServiceFive, "none" ]
+ - !Equals [ !Ref AllowedServiceSix, "none" ]
+ - !Equals [ !Ref AllowedServiceSeven, "none" ]
+ AssertDescription: >
+ When selecting any of the PermissionBoundary parameters the
+ ProgrammaticPermissionsBoundary parameter needs to be set to "True"
+
+
+Outputs:
+ PipelineName:
+ Description: "The name of the pipeline provisioned"
+ Value: !Ref Pipeline
+
+ ArtifactPromotionBucketArn:
+ Condition: CreatePromoteStage
+ Description: >
+ The ARN of the bucket containing artifacts to be promoted to higher
+ environments.
+ Value: !GetAtt ArtifactPromotionBucket.Arn
+
+ ArtifactPromotionBucketEventTriggerRoleArn:
+ Condition: CreatePromoteStage
+ Description: >
+ The ARN of the IAM role CloudWatch Events assume to notify the higher environments
+ any changes to the promotion bucket. This is one of the components of the event-based trigger.
+ Value: !GetAtt PromotionTriggerCloudWatchEventRole.Arn
+
+ GitHubActionsRoleArn:
+ Condition: CreateGitHubActionsResources
+ Description: >
+ Role ARN for deploying and signing artifacts in GitHub Actions.
+ Restricted for usage only in the repository specified in the
+ `GitHubRepositoryName` and/or `OneLoginRepositoryName` parameter
+ and on branches named `main`.
+ Value: !GetAtt GitHubActionsRole.Arn
+
+ GitHubActionsRoleName:
+ Condition: CreateGitHubActionsResources
+ Description: >
+ Role name for deploying and signing artifacts in GitHub Actions.
+ Restricted for usage only in the repository specified in the
+ `GitHubRepositoryName` and/or `OneLoginRepositoryName` parameter
+ and on branches named `main`.
+ Value: !Ref GitHubActionsRole
+ Export:
+ Name: !Sub "${AWS::StackName}-GitHubActionsRoleName"
+
+ GitHubActionsValidateRoleArn:
+ Condition: CreateGitHubActionsResources
+ Description: >
+ Role ARN for running `sam validate` in GitHub Actions. Restricted for
+ usage only in the repository specified in the `GitHubRepositoryName`
+ and/or `OneLoginRepositoryName` parameter.
+ Value: !GetAtt GitHubActionsValidateRole.Arn
+
+ GitHubArtifactSourceBucketName:
+ Condition: CreateGitHubActionsResources
+ Description: >
+ The name of the bucket into which GitHub should publish artifacts for
+ deployment.
+ Value: !Ref GitHubArtifactSourceBucket
+
+Conditions:
+ SigningProfile:
+ Fn::And:
+ - Fn::Not:
+ - Fn::Equals:
+ - !Ref SigningProfileArn
+ - "none"
+ - Fn::Not:
+ - Fn::Equals:
+ - !Ref SigningProfileVersionArn
+ - "none"
+
+ AccessLogsCustomBucketName:
+ Fn::Equals:
+ - !Ref AccessLogsCustomBucketNameEnabled
+ - "Yes"
+
+ PipelineEnvironmentNameEnabled:
+ Fn::Equals:
+ - !Ref PipelineEnvironmentNameEnabled
+ - "Yes"
+
+ AdditionalCodeSigningProfiles:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref AdditionalCodeSigningVersionArns
+ - "none"
+
+ CreateContainerSignerResources:
+ Fn::Or:
+ - Fn::Equals:
+ - !Ref Environment
+ - "build"
+ - Fn::Equals:
+ - !Ref Environment
+ - "demo"
+ - Fn::Equals:
+ - !Ref Environment
+ - "dev"
+ - Fn::Equals:
+ - !Ref Environment
+ - "local"
+
+ NotProduction:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref Environment
+ - "production"
+
+ IsDevDemoLocal:
+ Fn::Or:
+ - Fn::Equals:
+ - !Ref Environment
+ - "dev"
+ - Fn::Equals:
+ - !Ref Environment
+ - "demo"
+ - Fn::Equals:
+ - !Ref Environment
+ - "local"
+
+ IsContainerSignerProvidedInParameters:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref ContainerSignerKmsKeyArn
+ - "none"
+
+ CreateContainerSignerPolicy:
+ Fn::And:
+ - !Condition CreateContainerSignerResources
+ - !Condition IsContainerSignerProvidedInParameters
+
+ CreateCustomKMSKeyPolicy:
+ Fn::Not:
+ - Fn::Equals:
+ - !Join ['', !Ref CustomKmsKeyArns]
+ - ""
+
+ CreateAlphaGovRepoResources:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref GitHubRepositoryName
+ - "none"
+
+ CreateOneLoginRepoResources:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref OneLoginRepositoryName
+ - "none"
+
+ CreateGitHubActionsResources:
+ Fn::Or: [Condition: CreateAlphaGovRepoResources, Condition: CreateOneLoginRepoResources]
+
+ CreateAlphaGovActionDevLocal:
+ Fn::And:
+ - Condition: CreateAlphaGovRepoResources
+ - Condition: IsDevDemoLocal
+
+ CreateAlphaGovActionBuild:
+ Fn::And:
+ - Condition: CreateAlphaGovRepoResources
+ - Fn::Not:
+ - Condition: IsDevDemoLocal
+
+ CreateOneLoginDevLocal:
+ Fn::And:
+ - Condition: CreateOneLoginRepoResources
+ - Condition: IsDevDemoLocal
+
+ CreateOneLoginBuild:
+ Fn::And:
+ - Condition: CreateOneLoginRepoResources
+ - Fn::Not:
+ - Condition: IsDevDemoLocal
+
+ CreateDeploymentTriggerEventBusPolicy:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref ArtifactSourceBucketEventTriggerRoleArn
+ - "none"
+
+ CreateManualApprovalStage:
+ Fn::Equals:
+ - !Ref RequireManualApproval
+ - "Yes"
+
+ CreateTrafficTest:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref TrafficTestImageRepositoryUri
+ - "none"
+
+ CreateTestAction:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref TestImageRepositoryUri
+ - "none"
+
+ CreateTestContainerSignatureValidateStage:
+ Fn::And:
+ - !Condition CreateTestAction
+ - Fn::Equals:
+ - !Ref RequireTestContainerSignatureValidation
+ - "Yes"
+ - !Condition IsContainerSignerProvidedInParameters
+
+ CreateVPCConfigurationForTestContainer:
+ Fn::And:
+ - !Condition CreateTestAction
+ - !Condition NotProduction
+ - Fn::Equals:
+ - !Ref RunTestContainerInVPC
+ - "True"
+
+ CreatePromoteStage:
+ Fn::Equals:
+ - !Ref IncludePromotion
+ - "Yes"
+
+ EnablePipelinePolling:
+ Fn::And:
+ - Fn::Not:
+ - Fn::Equals:
+ - !Ref ArtifactSourceBucketArn
+ - "none"
+ - Fn::Equals:
+ - !Ref ArtifactSourceBucketEventTriggerRoleArn
+ - "none"
+
+ EmitBuildNotifications:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref SlackNotificationType
+ - "None"
+
+ InvokableLambda:
+ Fn::Not:
+ - Fn::Equals:
+ - !Join ['', !Ref InvokableLambdaAccounts]
+ - ""
+
+ AccessDynamoTable:
+ Fn::Not:
+ - Fn::Equals:
+ - !Join ['', !Ref AccessDynamoDBAccounts]
+ - ""
+
+ EmitGitHubArtifactWriteLogs:
+ Fn::And:
+ - Fn::Not:
+ - Fn::Equals:
+ - !Ref ArtifactWriteTimeLoggingLambdaArn
+ - "None"
+ - !Condition CreateGitHubActionsResources
+
+ EmitPromotionArtifactWriteLogs:
+ Fn::And:
+ - Fn::Not:
+ - Fn::Equals:
+ - !Ref ArtifactWriteTimeLoggingLambdaArn
+ - "None"
+ - !Condition CreatePromoteStage
+
+ UseTwoAllowedAccounts:
+ Fn::Not:
+ - Fn::Equals:
+ - Fn::Select:
+ - 1
+ - Fn::Split:
+ - ","
+ - Fn::Sub:
+ - "${AccountIds},,,"
+ - AccountIds: !Ref AllowedAccounts
+ - ""
+
+ UseTruncatedPipelineStackName:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref TruncatedPipelineStackName
+ - "none"
+
+ UseProgrammaticPermissionsBoundary: !Equals
+ - !Ref ProgrammaticPermissionsBoundary
+ - "True"
+
+ IncludeAthenaAndGlue: !Or
+ - !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "Athena & Glue"
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "Athena, Glue & Redshift"
+ - !Or
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "Athena & Glue"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "Athena, Glue & Redshift"
+ - !Or
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "Athena & Glue"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "Athena, Glue & Redshift"
+ - !Or
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "Athena & Glue"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "Athena, Glue & Redshift"
+ - !Or
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "Athena & Glue"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "Athena, Glue & Redshift"
+ - !Or
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "Athena & Glue"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "Athena, Glue & Redshift"
+ - !Or
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "Athena & Glue"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "Athena, Glue & Redshift"
+
+ IncludeAthenaGlueRedshift: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "Athena, Glue & Redshift"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "Athena, Glue & Redshift"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "Athena, Glue & Redshift"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "Athena, Glue & Redshift"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "Athena, Glue & Redshift"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "Athena, Glue & Redshift"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "Athena, Glue & Redshift"
+
+ IncludeCognito: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "Cognito"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "Cognito"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "Cognito"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "Cognito"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "Cognito"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "Cognito"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "Cognito"
+
+ IncludeDynamoDB: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "DynamoDB"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "DynamoDB"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "DynamoDB"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "DynamoDB"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "DynamoDB"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "DynamoDB"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "DynamoDB"
+
+ IncludeECRAndECS: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "ECR & ECS"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "ECR & ECS"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "ECR & ECS"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "ECR & ECS"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "ECR & ECS"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "ECR & ECS"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "ECR & ECS"
+
+ IncludeEC2: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "EC2"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "EC2"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "EC2"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "EC2"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "EC2"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "EC2"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "EC2"
+
+ IncludeEventBridge: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "EventBridge"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "EventBridge"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "EventBridge"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "EventBridge"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "EventBridge"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "EventBridge"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "EventBridge"
+
+ IncludeFirehoseAndKinesis: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "Firehose & Kinesis"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "Firehose & Kinesis"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "Firehose & Kinesis"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "Firehose & Kinesis"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "Firehose & Kinesis"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "Firehose & Kinesis"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "Firehose & Kinesis"
+
+ IncludeLambda: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "Lambda"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "Lambda"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "Lambda"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "Lambda"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "Lambda"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "Lambda"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "Lambda"
+ IncludePerformanceTest: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "PerformanceTest"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "PerformanceTest"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "PerformanceTest"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "PerformanceTest"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "PerformanceTest"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "PerformanceTest"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "PerformanceTest"
+
+ IncludeQuickSight: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "QuickSight"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "QuickSight"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "QuickSight"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "QuickSight"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "QuickSight"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "QuickSight"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "QuickSight"
+
+ IncludeSNS: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "SNS"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "SNS"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "SNS"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "SNS"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "SNS"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "SNS"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "SNS"
+
+ IncludeSSM: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "SSM"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "SSM"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "SSM"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "SSM"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "SSM"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "SSM"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "SSM"
+
+ IncludeStepFunctions: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "StepFunctions"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "StepFunctions"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "StepFunctions"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "StepFunctions"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "StepFunctions"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "StepFunctions"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "StepFunctions"
+
+ IncludeSQS: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "SQS"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "SQS"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "SQS"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "SQS"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "SQS"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "SQS"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "SQS"
+
+ IncludeXray: !Or
+ - !Equals
+ - !Ref AllowedServiceOne
+ - "Xray"
+ - !Equals
+ - !Ref AllowedServiceTwo
+ - "Xray"
+ - !Equals
+ - !Ref AllowedServiceThree
+ - "Xray"
+ - !Equals
+ - !Ref AllowedServiceFour
+ - "Xray"
+ - !Equals
+ - !Ref AllowedServiceFive
+ - "Xray"
+ - !Equals
+ - !Ref AllowedServiceSix
+ - "Xray"
+ - !Equals
+ - !Ref AllowedServiceSeven
+ - "Xray"
+
+ IncludeDynamicResources:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref DynamicResourcesPrefix
+ - "none"
+
+ IncludeDynamicSQS:
+ Fn::And:
+ - Condition: IncludeDynamicResources
+ - Condition: IncludeSQS
+
+ DeployECSCanaryStack:
+ Fn::Not:
+ - Fn::Equals:
+ - !Ref ECSCanaryDeployment
+ - None
+
+Mappings:
+ BuildNotifications:
+ "All":
+ EventTypeIds:
+ - codepipeline-pipeline-pipeline-execution-failed
+ - codepipeline-pipeline-pipeline-execution-succeeded
+ "Failures":
+ EventTypeIds:
+ - codepipeline-pipeline-pipeline-execution-failed
+ "None":
+ EventTypeIds: []
+ # See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html
+ # ElasticLoadBalancerAccountIds:
+ # eu-west-2:
+ # AccountId: 652711504416
+
+Resources:
+ LogsKmsKey:
+ Type: AWS::KMS::Key
+ Properties:
+ EnableKeyRotation: true
+ KeyPolicy:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ AWS: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:root"
+ Action:
+ - "kms:*"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Principal:
+ Service: !Sub "logs.${AWS::Region}.amazonaws.com"
+ Action:
+ - "kms:Encrypt*"
+ - "kms:Decrypt*"
+ - "kms:ReEncrypt*"
+ - "kms:GenerateDataKey*"
+ - "kms:Describe*"
+ Resource:
+ - "*"
+ Condition:
+ ArnLike:
+ "kms:EncryptionContext:aws:logs:arn": !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "LogsKmsKey"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # S3 Access Logs Bucket
+ #
+
+ S3AccessLogsBucket:
+ Type: AWS::S3::Bucket
+ # checkov:skip=CKV_AWS_18:This is the access logs bucket. It should not log itself.
+ Properties:
+ LifecycleConfiguration:
+ Rules:
+ - Id: artifactBucketExpiry
+ Status: Enabled
+ ExpirationInDays: 30
+ BucketName: !If
+ - AccessLogsCustomBucketName
+ - !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "s3logs"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - '-'
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - /
+ - Ref: AWS::StackId
+ - !Ref AWS::NoValue
+ VersioningConfiguration:
+ Status: "Enabled"
+ PublicAccessBlockConfiguration:
+ BlockPublicAcls: true
+ BlockPublicPolicy: true
+ IgnorePublicAcls: true
+ RestrictPublicBuckets: true
+ BucketEncryption:
+ ServerSideEncryptionConfiguration:
+ - ServerSideEncryptionByDefault:
+ SSEAlgorithm: AES256
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "s3logs"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+ - Key: CheckovRulesToSkip
+ Value: CKV_AWS_18
+
+
+ S3AccessLogsBucketPolicy:
+ Type: AWS::S3::BucketPolicy
+ Properties:
+ Bucket: !Ref S3AccessLogsBucket
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "EnableS3Logging"
+ Effect: "Allow"
+ Resource:
+ - !Sub "${S3AccessLogsBucket.Arn}/*"
+ Principal:
+ Service: "logging.s3.amazonaws.com"
+ Action:
+ - "s3:PutObject"
+ Condition:
+ StringEquals:
+ "aws:SourceAccount": !Sub "${AWS::AccountId}"
+ Bool:
+ "aws:SecureTransport": true
+
+ #
+ # GitHub Artifact Source
+ #
+
+ GitHubArtifactSourceBucket:
+ Condition: CreateGitHubActionsResources
+ Type: AWS::S3::Bucket
+ Properties:
+ LifecycleConfiguration:
+ Rules:
+ - Id: artifactBucketExpiry
+ Status: Enabled
+ ExpirationInDays: 180
+ VersioningConfiguration:
+ Status: "Enabled"
+ PublicAccessBlockConfiguration:
+ BlockPublicAcls: true
+ BlockPublicPolicy: true
+ IgnorePublicAcls: true
+ RestrictPublicBuckets: true
+ LoggingConfiguration:
+ DestinationBucketName: !Ref S3AccessLogsBucket
+ LogFilePrefix: "pipeline/github/"
+ BucketEncryption:
+ ServerSideEncryptionConfiguration:
+ - ServerSideEncryptionByDefault:
+ SSEAlgorithm: "AES256"
+ NotificationConfiguration:
+ !If
+ - EmitGitHubArtifactWriteLogs
+ - LambdaConfigurations:
+ - Event: s3:ObjectCreated:Put
+ Function: !Ref ArtifactWriteTimeLoggingLambdaArn
+ - !Ref AWS::NoValue
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "githubartifactsourcebucket"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+ - Key: "ApplicationName"
+ Value: !Ref SAMStackName
+ - Key: "Environment"
+ Value: !Ref Environment
+
+ GitHubArtifactSourceBucketPolicy:
+ Condition: CreateGitHubActionsResources
+ Type: AWS::S3::BucketPolicy
+ Properties:
+ Bucket: !Ref GitHubArtifactSourceBucket
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Resource:
+ - !GetAtt GitHubArtifactSourceBucket.Arn
+ - !Sub "${GitHubArtifactSourceBucket.Arn}/*"
+ Principal:
+ AWS: !GetAtt GitHubActionsRole.Arn
+ Action:
+ - "s3:PutObject"
+ - "s3:PutObjectAcl"
+ - "s3:ListBucket"
+ Condition:
+ Bool:
+ "aws:SecureTransport": true
+
+ #
+ # Artifact Promotion
+ #
+
+ ArtifactPromotionBucket:
+ Condition: CreatePromoteStage
+ Type: AWS::S3::Bucket
+ Properties:
+ LifecycleConfiguration:
+ Rules:
+ - Id: artifactBucketExpiry
+ Status: Enabled
+ ExpirationInDays: 180
+ VersioningConfiguration:
+ Status: "Enabled"
+ PublicAccessBlockConfiguration:
+ BlockPublicAcls: true
+ BlockPublicPolicy: true
+ IgnorePublicAcls: true
+ RestrictPublicBuckets: true
+ LoggingConfiguration:
+ DestinationBucketName: !Ref S3AccessLogsBucket
+ LogFilePrefix: "pipeline/promotion/"
+ BucketEncryption:
+ ServerSideEncryptionConfiguration:
+ - ServerSideEncryptionByDefault:
+ SSEAlgorithm: "AES256"
+ NotificationConfiguration:
+ !If
+ - EmitPromotionArtifactWriteLogs
+ - LambdaConfigurations:
+ - Event: s3:ObjectCreated:Put
+ Function: !Ref ArtifactWriteTimeLoggingLambdaArn
+ - !Ref AWS::NoValue
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "artifactpromotionbucket"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+ - Key: "ApplicationName"
+ Value: !Ref SAMStackName
+ - Key: "Environment"
+ Value: !Ref Environment
+
+ ArtifactPromotionBucketPolicy:
+ Condition: CreatePromoteStage
+ Type: AWS::S3::BucketPolicy
+ Properties:
+ Bucket: !Ref ArtifactPromotionBucket
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Resource:
+ - !GetAtt ArtifactPromotionBucket.Arn
+ - !Sub "${ArtifactPromotionBucket.Arn}/*"
+ Principal:
+ AWS: !Split [",", !Ref AllowedAccounts]
+ Action:
+ - "s3:GetBucketVersioning"
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetObjectTagging"
+ - "s3:ListBucket"
+ Condition:
+ StringEquals:
+ "aws:PrincipalOrgID": !Ref AWSOrganizationId
+ Bool:
+ "aws:SecureTransport": true
+
+ #
+ # Deny resources creation outside UK region
+ #
+
+ LockToRegionPolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "LockToRegionPolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Deny"
+ Resource:
+ - "*"
+ NotAction:
+ - "a4b:*"
+ - "acm:*"
+ - "aws-marketplace-management:*"
+ - "aws-marketplace:*"
+ - "budgets:*"
+ - "ce:*"
+ - "chime:*"
+ - "cloudfront:*"
+ - "cognito-idp:*"
+ - "config:*"
+ - "cur:*"
+ - "directconnect:*"
+ - "ec2:Describe*"
+ - "fms:*"
+ - "globalaccelerator:*"
+ - "health:*"
+ - "iam:*"
+ - "importexport:*"
+ - "kms:*"
+ - "mobileanalytics:*"
+ - "networkmanager:*"
+ - "organizations:*"
+ - "pricing:*"
+ - "pipes:*"
+ - "route53:*"
+ - "route53domains:*"
+ - "s3:GetAccountPublic*"
+ - "s3:ListAllMyBuckets"
+ - "s3:PutAccountPublic*"
+ - "ses:*"
+ - "shield:*"
+ - "sts:*"
+ - "support:*"
+ - "synthetics:*"
+ - "trustedadvisor:*"
+ - "waf-regional:*"
+ - "waf:*"
+ - "wafv2:*"
+ - "wellarchitected:*"
+ Condition:
+ StringNotEquals:
+ "aws:RequestedRegion": [
+ "eu-west-2"
+ ]
+
+ #
+ # GitHub Actions Integration
+ #
+
+ ContainerSignerKmsKey:
+ Type: AWS::KMS::Key
+ Condition: CreateContainerSignerResources
+ #checkov:skip=CKV_AWS_7:Automatic key rotation can only be enabled on symmetric keys
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
+ Properties:
+ Description: Asymmetric key used to sign and validate ECR container artifacts
+ Enabled: true
+ KeySpec: RSA_4096
+ KeyUsage: SIGN_VERIFY
+ KeyPolicy:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ AWS: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:root"
+ Action:
+ - "kms:*"
+ Resource:
+ - "*"
+ - !If
+ - CreatePromoteStage
+ - Effect: "Allow"
+ Principal:
+ AWS: !Split [",", !Ref AllowedAccounts]
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Verify"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Principal:
+ Federated: !ImportValue GitHubIdentityProviderArn
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Sign"
+ Resource:
+ - "*"
+ Condition:
+ StringEquals:
+ "kms:ViaService": !Sub "ecr.${AWS::Region}.amazonaws.com"
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "ContainerSignerKmsKey"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+ - Key: CheckovRulesToSkip
+ Value: CKV_AWS_7
+
+ GitHubActionsPolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Condition: CreateGitHubActionsResources
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "GitHubActionsPolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "AccessToGitHubArtifactSourceBucket"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:PutObject"
+ - "s3:GetObjectTagging"
+ - "s3:GetObjectVersion"
+ - "s3:ListBucket"
+ Resource:
+ - !GetAtt GitHubArtifactSourceBucket.Arn
+ - !Sub "${GitHubArtifactSourceBucket.Arn}/*"
+ - Sid: "SAMValidate"
+ Effect: "Allow"
+ Action:
+ - "iam:ListPolicies"
+ Resource: "*"
+ - Sid: "AccessToECR"
+ Effect: "Allow"
+ Action:
+ - "ecr:GetAuthorizationToken"
+ Resource: "*"
+ - !If
+ - SigningProfile
+ - Sid: "ArtifactSigningWithProfile"
+ Effect: "Allow"
+ Action:
+ - "signer:GetSigningProfile"
+ - "signer:StartSigningJob"
+ Resource: !Ref SigningProfileArn
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "ArtifactSigningStatusQueries"
+ Effect: "Allow"
+ Action:
+ - "signer:ListSigningJobs"
+ - "signer:ListSigningProfiles"
+ - "signer:DescribeSigningJob"
+ Resource: "*"
+ - !Ref AWS::NoValue
+ - !If
+ - CreateContainerSignerResources
+ - Sid: "DefaultContainerSigning"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Sign"
+ Resource:
+ - !GetAtt ContainerSignerKmsKey.Arn
+ - !Ref AWS::NoValue
+ - !If
+ - CreateContainerSignerPolicy
+ - Sid: "ContainerSigning"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Sign"
+ Resource:
+ - !Ref ContainerSignerKmsKeyArn
+ - !Ref AWS::NoValue
+
+
+ GitHubActionsRole:
+ Type: AWS::IAM::Role
+ Condition: CreateGitHubActionsResources
+ # checkov:skip=GDS_AWS_1:Don't run GDS_AWS_1
+ Properties:
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Fn::If:
+ - CreateAlphaGovActionDevLocal
+ - Effect: "Allow"
+ Action: "sts:AssumeRoleWithWebIdentity"
+ Principal:
+ Federated: !ImportValue GitHubIdentityProviderArn
+ Condition:
+ StringLike:
+ "token.actions.githubusercontent.com:sub":
+ - !Sub "repo:alphagov/${GitHubRepositoryName}*ref:refs/heads/*"
+ - !Sub "repo:alphagov/${GitHubRepositoryName}:environment:*"
+ - !Ref AWS::NoValue
+ - Fn::If:
+ - CreateAlphaGovActionBuild
+ - Effect: "Allow"
+ Action: "sts:AssumeRoleWithWebIdentity"
+ Principal:
+ Federated: !ImportValue GitHubIdentityProviderArn
+ Condition:
+ StringLike:
+ "token.actions.githubusercontent.com:sub":
+ - !Sub "repo:alphagov/${GitHubRepositoryName}*ref:refs/heads/main"
+ - !Ref AWS::NoValue
+ - Fn::If:
+ - CreateOneLoginDevLocal
+ - Effect: "Allow"
+ Action: "sts:AssumeRoleWithWebIdentity"
+ Principal:
+ Federated: !ImportValue GitHubIdentityProviderArn
+ Condition:
+ StringLike:
+ "token.actions.githubusercontent.com:sub":
+ - !Sub "repo:govuk-one-login/${OneLoginRepositoryName}*ref:refs/heads/*"
+ - !Sub "repo:govuk-one-login/${OneLoginRepositoryName}:environment:*"
+ - !Ref AWS::NoValue
+ - Fn::If:
+ - CreateOneLoginBuild
+ - Effect: "Allow"
+ Action: "sts:AssumeRoleWithWebIdentity"
+ Principal:
+ Federated: !ImportValue GitHubIdentityProviderArn
+ Condition:
+ StringLike:
+ "token.actions.githubusercontent.com:sub":
+ - !Sub "repo:govuk-one-login/${OneLoginRepositoryName}*ref:refs/heads/main"
+ - !Ref AWS::NoValue
+ ManagedPolicyArns:
+ - !Ref GitHubActionsPolicy
+ - !Ref LockToRegionPolicy
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "GitHubActionsRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ GitHubActionsValidatePolicy:
+ Condition: CreateGitHubActionsResources
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "GitHubActionsValidatePolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "SAMValidate"
+ Effect: "Allow"
+ Action:
+ - "iam:ListPolicies"
+ Resource: "*"
+
+ GitHubActionsValidateRole:
+ Type: AWS::IAM::Role
+ Condition: CreateGitHubActionsResources
+ Properties:
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - !If
+ - CreateAlphaGovRepoResources
+ - Effect: "Allow"
+ Action: "sts:AssumeRoleWithWebIdentity"
+ Principal:
+ Federated: !ImportValue GitHubIdentityProviderArn
+ Condition:
+ StringLike:
+ "token.actions.githubusercontent.com:sub": !Sub "repo:alphagov/${GitHubRepositoryName}:*"
+ - !Ref AWS::NoValue
+ - !If
+ - CreateOneLoginRepoResources
+ - Effect: "Allow"
+ Action: "sts:AssumeRoleWithWebIdentity"
+ Principal:
+ Federated: !ImportValue GitHubIdentityProviderArn
+ Condition:
+ StringLike:
+ "token.actions.githubusercontent.com:sub": !Sub "repo:govuk-one-login/${OneLoginRepositoryName}:*"
+ - !Ref AWS::NoValue
+ ManagedPolicyArns:
+ - !Ref GitHubActionsValidatePolicy
+ - !Ref LockToRegionPolicy
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "GitHubActionsValidateRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # Shared Code Build Policy
+ #
+
+ CodeBuildPolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "CodeBuildPolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*"
+ Action:
+ - "logs:CreateLogGroup"
+ - "logs:CreateLogStream"
+ - "logs:PutLogEvents"
+ Effect: "Allow"
+ - Resource:
+ - !GetAtt PipelineBucket.Arn
+ - !Sub "${PipelineBucket.Arn}/*"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetBucketVersioning"
+ - "s3:PutObjectAcl"
+ - "s3:PutObject"
+ Effect: "Allow"
+ - Resource:
+ - !Sub "arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/*"
+ Action:
+ - "codebuild:CreateReportGroup"
+ - "codebuild:CreateReport"
+ - "codebuild:UpdateReport"
+ - "codebuild:BatchPutTestCases"
+ Effect: "Allow"
+ - Resource:
+ - !Sub "arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/*-${SAMStackName}"
+ Action:
+ - "codebuild:CreateProject"
+ - "codebuild:DeleteProject"
+ - "codebuild:UpdateProject"
+ Effect: "Allow"
+
+ #
+ # Deploy (CodeBuild)
+ #
+
+ CodeSigningConfig:
+ Condition: SigningProfile
+ Type: AWS::Lambda::CodeSigningConfig
+ Properties:
+ Description: !Sub "Code Signing Config for ${AWS::StackName}"
+ AllowedPublishers:
+ SigningProfileVersionArns: !If
+ - AdditionalCodeSigningProfiles
+ - !Split [",", !Sub "${SigningProfileVersionArn},${AdditionalCodeSigningVersionArns}"]
+ - !Split [",", !Ref SigningProfileVersionArn]
+ CodeSigningPolicies:
+ UntrustedArtifactOnDeployment: "Enforce"
+
+ AppPermissionsBoundary:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ # checkov:skip=CKV_AWS_111:states:Send* are write actions but do not take a resource
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "AppPermissionsBoundary"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - "logs:CreateLog*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
+ - Effect: "Allow"
+ Action:
+ - "logs:PutLogEvents"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:log-stream:*"
+ - Effect: "Allow"
+ Action:
+ - "logs:*LogDelivery"
+ - "logs:ListL*"
+ - "logs:*LogEvents"
+ - "logs:PutRes*"
+ - "logs:DescribeR*"
+ - "logs:DescribeLog*"
+ - "sns:ListTopics"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "cloudwatch:PutMetricData"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "sns:Publish"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*"
+ Condition:
+ StringEquals:
+ "aws:PrincipalOrgID": !Ref AWSOrganizationId
+ - Effect: "Allow"
+ Action:
+ - "sqs:SendMessage*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:*"
+ - Effect: "Allow"
+ Action:
+ - "sqs:Ch*"
+ - "sqs:DeleteM*"
+ - "sqs:GetQueue*"
+ - "sqs:Rec*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:*:*"
+ - Effect: "Allow"
+ Action:
+ - "kinesis:DescribeLimits"
+ - "kinesis:ListStreams"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "kinesis:Desc*"
+ - "kinesis:Get*"
+ - "kinesis:PutRecord*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:kinesis:${AWS::Region}:${AWS::AccountId}:stream/*"
+ - Effect: "Allow"
+ Action:
+ - "firehose:PutRecord*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:firehose:${AWS::Region}:${AWS::AccountId}:deliverystream/*"
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:ListStreams"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:DescribeStream"
+ - "dynamodb:GetRecords"
+ - "dynamodb:GetShardIterator"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*/stream/*"
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:GetItem"
+ - "dynamodb:Scan"
+ - "dynamodb:Query"
+ - "dynamodb:Batch*"
+ - "dynamodb:Describe*"
+ - "dynamodb:DeleteItem"
+ - "dynamodb:PutItem"
+ - "dynamodb:UpdateItem"
+ - "dynamodb:PartiQ*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*"
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*/index/*"
+ - Effect: "Allow"
+ Action:
+ - "s3:ListBucket"
+ - "s3:ListBucketVersions"
+ - "s3:ListAllMyBuckets"
+ - "s3:GetBucketLocation"
+ - "s3:GetObjec*"
+ - "s3:GetLifecycleConfiguration"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::*"
+ - !Sub "arn:${AWS::Partition}:s3:::*/*"
+ - Effect: "Allow"
+ Action:
+ - "s3:DeleteObject*"
+ - "s3:PutObjec*"
+ - "s3:PutLifecycle*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::*"
+ - !Sub "arn:${AWS::Partition}:s3:::*/*"
+ Condition:
+ StringEquals:
+ "s3:ResourceAccount":
+ - !Sub "${AWS::AccountId}"
+ - Effect: "Allow"
+ Action:
+ - "events:PutEvents"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:event-bus/*"
+ - Effect: "Allow"
+ Action:
+ - "ssm:DescribeParameters"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "ssm:GetParameter*"
+ - "ssm:PutParameter"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/*"
+ - Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:*crypt*"
+ - "kms:GenerateDataKey*"
+ - "kms:GetPublicKey"
+ - "kms:Sign"
+ - "kms:Verify"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:*:key/*"
+ - Effect: "Allow"
+ Action:
+ - "kms:GenerateRandom"
+ - "kms:ListKeys"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "ecr:BatchCheck*"
+ - "ecr:BatchGetIm*"
+ - "ecr:GetD*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecr:${AWS::Region}:*:repository/*"
+ - Effect: "Allow"
+ Action:
+ - "ecr:GetAuth*"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "ecs:RunTask"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:task-definition/*"
+ - Effect: "Allow"
+ Action:
+ - "iam:PassRole"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/*"
+ - !If
+ - SigningProfile
+ - Effect: "Allow"
+ Action:
+ - "lambda:GetAlias"
+ - "lambda:GetProvisionedConcurrencyConfig"
+ - "lambda:UpdateAlias"
+ - "lambda:InvokeFunction"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
+ - !Ref AWS::NoValue
+ - !If
+ - InvokableLambda
+ - Effect: "Allow"
+ Action:
+ - "lambda:InvokeFunction"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:*:function:*"
+ Condition:
+ ForAnyValue:StringEquals:
+ "aws:ResourceAccount": !Ref InvokableLambdaAccounts
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "codedeploy:PutLifecycleEventHookExecutionStatus"
+ Resource:
+ - !Sub 'arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:*'
+ - Effect: "Allow"
+ Action:
+ - "cloudwatch:DescribeAlarms"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "xray:PutTraceSegments"
+ - "xray:PutTelemetryRecords"
+ - "xray:GetSampling*"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "ec2:Describe*"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "ec2:*NetworkInterface"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:*/*"
+ - Effect: "Allow"
+ Action:
+ - "states:Start*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:stateMachine:*"
+ - Effect: "Allow"
+ Action:
+ - "states:DescribeExecution"
+ - "states:StopExecution"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:execution:*:*"
+ - Effect: "Allow"
+ Action:
+ - "states:GetActivityTask"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:activity:*"
+ - Effect: "Allow"
+ Action:
+ - "states:SendTask*"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "cognito-idp:Describe*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/*"
+ - Effect: "Allow"
+ Action:
+ - "glue:GetSecurityConfiguration"
+ Resource: "*"
+ - Effect: "Allow"
+ Action:
+ - "glue:GetDatabase"
+ - "glue:GetTable"
+ - "glue:CreateTa*"
+ - "glue:CreateDatab*"
+ - "glue:BatchGetP*"
+ - "glue:BatchC*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:glue:${AWS::Region}:${AWS::AccountId}:*"
+ - Effect: "Allow"
+ Action:
+ - "athena:StartQueryExecution"
+ - "athena:GetQuery*"
+ - "athena:*agResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:athena:${AWS::Region}:${AWS::AccountId}:workgroup/*"
+ - Effect: "Allow"
+ Action:
+ - "s3:CreateJob"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "cloudformation:ListStackResources"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/*/*"
+ - Effect: "Allow"
+ Action:
+ - "codebuild:*Projects"
+ - "codebuild:BatchGetBuild*"
+ - "codebuild:ListBuild*"
+ - "codebuild:StartBuild*"
+ - "codebuild:StopBuild*"
+ Resource:
+ - "*"
+ Condition:
+ BoolIfExists:
+ aws:MultiFactorAuthPresent: true
+ - Effect: Allow
+ Action:
+ - "textract:*"
+ Resource:
+ - "*"
+ Condition:
+ StringEquals:
+ "aws:PrincipalOrgID": !Ref AWSOrganizationId
+ - Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecrets" # pragma: allowlist secret
+ Resource:
+ - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*" # pragma: allowlist secret
+ - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:216552277552:secret:*" # pragma: allowlist secret
+
+ AppProgrammaticPermissionsBoundary:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ # checkov:skip=CKV_AWS_111:states:Send* are write actions but do not take a resource
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "AppProgrammaticPermissionsBoundary"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - !If
+ - IncludeAthenaAndGlue
+ - Effect: "Allow"
+ Action:
+ - "athena:StartQueryExecution"
+ - "athena:GetQueryExecution"
+ - "athena:GetQueryResults"
+ - "athena:*TagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:athena:${AWS::Region}:${AWS::AccountId}:workgroup/*"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "cloudformation:ListStackResources"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/*/*"
+ - !If
+ - IncludeDynamicResources
+ - Effect: Allow
+ Action:
+ - cloudformation:CreateStack
+ - cloudformation:DeleteStack
+ - cloudformation:UpdateStack
+ - cloudformation:CreateChangeSet
+ Resource: !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${DynamicResourcesPrefix}-*"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "cloudwatch:DescribeAlarms"
+ - "cloudwatch:DeleteAlarms"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "cloudwatch:PutMetricData"
+ - "cloudwatch:PutMetricAlarm"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "codebuild:*Projects"
+ - "codebuild:BatchGetBuild*"
+ - "codebuild:ListBuild*"
+ - "codebuild:StartBuild*"
+ - "codebuild:StopBuild*"
+ Resource:
+ - "*"
+ Condition:
+ BoolIfExists:
+ aws:MultiFactorAuthPresent: true
+ - Effect: "Allow"
+ Action:
+ - "codedeploy:PutLifecycleEventHookExecutionStatus"
+ Resource:
+ - !Sub 'arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:*'
+ - !If
+ - DeployECSCanaryStack
+ - Effect: "Allow"
+ Action:
+ - "cloudformation:DescribeStacks"
+ - "codedeploy:CreateDeploymentGroup"
+ - "codedeploy:UpdateDeploymentGroup"
+ - "codedeploy:DeleteDeploymentGroup"
+ - "codedeploy:GetDeploymentGroup"
+ - "codedeploy:GetDeployment"
+ - "codedeploy:CreateDeployment"
+ - "codedeploy:GetDeploymentConfig"
+ - "codedeploy:RegisterApplicationRevision"
+ - "codedeploy:GetApplicationRevision"
+ - "ecs:DescribeServices"
+ - "ecs:UpdateServicePrimaryTaskSet"
+ - "ecs:DeleteTaskSet"
+ - "elasticloadbalancing:ModifyListener"
+ - "elasticloadbalancing:ModifyRule"
+ - "events:PutRule"
+ - "events:DeleteRule"
+ - "events:PutTargets"
+ - "events:RemoveTargets"
+ - "lambda:AddPermission"
+ - "lambda:RemovePermission"
+ Resource:
+ - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/*'
+ - !Sub 'arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:*'
+ - !Sub "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:*"
+ - !Sub "arn:${AWS::Partition}:elasticloadbalancing:${AWS::Region}:${AWS::AccountId}:*"
+ - !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/*"
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
+ - !Ref AWS::NoValue
+ - !If
+ - DeployECSCanaryStack
+ - Effect: "Allow"
+ Action:
+ - "ecs:CreateTaskSet"
+ - "elasticloadbalancing:DescribeTargetGroups"
+ - "elasticloadbalancing:DescribeListeners"
+ - "elasticloadbalancing:DescribeRules"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeCognito
+ - Effect: "Allow"
+ Action:
+ - "cognito-idp:DescribeUserPoolClient"
+ - "cognito-idp:DeleteUserPoolClient"
+ - "cognito-idp:Admin*User"
+ - "cognito-idp:AdminInitiateAuth"
+ - "cognito-idp:AdminRespondToAuthChallenge"
+ - "cognito-idp:AdminSetUserMFAPreference"
+ - "cognito-idp:AdminUpdateUserAttributes"
+ - "cognito-idp:ChangePassword"
+ - "cognito-idp:GetLogDeliveryConfiguration"
+ - "cognito-idp:GetUserAttributeVerificationCode"
+ - "cognito-idp:RespondToAuthChallenge"
+ - "cognito-idp:SetLogDeliveryConfiguration"
+ - "cognito-idp:VerifyUserAttribute"
+ - "cognito-idp:*ForgotPassword"
+ - "cognito-idp:UpdateUserPoolClient"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeCognito
+ - Effect: "Allow"
+ Action:
+ - "sns:Publish"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeDynamoDB
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:DescribeStream"
+ - "dynamodb:GetRecords"
+ - "dynamodb:GetShardIterator"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*/stream/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeDynamoDB
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:GetItem"
+ - "dynamodb:Scan"
+ - "dynamodb:Query"
+ - "dynamodb:Batch*"
+ - "dynamodb:DescribeTable"
+ - "dynamodb:DescribeTimeToLive"
+ - "dynamodb:DeleteItem"
+ - "dynamodb:PutItem"
+ - "dynamodb:UpdateItem"
+ - "dynamodb:PartiQ*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*"
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*/index/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeDynamoDB
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:ListStreams"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeDynamoDB
+ - !If
+ - AccessDynamoTable
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:BatchGetItem"
+ - "dynamodb:DescribeTable"
+ - "dynamodb:Get*"
+ - "dynamodb:Query"
+ - "dynamodb:Scan"
+ - "dynamodb:UpdateItem"
+ - "dynamodb:PutItem"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:*:table:*"
+ Condition:
+ ForAnyValue:StringEquals:
+ "aws:ResourceAccount": !Ref AccessDynamoDBAccounts #AWS account ID of the resource being accessed
+ - !Ref AWS::NoValue
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeECRAndECS
+ - Effect: "Allow"
+ Action:
+ - "ecr:BatchCheckLayerAvailability"
+ - "ecr:BatchGetImage"
+ - "ecr:GetDownloadUrlForLayer"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecr:${AWS::Region}:*:repository/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeECRAndECS
+ - Effect: "Allow"
+ Action:
+ - "ecr:GetAuthorizationToken"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeECRAndECS
+ - Effect: "Allow"
+ Action:
+ - "ecs:RunTask"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:task-definition/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeEC2
+ - Effect: "Allow"
+ Action:
+ - "ec2:DescribeNetworkInterfaces"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeEC2
+ - Effect: "Allow"
+ Action:
+ - "ec2:*NetworkInterface"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:*/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeEC2
+ - Effect: "Allow"
+ Action:
+ - "ec2:StartInstances"
+ - "ec2:StopInstances"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*"
+ - !Sub "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:license-configuration:*"
+ Condition:
+ StringLike:
+ "ec2:ResourceTag/Name": "*redshift*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeEventBridge
+ - Effect: "Allow"
+ Action:
+ - "events:PutEvents"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:event-bus/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeEventBridge
+ - Effect: "Allow"
+ Action:
+ - "scheduler:UpdateSchedule"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:scheduler:${AWS::Region}:${AWS::AccountId}:schedule/*/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeFirehoseAndKinesis
+ - Effect: "Allow"
+ Action:
+ - "firehose:PutRecord*"
+ - "firehose:DescribeDeliveryStream"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:firehose:${AWS::Region}:${AWS::AccountId}:deliverystream/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeAthenaAndGlue
+ - Effect: "Allow"
+ Action:
+ - "glue:GetDatabase"
+ - "glue:GetTable*"
+ - "glue:CreateTable"
+ - "glue:UpdateTable"
+ - "glue:CreateDatabase"
+ - "glue:BatchCreatePartition"
+ - "glue:*GetPartition*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:glue:${AWS::Region}:${AWS::AccountId}:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeAthenaAndGlue
+ - Effect: "Allow"
+ Action:
+ - "glue:GetSecurityConfiguration"
+ Resource: "*"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "iam:PassRole"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/*"
+ - !If
+ - IncludeFirehoseAndKinesis
+ - Effect: "Allow"
+ Action:
+ - "kinesis:DescribeLimits"
+ - "kinesis:ListStreams"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeFirehoseAndKinesis
+ - Effect: "Allow"
+ Action:
+ - "kinesis:DescribeStream"
+ - "kinesis:DescribeStreamSummary"
+ - "kinesis:Get*"
+ - "kinesis:PutRecord*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:kinesis:${AWS::Region}:${AWS::AccountId}:stream/*"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:*crypt*"
+ - "kms:GenerateDataKey*"
+ - "kms:GetPublicKey"
+ - "kms:Sign"
+ - "kms:Verify"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:*:key/*"
+ - Effect: "Allow"
+ Action:
+ - "kms:GenerateRandom"
+ - "kms:ListKeys"
+ Resource:
+ - "*"
+ - !If
+ - IncludeLambda
+ - !If
+ - SigningProfile
+ - Effect: "Allow"
+ Action:
+ - "lambda:GetAlias"
+ - "lambda:GetProvisionedConcurrencyConfig"
+ - "lambda:UpdateAlias"
+ - "lambda:InvokeFunction"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
+ - !Ref AWS::NoValue
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeLambda
+ - !If
+ - InvokableLambda
+ - Effect: "Allow"
+ Action:
+ - "lambda:InvokeFunction"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:*:function:*"
+ Condition:
+ ForAnyValue:StringEquals:
+ "aws:ResourceAccount": !Ref InvokableLambdaAccounts
+ - !Ref AWS::NoValue
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeLambda
+ - Effect: "Allow"
+ Action:
+ - "lambda:*EventSourceMapping*"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludePerformanceTest
+ - !If
+ - InvokableLambda
+ - Effect: "Allow"
+ Action:
+ - "lambda:InvokeFunction"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:*:function:*"
+ Condition:
+ ForAnyValue:StringEquals:
+ "aws:ResourceAccount": !Ref InvokableLambdaAccounts
+ - !Ref AWS::NoValue
+ - !Ref AWS::NoValue
+ - !If
+ - IncludePerformanceTest
+ - Effect: Allow
+ Action:
+ - ec2:CreateNetworkInterface
+ - ec2:DescribeDhcpOptions
+ - ec2:DescribeNetworkInterfaces
+ - ec2:DeleteNetworkInterface
+ - ec2:DescribeSubnets
+ - ec2:DescribeSecurityGroups
+ - ec2:DescribeVpcs
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludePerformanceTest
+ - Effect: Allow
+ Action:
+ - ec2:CreateNetworkInterfacePermission
+ Resource: !Sub "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:network-interface/*"
+ Condition:
+ ArnEquals:
+ ec2:Subnet:
+ - Fn::Sub:
+ - "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${SubnetId}"
+ - SubnetId:
+ Fn::ImportValue:
+ Fn::Sub: "${VpcStackName}-ProtectedSubnetIdA"
+ - Fn::Sub:
+ - "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${SubnetId}"
+ - SubnetId:
+ Fn::ImportValue:
+ Fn::Sub: "${VpcStackName}-ProtectedSubnetIdB"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "logs:CreateLog*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
+ - Effect: "Allow"
+ Action:
+ - "logs:PutLogEvents"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:log-stream:*"
+ - Effect: "Allow"
+ Action:
+ - "logs:*LogDeliver*"
+ - "logs:*LogEvents"
+ - "logs:PutResourcePolicy"
+ - "logs:DescribeResourcePolicies"
+ - "logs:DescribeLog*"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "secretsmanager:CreateSecret" # pragma: allowlist secret
+ - "secretsmanager:DeleteResourcePolicy" # pragma: allowlist secret
+ - "secretsmanager:DeleteSecret" # pragma: allowlist secret
+ - "secretsmanager:DescribeSecret" # pragma: allowlist secret
+ - "secretsmanager:GetRandomPassword" # pragma: allowlist secret
+ - "secretsmanager:GetResourcePolicy" # pragma: allowlist secret
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecretVersionIds" # pragma: allowlist secret
+ - "secretsmanager:PutResourcePolicy" # pragma: allowlist secret
+ - "secretsmanager:PutSecretValue" # pragma: allowlist secret
+ - "secretsmanager:RestoreSecret" # pragma: allowlist secret
+ - "secretsmanager:TagResource" # pragma: allowlist secret
+ - "secretsmanager:UntagResource" # pragma: allowlist secret
+ - "secretsmanager:UpdateSecret" # pragma: allowlist secret
+ - "secretsmanager:UpdateSecretVersionStage" # pragma: allowlist secret
+ - "secretsmanager:ValidateResourcePolicy" # pragma: allowlist secret
+ Resource:
+ - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*" # pragma: allowlist secret
+ - Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecrets" # pragma: allowlist secret
+ Resource:
+ - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:216552277552:secret:*" # pragma: allowlist secret
+ - !If
+ - IncludeQuickSight
+ - Effect: "Allow"
+ Action:
+ - "quicksight:CreateAnalysis"
+ - "quicksight:CreateGroupMembership"
+ - "quicksight:DeleteUser"
+ - "quicksight:DescribeAnalysis"
+ - "quicksight:DescribeAnalysisPermissions"
+ - "quicksight:DescribeAssetBundleExportJob"
+ - "quicksight:DescribeAssetBundleImportJob"
+ - "quicksight:DescribeTheme"
+ - "quicksight:DescribeUser"
+ - "quicksight:GenerateEmbedUrlForRegisteredUser"
+ - "quicksight:ListGroups"
+ - "quicksight:ListUserGroups"
+ - "quicksight:PassDataSet"
+ - "quicksight:RegisterUser"
+ - "quicksight:StartAssetBundleExportJob"
+ - "quicksight:StartAssetBundleImportJob"
+ - "quicksight:UpdateAnalysis"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:quicksight:${AWS::Region}:${AWS::AccountId}:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeAthenaGlueRedshift
+ - Effect: "Allow"
+ Action:
+ - "redshift-data:ExecuteStatement"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:*"
+ - !Sub "arn:${AWS::Partition}:redshift-serverless:${AWS::Region}:${AWS::AccountId}:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeAthenaGlueRedshift
+ - Effect: "Allow"
+ Action:
+ - "redshift-data:DescribeStatement"
+ - "redshift-data:GetStatementResult"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeSNS
+ - Effect: "Allow"
+ Action:
+ - "sns:Publish"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*"
+ Condition:
+ StringEquals:
+ "aws:PrincipalOrgID": !Ref AWSOrganizationId
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeSSM
+ - Effect: "Allow"
+ Action:
+ - "ssm:DescribeParameters"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeSSM
+ - Effect: "Allow"
+ Action:
+ - "ssm:GetParameter*"
+ - "ssm:PutParameter"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeStepFunctions
+ - Effect: "Allow"
+ Action:
+ - "states:Start*"
+ - "states:ListExecutions"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:stateMachine:*"
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:mapRun:*/*:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeStepFunctions
+ - Effect: "Allow"
+ Action:
+ - "states:DescribeExecution"
+ - "states:StopExecution"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:execution:*:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeStepFunctions
+ - Effect: "Allow"
+ Action:
+ - "states:GetActivityTask"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:activity:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeStepFunctions
+ - Effect: "Allow"
+ Action:
+ - "states:SendTask*"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeSQS
+ - Effect: "Allow"
+ Action:
+ - "sqs:ChangeMessageVisibility"
+ - "sqs:DeleteMessage"
+ - "sqs:GetQueue*"
+ - "sqs:ReceiveMessage"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:*:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeSQS
+ - Effect: "Allow"
+ Action:
+ - "sqs:SendMessage*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:*"
+ - !Ref AWS::NoValue
+ - !If
+ - IncludePerformanceTest
+ - !If
+ - InvokableLambda
+ - Effect: "Allow"
+ Action:
+ - "sqs:SendMessage"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:*:*"
+ Condition:
+ ForAnyValue:StringEquals:
+ "aws:ResourceAccount": !Ref InvokableLambdaAccounts
+ - !Ref AWS::NoValue
+ - !Ref AWS::NoValue
+ - !If
+ - IncludeDynamicSQS
+ - Effect: "Allow"
+ Action:
+ - "sqs:CreateQueue"
+ - "sqs:DeleteQueue"
+ - "sqs:SetQueueAttributes"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:${DynamicResourcesPrefix}-*"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "sts:AssumeRole"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${SAMStackName}-PerformanceTesterRole"
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${SAMStackName}-*pairwise*"
+ - Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:ListBucket"
+ - "s3:ListBucketVersions"
+ - "s3:ListAllMyBuckets"
+ - "s3:GetBucketLocation"
+ - "s3:GetObjectTagging"
+ - "s3:GetObjectVersion"
+ - "s3:GetLifecycleConfiguration"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::*"
+ - !Sub "arn:${AWS::Partition}:s3:::*/*"
+ - Effect: "Allow"
+ Action:
+ - "s3:DeleteObject*"
+ - "s3:PutObject"
+ - "s3:PutObjectAcl"
+ - "s3:PutObjectTagging"
+ - "s3:PutLifecycleConfiguration"
+ - "s3:RestoreObject"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::*"
+ - !Sub "arn:${AWS::Partition}:s3:::*/*"
+ Condition:
+ StringEquals:
+ "s3:ResourceAccount":
+ - !Sub "${AWS::AccountId}"
+ - Effect: "Allow"
+ Action:
+ - "s3:CreateJob"
+ - "s3:DescribeJob"
+ - "s3:*JobTagging" # GetJobTagging, PutJobTagging, DeleteJobTagging
+ Resource:
+ - "*"
+ - Effect: Allow
+ Action:
+ - "textract:*"
+ Resource:
+ - "*"
+ Condition:
+ StringEquals:
+ "aws:PrincipalOrgID": !Ref AWSOrganizationId
+ - !If
+ - IncludeXray
+ - Effect: "Allow"
+ Action:
+ - "xray:PutTraceSegments"
+ - "xray:PutTelemetryRecords"
+ - "xray:GetSampling*"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+
+ DeployPolicy1:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployPolicy1"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "PolicyManagement"
+ Effect: "Allow"
+ Action:
+ - "iam:CreatePolicy*"
+ - "iam:DeletePolicy*"
+ - "iam:GetPolicy*"
+ - "iam:ListPolicyTags"
+ - "iam:ListPolicyVersions"
+ - "iam:TagPolicy"
+ - "iam:UntagPolicy"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/*"
+ - !If
+ - UseProgrammaticPermissionsBoundary
+ - Sid: "RoleManagementWithBoundary"
+ Effect: "Allow"
+ Action:
+ - "iam:AttachRolePolicy"
+ - "iam:CreateRole"
+ - "iam:DeleteRolePolicy"
+ - "iam:DetachRolePolicy"
+ - "iam:PutRolePermissionsBoundary"
+ - "iam:PutRolePolicy"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${SAMStackName}-*"
+ Condition:
+ StringEquals:
+ "iam:PermissionsBoundary": !Ref AppProgrammaticPermissionsBoundary
+ - Sid: "RoleManagementWithBoundary"
+ Effect: "Allow"
+ Action:
+ - "iam:AttachRolePolicy"
+ - "iam:CreateRole"
+ - "iam:DeleteRolePolicy"
+ - "iam:DetachRolePolicy"
+ - "iam:PutRolePermissionsBoundary"
+ - "iam:PutRolePolicy"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${SAMStackName}-*"
+ Condition:
+ StringEquals:
+ "iam:PermissionsBoundary": !Ref AppPermissionsBoundary
+ - Sid: "RoleManagement"
+ Effect: "Allow"
+ Action:
+ - "iam:DeleteRole"
+ - "iam:GetRole"
+ - "iam:GetRolePolicy"
+ - "iam:ListRolePolicies"
+ - "iam:ListAttachedRolePolicies"
+ - "iam:ListRoleTags"
+ - "iam:TagRole"
+ - "iam:UntagRole"
+ - "iam:UpdateAssumeRolePolicy"
+ - "iam:UpdateRole"
+ - "iam:UpdateRoleDescription"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${SAMStackName}-*"
+ - Sid: "ServiceLinkedRoleManagement"
+ Effect: "Allow"
+ Action:
+ - "iam:CreateServiceLinkedRole"
+ - "iam:DeleteServiceLinkedRole"
+ - "iam:GetServiceLinkedRoleDeletionStatus"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/*"
+ - Sid: "ListServiceRoles"
+ Effect: "Allow"
+ Action:
+ - "iam:ListRoles"
+ Resource: "*"
+ - Sid: "PassRole"
+ Effect: "Allow"
+ Action:
+ - "iam:PassRole"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${SAMStackName}-*"
+ - Sid: "PassAutoscalingRole"
+ Effect: "Allow"
+ Action:
+ - "iam:PassRole"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/lambda.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_LambdaConcurrency"
+ - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"
+ - !If
+ - SigningProfile
+ - Sid: "DeploySignedLambda"
+ Effect: "Allow"
+ Action:
+ - "lambda:CreateFunction"
+ - "lambda:PutFunctionCodeSigningConfig"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
+ Condition:
+ ForAnyValue:StringEquals:
+ lambda:CodeSigningConfigArn:
+ - !Ref CodeSigningConfig
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "CodeSigning"
+ Effect: "Allow"
+ Action:
+ - "lambda:GetCodeSigningConfig"
+ Resource:
+ - !Ref CodeSigningConfig
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "ManageLambda"
+ Effect: "Allow"
+ Action:
+ - "lambda:AddPermission"
+ - "lambda:CreateAlias"
+ - "lambda:DeleteAlias"
+ - "lambda:DeleteFunction"
+ - "lambda:DeleteFunctionConcurrency"
+ - "lambda:DeleteFunctionEventInvokeConfig"
+ - "lambda:GetAlias"
+ - "lambda:GetFunction"
+ - "lambda:GetFunctionConfiguration"
+ - "lambda:GetFunctionEventInvokeConfig"
+ - "lambda:GetPolicy"
+ - "lambda:InvokeAsync"
+ - "lambda:InvokeFunction"
+ - "lambda:ListAliases"
+ - "lambda:ListFunctionEventInvokeConfigs"
+ - "lambda:ListProvisionedConcurrencyConfigs"
+ - "lambda:ListTags"
+ - "lambda:ListVersionsByFunction"
+ - "lambda:PublishVersion"
+ - "lambda:PutFunctionConcurrency"
+ - "lambda:PutFunctionEventInvokeConfig"
+ - "lambda:RemovePermission"
+ - "lambda:TagResource"
+ - "lambda:UntagResource"
+ - "lambda:UpdateAlias"
+ - "lambda:UpdateFunctionCode"
+ - "lambda:UpdateFunctionConfiguration"
+ - "lambda:UpdateFunctionEventInvokeConfig"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "ManageLambdaLayers"
+ Effect: "Allow"
+ Action:
+ - "lambda:AddLayerVersionPermission"
+ - "lambda:DeleteLayerVersion"
+ - "lambda:GetLayerVersion*"
+ - "lambda:PublishLayerVersion"
+ - "lambda:RemoveLayerVersionPermission"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:layer:*"
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:layer:*:*"
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "LambdaLayers"
+ Effect: "Allow"
+ Action:
+ - "lambda:ListLayer*"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "EventSourceMappings"
+ Effect: "Allow"
+ Action:
+ - "lambda:CreateEventSourceMapping"
+ - "lambda:GetEventSourceMapping"
+ - "lambda:ListEventSourceMappings"
+ Resource:
+ - "*"
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "EventSourceMappingManagement"
+ Effect: "Allow"
+ Action:
+ - "lambda:*EventSourceMapping"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:event-source-mapping:*"
+ - !Ref AWS::NoValue
+ - !If
+ - SigningProfile
+ - Sid: "ProvisionedConcurrency"
+ Effect: "Allow"
+ Action:
+ - "lambda:DeleteProvisionedConcurrencyConfig"
+ - "lambda:GetProvisionedConcurrencyConfig"
+ - "lambda:PutProvisionedConcurrencyConfig"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*:*"
+ - !Ref AWS::NoValue
+ - Sid: "ManageAutoscaling"
+ Effect: "Allow"
+ Action:
+ - "application-autoscaling:*ScalableTarge*"
+ - "application-autoscaling:DescribeScalingPolicies"
+ - "application-autoscaling:PutScalingPolicy"
+ - "application-autoscaling:DeleteScalingPolicy"
+ - "application-autoscaling:DescribeScheduledActions"
+ Resource: "*"
+ - Sid: "AthenaWorkGroup"
+ Effect: "Allow"
+ Action:
+ - "athena:CreateWorkGroup"
+ - "athena:DeleteWorkGroup"
+ - "athena:GetWorkGroup"
+ - "athena:ListWorkGroups"
+ - "athena:UpdateWorkGroup"
+ - "athena:*agResourc*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:athena:${AWS::Region}:${AWS::AccountId}:workgroup/*"
+
+ DeployPolicy2:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployPolicy2"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "ApiGateway"
+ Effect: "Allow"
+ Action:
+ - "apigateway:*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}::*"
+ - Sid: "SNS"
+ Effect: "Allow"
+ Action:
+ - "sns:GetSubscriptionAttributes"
+ - "sns:ListSubscriptions"
+ - "sns:ListTopics"
+ - "sns:SetSubscriptionAttributes"
+ Resource:
+ - "*"
+ - Sid: "SNSSubscribe"
+ Effect: "Allow"
+ Action:
+ - "sns:Unsubscribe"
+ - "sns:Subscribe"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:*:*"
+ - Sid: "SNSManagement"
+ Effect: "Allow"
+ Action:
+ - "sns:AddPermission"
+ - "sns:CreateTopic"
+ - "sns:DeleteTopic"
+ - "sns:GetTopicAttributes"
+ - "sns:ListSubscriptionsByTopic"
+ - "sns:ListTagsForResource"
+ - "sns:Publish"
+ - "sns:RemovePermission"
+ - "sns:SetTopicAttributes"
+ - "sns:TagResource"
+ - "sns:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*"
+ - Sid: "SQSManagement"
+ Effect: "Allow"
+ Action:
+ - "sqs:AddPermission"
+ - "sqs:ChangeMessageVisibility"
+ - "sqs:CreateQueue"
+ - "sqs:DeleteMessage"
+ - "sqs:DeleteQueue"
+ - "sqs:GetQueueAttributes"
+ - "sqs:ListDeadLetterSourceQueues"
+ - "sqs:ListQueueTags"
+ - "sqs:PurgeQueue"
+ - "sqs:ReceiveMessage"
+ - "sqs:RemovePermission"
+ - "sqs:SendMessage"
+ - "sqs:SetQueueAttributes"
+ - "sqs:TagQueue"
+ - "sqs:UntagQueue"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:*"
+ - Sid: "SQS"
+ Effect: "Allow"
+ Action:
+ - "sqs:ListQueues"
+ Resource:
+ - "*"
+ - Sid: "KinesisStreamManagement"
+ Effect: "Allow"
+ Action:
+ - "kinesis:AddTagsToStream"
+ - "kinesis:CreateStream"
+ - "kinesis:DecreaseStreamRetentionPeriod"
+ - "kinesis:DeleteStream"
+ - "kinesis:DescribeStream*"
+ - "kinesis:GetRecords"
+ - "kinesis:GetShardIterator"
+ - "kinesis:IncreaseStreamRetentionPeriod"
+ - "kinesis:ListStreamConsumers"
+ - "kinesis:ListTagsForStream"
+ - "kinesis:MergeShards"
+ - "kinesis:PutRecord*"
+ - "kinesis:RegisterStreamConsumer"
+ - "kinesis:RemoveTagsFromStream"
+ - "kinesis:SplitShard"
+ - "kinesis:*StreamEncryption"
+ - "kinesis:SubscribeToShard"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:kinesis:${AWS::Region}:${AWS::AccountId}:stream/*"
+ - Sid: "Kinesis"
+ Effect: "Allow"
+ Action:
+ - "kinesis:*EnhancedMonitoring"
+ - "kinesis:ListShards"
+ - "kinesis:ListStreams"
+ - "kinesis:UpdateShardCount"
+ - "kinesis:UpdateStreamMode"
+ Resource:
+ - "*"
+ - Sid: "KinesisFirehoseManagement"
+ Effect: "Allow"
+ Action:
+ - "firehose:CreateDeliveryStream"
+ - "firehose:DeleteDeliveryStream"
+ - "firehose:DescribeDeliveryStream"
+ - "firehose:ListTagsForDeliveryStream"
+ - "firehose:PutRecord*"
+ - "firehose:StartDeliveryStreamEncryption"
+ - "firehose:StopDeliveryStreamEncryption"
+ - "firehose:TagDeliveryStream"
+ - "firehose:UntagDeliveryStream"
+ - "firehose:UpdateDestination"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:firehose:${AWS::Region}:${AWS::AccountId}:deliverystream/*"
+ - Sid: "KinesisFirehose"
+ Effect: "Allow"
+ Action:
+ - "firehose:ListDeliveryStreams"
+ Resource:
+ - "*"
+ - Sid: "DynamoDBManagement"
+ Effect: "Allow"
+ Action:
+ - "dynamodb:Batch*"
+ - "dynamodb:ConditionCheckItem"
+ - "dynamodb:CreateBackup"
+ - "dynamodb:CreateTable*"
+ - "dynamodb:DeleteTable*"
+ - "dynamodb:DescribeContinuousBackups"
+ - "dynamodb:DescribeContributorInsights"
+ - "dynamodb:DescribeKinesisStreamingDestination"
+ - "dynamodb:DescribeTable*"
+ - "dynamodb:DescribeTimeToLive"
+ - "dynamodb:DisableKinesisStreamingDestination"
+ - "dynamodb:EnableKinesisStreamingDestination"
+ - "dynamodb:ExportTableToPointInTime"
+ - "dynamodb:GetItem"
+ - "dynamodb:List*"
+ - "dynamodb:PartiQL*"
+ - "dynamodb:PutItem"
+ - "dynamodb:Query"
+ - "dynamodb:Restore*"
+ - "dynamodb:Scan"
+ - "dynamodb:StartAwsBackupJob"
+ - "dynamodb:TagResource"
+ - "dynamodb:UntagResource"
+ - "dynamodb:UpdateContinuousBackups"
+ - "dynamodb:UpdateContributorInsights"
+ - "dynamodb:UpdateItem"
+ - "dynamodb:UpdateTable*"
+ - "dynamodb:UpdateTimeToLive"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*"
+ - Sid: "DynamoDBStreamManagement"
+ Effect: "Allow"
+ Action:
+ - "dynamodb:DescribeStream"
+ - "dynamodb:GetRecords"
+ - "dynamodb:GetShardIterator"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*/stream/*"
+ - Sid: "DynamoDB"
+ Effect: "Allow"
+ Action:
+ - "dynamodb:ListBackups"
+ - "dynamodb:ListContributorInsights"
+ - "dynamodb:ListStreams"
+ - "dynamodb:ListTables"
+ Resource:
+ - "*"
+ - Sid: "S3Management"
+ Effect: "Allow"
+ Action:
+ - "s3:CreateBucket"
+ - "s3:DeleteAccessGrant"
+ - "s3:DeleteBucket"
+ - "s3:DeleteBucketPolicy"
+ - "s3:GetAccelerateConfiguration"
+ - "s3:GetBucket*"
+ - "s3:GetEncryptionConfiguration"
+ - "s3:GetIntelligentTieringConfiguration"
+ - "s3:GetInventoryConfiguration"
+ - "s3:GetLifecycleConfiguration"
+ - "s3:GetMetricsConfiguration"
+ - "s3:GetObject"
+ - "s3:GetReplicationConfiguration"
+ - "s3:ListBucket*"
+ - "s3:PutAccelerateConfiguration"
+ - "s3:PutAccountPublicAccessBlock"
+ - "s3:PutAnalyticsConfiguration"
+ - "s3:PutBucket*"
+ - "s3:PutEncryptionConfiguration"
+ - "s3:PutIntelligentTieringConfiguration"
+ - "s3:PutInventoryConfiguration"
+ - "s3:PutLifecycleConfiguration"
+ - "s3:PutMetricsConfiguration"
+ - "s3:PutReplicationConfiguration"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::*"
+ - Sid: "EventBusManagement"
+ Effect: "Allow"
+ Action:
+ - "events:CreateEventBus"
+ - "events:DeleteEventBus"
+ - "events:DescribeEventBus"
+ - "events:ListTagsForResource"
+ - "events:PutEvents"
+ - "events:TagResource"
+ - "events:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:event-bus/*"
+ - Sid: "EventRuleManagement"
+ Effect: "Allow"
+ Action:
+ - "events:DeleteRule"
+ - "events:DescribeRule"
+ - "events:DisableRule"
+ - "events:EnableRule"
+ - "events:ListTagsForResource"
+ - "events:PutRule"
+ - "events:PutTargets"
+ - "events:RemoveTargets"
+ - "events:TagResource"
+ - "events:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/*"
+ - Sid: "EventHub"
+ Effect: "Allow"
+ Action:
+ - "events:ListEventBuses"
+ - "events:ListRules"
+ - "events:PutPermission"
+ - "events:RemovePermission"
+ - "events:TestEventPattern"
+ Resource:
+ - "*"
+
+ DeployPolicy3:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployPolicy3"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "LogManagement"
+ Effect: "Allow"
+ Action:
+ - "logs:AssociateKmsKey"
+ - "logs:CreateLogGroup"
+ - "logs:CreateLogStream"
+ - "logs:DeleteLogGroup"
+ - "logs:DeleteLogStream"
+ - "logs:DeleteMetricFilter"
+ - "logs:DeleteRetentionPolicy"
+ - "logs:DeleteSubscriptionFilter"
+ - "logs:DescribeLogGroups"
+ - "logs:DescribeLogStreams"
+ - "logs:DescribeMetricFilters"
+ - "logs:DescribeSubscriptionFilters"
+ - "logs:DisassociateKmsKey"
+ - "logs:GetLogEvents"
+ - "logs:FilterLogEvents"
+ - "logs:ListTagsLogGroup"
+ - "logs:ListTagsForResource"
+ - "logs:PutMetricFilter"
+ - "logs:PutRetentionPolicy"
+ - "logs:PutSubscriptionFilter"
+ - "logs:TagLogGroup"
+ - "logs:UntagLogGroup"
+ - "logs:TagResource"
+ - "logs:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:log-stream:*"
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:885513274347:destination:*"
+ - Sid: "CloudWatchAlarmManagement"
+ Effect: "Allow"
+ Action:
+ - "cloudwatch:DeleteAlarms"
+ - "cloudwatch:DescribeAlarmHistory"
+ - "cloudwatch:DescribeAlarms"
+ - "cloudwatch:DisableAlarmActions"
+ - "cloudwatch:EnableAlarmActions"
+ - "cloudwatch:ListTagsForResource"
+ - "cloudwatch:PutCompositeAlarm"
+ - "cloudwatch:PutMetricAlarm"
+ - "cloudwatch:SetAlarmState"
+ - "cloudwatch:TagResource"
+ - "cloudwatch:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
+ - Sid: "CloudWatchDashboardManagement"
+ Effect: "Allow"
+ Action:
+ - "cloudwatch:DeleteDashboards"
+ - "cloudwatch:GetDashboard"
+ - "cloudwatch:ListTagsForResource"
+ - "cloudwatch:PutDashboard"
+ - "cloudwatch:TagResource"
+ - "cloudwatch:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudwatch::${AWS::AccountId}:dashboard/*"
+ - Sid: "CloudWatchInsightRuleManagement"
+ Effect: "Allow"
+ Action:
+ - "cloudwatch:DeleteInsightRules"
+ - "cloudwatch:DisableInsightRules"
+ - "cloudwatch:EnableInsightRules"
+ - "cloudwatch:GetInsightRuleReport"
+ - "cloudwatch:ListTagsForResource"
+ - "cloudwatch:PutInsightRule"
+ - "cloudwatch:TagResource"
+ - "cloudwatch:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:insight-rule/*"
+ - Sid: "CloudWatch"
+ Effect: "Allow"
+ Action:
+ - "cloudwatch:DeleteAnomalyDetector"
+ - "cloudwatch:DescribeAlarmsForMetric"
+ - "cloudwatch:DescribeAnomalyDetectors"
+ - "cloudwatch:DescribeInsightRules"
+ - "cloudwatch:ListDashboards"
+ - "cloudwatch:PutAnomalyDetector"
+ - "cloudwatch:PutMetricData"
+ Resource:
+ - "*"
+ - Sid: "ApiGatewayLogDelivery"
+ Effect: "Allow"
+ Action:
+ - "logs:CreateLogDelivery"
+ - "logs:DeleteLogDelivery"
+ - "logs:DescribeResourcePolicies"
+ - "logs:GetLogDelivery"
+ - "logs:ListLogDeliveries"
+ - "logs:PutResourcePolicy"
+ - "logs:UpdateLogDelivery"
+ Resource:
+ - "*"
+ - Sid: "SSMParameterManagement"
+ Effect: "Allow"
+ Action:
+ - "ssm:AddTagsToResource"
+ - "ssm:DeleteParameter*"
+ - "ssm:DescribeParameters"
+ - "ssm:GetParameter*"
+ - "ssm:LabelParameterVersion"
+ - "ssm:ListTagsForResource"
+ - "ssm:PutParameter"
+ - "ssm:RemoveTagsFromResource"
+ - "ssm:UnlabelParameterVersion"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/*"
+ - Sid: "SecretsManagerManagement"
+ Effect: "Allow"
+ Action:
+ - "secretsmanager:CancelRotateSecret" # pragma: allowlist secret
+ - "secretsmanager:CreateSecret" # pragma: allowlist secret
+ - "secretsmanager:DeleteResourcePolicy" # pragma: allowlist secret
+ - "secretsmanager:DeleteSecret" # pragma: allowlist secret
+ - "secretsmanager:DescribeSecret" # pragma: allowlist secret
+ - "secretsmanager:GetResourcePolicy" # pragma: allowlist secret
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecretVersionIds" # pragma: allowlist secret
+ - "secretsmanager:PutResourcePolicy" # pragma: allowlist secret
+ - "secretsmanager:PutSecretValue" # pragma: allowlist secret
+ - "secretsmanager:RestoreSecret" # pragma: allowlist secret
+ - "secretsmanager:RotateSecret" # pragma: allowlist secret
+ - "secretsmanager:TagResource" # pragma: allowlist secret
+ - "secretsmanager:UntagResource" # pragma: allowlist secret
+ - "secretsmanager:UpdateSecret" # pragma: allowlist secret
+ - "secretsmanager:UpdateSecretVersionStage" # pragma: allowlist secret
+ - "secretsmanager:ValidateResourcePolicy" # pragma: allowlist secret
+ Resource:
+ - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*"
+ - Sid: "ObservabilitySecretsManager"
+ Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecrets" # pragma: allowlist secret
+ Resource:
+ - "arn:aws:secretsmanager:eu-west-2:216552277552:secret:*" # pragma: allowlist secret
+ - "arn:aws:secretsmanager:eu-west-2:985486846182:secret:*" # pragma: allowlist secret
+ - "arn:aws:secretsmanager:eu-west-2:841529299698:secret:*" # pragma: allowlist secret
+ - Sid: "ObservabilityLambdaLayer"
+ Effect: "Allow"
+ Action:
+ - "lambda:GetLayerVersion"
+ Resource:
+ - "arn:aws:lambda:eu-west-2:216552277552:layer:*:*"
+ - "arn:aws:lambda:eu-west-2:985486846182:layer:*:*"
+ - "arn:aws:lambda:eu-west-2:841529299698:layer:*:*"
+ - Sid: "ObservabilityKMS"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Decrypt"
+ - "kms:Verify"
+ Resource:
+ - "arn:aws:kms:eu-west-2:216552277552:key/*"
+ - "arn:aws:kms:eu-west-2:985486846182:key/*"
+ - "arn:aws:kms:eu-west-2:841529299698:key/*"
+ - !If
+ - CreateCustomKMSKeyPolicy
+ - Sid: "CustomKMSKeySigning"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Decrypt"
+ - "kms:Verify"
+ Resource: !Ref "CustomKmsKeyArns"
+ - !Ref AWS::NoValue
+ - Sid: "SecretsManagerWithoutTiesToResourcesManagement"
+ Effect: "Allow"
+ Action:
+ - "secretsmanager:GetRandomPassword" # pragma: allowlist secret
+ - "secretsmanager:ListSecrets" # pragma: allowlist secret
+ Resource: "*"
+ - Sid: "StepFunctionManagement"
+ Effect: "Allow"
+ Action:
+ - "states:CreateActivity"
+ - "states:CreateStateMachine"
+ - "states:DeleteActivity"
+ - "states:DeleteStateMachine"
+ - "states:UpdateStateMachine"
+ - "states:DescribeActivity"
+ - "states:DescribeStateMachine"
+ - "states:ListTagsForResource"
+ - "states:TagResource"
+ - "states:UntagResource"
+ - "states:DescribeStateMachineAlias"
+ - "states:DeleteStateMachineAlias"
+ - "states:ListStateMachineAliases"
+ - "states:CreateStateMachineAlias"
+ - "states:UpdateStateMachineAlias"
+ - "states:DeleteStateMachineVersion"
+ - "states:ListStateMachineVersions"
+ - "states:PublishStateMachineVersion"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:activity:*"
+ - !Sub "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:stateMachine:*"
+ - Sid: "ListStepFunctions"
+ Effect: "Allow"
+ Action:
+ - "states:ListActivities"
+ - "states:ListStateMachines"
+ Resource:
+ - "*"
+
+ DeployPolicy4:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployPolicy4"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "CodeDeployApplicationManagement"
+ Effect: "Allow"
+ Action:
+ - "codedeploy:BatchGetApplicationRevisions"
+ - "codedeploy:BatchGetApplications"
+ - "codedeploy:CreateApplication"
+ - "codedeploy:DeleteApplication"
+ - "codedeploy:GetApplication"
+ - "codedeploy:GetApplicationRevision"
+ - "codedeploy:ListApplicationRevisions"
+ - "codedeploy:ListDeploymentGroups"
+ - "codedeploy:ListTagsForResource"
+ - "codedeploy:RegisterApplicationRevision"
+ - "codedeploy:TagResource"
+ - "codedeploy:UntagResource"
+ - "codedeploy:UpdateApplication"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:application:*"
+ - Sid: "CodeDeployDeploymentGroupManagement"
+ Effect: "Allow"
+ Action:
+ - "codedeploy:BatchGetDeploymentGroups"
+ - "codedeploy:BatchGetDeploymentInstances"
+ - "codedeploy:BatchGetDeployments"
+ - "codedeploy:CreateDeployment"
+ - "codedeploy:CreateDeploymentGroup"
+ - "codedeploy:DeleteDeploymentGroup"
+ - "codedeploy:GetDeployment"
+ - "codedeploy:GetDeploymentGroup"
+ - "codedeploy:GetDeploymentInstance"
+ - "codedeploy:ListDeploymentInstances"
+ - "codedeploy:ListTagsForResource"
+ - "codedeploy:TagResource"
+ - "codedeploy:UntagResource"
+ - "codedeploy:UpdateDeploymentGroup"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:*/*"
+ - Sid: "CodeDeployDeploymentConfigManagement"
+ Effect: "Allow"
+ Action:
+ - "codedeploy:CreateDeploymentConfig"
+ - "codedeploy:DeleteDeploymentConfig"
+ - "codedeploy:GetDeploymentConfig"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentconfig:*"
+ - Sid: "CodeDeploy"
+ Effect: "Allow"
+ Action:
+ - "codedeploy:BatchGetDeploymentTargets"
+ - "codedeploy:ContinueDeployment"
+ - "codedeploy:CreateCloudFormationDeployment"
+ - "codedeploy:GetDeploymentTarget"
+ - "codedeploy:ListApplications"
+ - "codedeploy:ListDeploymentConfigs"
+ - "codedeploy:ListDeploymentTargets"
+ - "codedeploy:SkipWaitTimeForInstanceTermination"
+ - "codedeploy:StopDeployment"
+ Resource:
+ - "*"
+ - Sid: "KMS"
+ Effect: "Allow"
+ Action:
+ - "kms:CreateKey"
+ - "kms:GenerateRandom"
+ - "kms:ListAliases"
+ - "kms:ListKeys"
+ Resource:
+ - "*"
+ - Sid: "KMSKeyManagement"
+ Effect: "Allow"
+ Action:
+ - "kms:CancelKeyDeletion"
+ - "kms:CreateGrant"
+ - "kms:Decrypt"
+ - "kms:DescribeKey"
+ - "kms:DisableKey*"
+ - "kms:EnableKey*"
+ - "kms:Encrypt"
+ - "kms:GenerateDataKey*"
+ - "kms:GetKeyPolicy"
+ - "kms:GetKeyRotationStatus"
+ - "kms:GetPublicKey"
+ - "kms:ListGrants"
+ - "kms:ListKeyPolicies"
+ - "kms:ListResourceTags"
+ - "kms:PutKeyPolicy"
+ - "kms:ReEncrypt*"
+ - "kms:RetireGrant"
+ - "kms:RevokeGrant"
+ - "kms:ScheduleKeyDeletion"
+ - "kms:Sign"
+ - "kms:TagResource"
+ - "kms:UntagResource"
+ - "kms:UpdateKeyDescription"
+ - "kms:Verify"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
+ - Sid: "KMSAliasManagement"
+ Effect: "Allow"
+ Action:
+ - "kms:CreateAlias"
+ - "kms:DeleteAlias"
+ - "kms:UpdateAlias"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:alias/*"
+ - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
+ - Sid: "AccessSourceArtifacts"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ Resource:
+ - !If
+ - CreateGitHubActionsResources
+ - !GetAtt GitHubArtifactSourceBucket.Arn
+ - !Ref ArtifactSourceBucketArn
+ - !If
+ - CreateGitHubActionsResources
+ - !Sub "${GitHubArtifactSourceBucket.Arn}/*"
+ - !Sub "${ArtifactSourceBucketArn}/*"
+ - Sid: "TemplateBucketAccess"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetObjectTagging"
+ - "s3:ListBucket"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh"
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh/*"
+ - Sid: "ManageAppStack"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:CreateChangeSet"
+ - "cloudformation:CreateStack"
+ - "cloudformation:DeleteStack"
+ - "cloudformation:DescribeChangeSet"
+ - "cloudformation:DescribeStack*"
+ - "cloudformation:DetectStack*"
+ - "cloudformation:ExecuteChangeSet"
+ - "cloudformation:GetStackPolicy"
+ - "cloudformation:GetTemplate"
+ - "cloudformation:GetTemplateSummary"
+ - "cloudformation:ListChangeSets"
+ - "cloudformation:ListStackResources"
+ - "cloudformation:TagResource"
+ - "cloudformation:UpdateStack"
+ - "cloudformation:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${SAMStackName}*"
+ - Sid: "DescribeCurrentStack"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:DescribeStacks"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${AWS::StackName}/*"
+ - Sid: "ServerlessTransform"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:CreateChangeSet"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:aws:transform/Serverless-2016-10-31"
+ - Sid: "IncludeTransform"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:CreateChangeSet"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:aws:transform/Include"
+ - Sid: "CodeDeployBlueGreenTransform"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:CreateChangeSet"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:aws:transform/CodeDeployBlueGreen"
+ - Sid: "LanguageExtensionsTransform"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:CreateChangeSet"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:aws:transform/LanguageExtensions"
+
+ DeployPolicy5:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ # checkov:skip=CKV_AWS_111:test_create_star
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployPolicy5"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "ManageAlb"
+ Effect: "Allow"
+ Action:
+ - "elasticloadbalancing:CreateTargetGroup"
+ - "elasticloadbalancing:DeleteTargetGroup"
+ - "elasticloadbalancing:ModifyTargetGroup"
+ - "elasticloadbalancing:RegisterTargets"
+ - "elasticloadbalancing:CreateListener"
+ - "elasticloadbalancing:DeleteListener"
+ - "elasticloadbalancing:ModifyListener"
+ - "elasticloadbalancing:CreateRule"
+ - "elasticloadbalancing:DeleteRule"
+ - "elasticloadbalancing:DescribeRules"
+ - "elasticloadbalancing:CreateLoadBalancer"
+ - "elasticloadbalancing:CreateLoadBalancerListeners"
+ - "elasticloadbalancing:DeleteLoadBalancerListeners"
+ - "elasticloadbalancing:DescribeLoadBalancerAttributes"
+ - "elasticloadbalancing:DescribeLoadBalancerListeners"
+ - "elasticloadbalancing:DeleteLoadBalancer"
+ - "elasticloadbalancing:ModifyLoadBalancerAttributes"
+ - "elasticloadbalancing:ModifyTargetGroupAttributes"
+ - "elasticloadbalancing:AddTags"
+ - "elasticloadbalancing:RemoveTags"
+ - "elasticloadbalancing:ModifyListener"
+ - "elasticloadbalancing:ModifyLoadBalancerAttributes"
+ - "elasticloadbalancing:ModifyRule"
+ - "elasticloadbalancing:SetWebACL"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:elasticloadbalancing:${AWS::Region}:${AWS::AccountId}:*"
+ - Sid: "ListAlbResources"
+ Effect: "Allow"
+ Action:
+ - "elasticloadbalancing:DescribeLoadBalancers"
+ - "elasticloadbalancing:DescribeListeners"
+ - "elasticloadbalancing:DescribeTargetGroups"
+ - "elasticloadbalancing:DescribeTargetGroupAttributes"
+ - "elasticloadbalancing:DescribeTargetHealth"
+ - "elasticloadbalancing:DescribeTags"
+ - "elasticloadbalancing:DescribeRules"
+ Resource:
+ - "*"
+ - Sid: "ManageSecurityGroups"
+ Effect: "Allow"
+ Action:
+ - "ec2:CreateTags"
+ - "ec2:DeleteTags"
+ - "ec2:CreateSecurityGroup"
+ - "ec2:DeleteSecurityGroup"
+ - "ec2:ModifySecurityGroupRules"
+ - "ec2:AuthorizeSecurityGroupIngress"
+ - "ec2:AuthorizeSecurityGroupEgress"
+ - "ec2:RevokeSecurityGroupIngress"
+ - "ec2:RevokeSecurityGroupEgress"
+ - "ec2:UpdateSecurityGroupRuleDescriptionsIngress"
+ - "ec2:UpdateSecurityGroupRuleDescriptionsEgress"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:*/*"
+ - Sid: "VPC"
+ Effect: "Allow"
+ Action:
+ - "ec2:DescribeAccountAttributes"
+ - "ec2:DescribeAddresses"
+ - "ec2:DescribeInternetGateways"
+ - "ec2:DescribeNatGateways"
+ - "ec2:DescribeSecurityGroups"
+ - "ec2:DescribeSubnets"
+ - "ec2:DescribeVpcs"
+ Resource:
+ - "*"
+ - Sid: "CreateEcsClusters"
+ Effect: "Allow"
+ Action:
+ - "ecs:CreateCluster"
+ - "ecs:DescribeClusters"
+ - "ecs:DescribeServices"
+ Resource:
+ - "*"
+ - Sid: "ManageEcs"
+ Effect: "Allow"
+ Action:
+ - "ecs:DeleteCluster"
+ - "ecs:UpdateCluster"
+ - "ecs:CreateService"
+ - "ecs:DeleteService"
+ - "ecs:UpdateService"
+ - "ecs:TagResource"
+ - "ecs:UntagResource"
+ - "ecs:ListTagsForResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:*"
+ - Sid: "ManageEcsTaskDefinitions"
+ Effect: "Allow"
+ Action:
+ - "ecs:RegisterTaskDefinition"
+ - "ecs:DeregisterTaskDefinition"
+ - "ecs:DescribeTaskDefinition"
+ - "ecs:CreateTaskSet"
+ - "ecs:DeleteTaskSet"
+ - "ecs:DescribeTaskSets"
+ - "ecs:UpdateServicePrimaryTaskSet"
+ - "ecs:UpdateTaskSet"
+ Resource:
+ - "*"
+ - Sid: "CreateRoute53HostedZones"
+ Effect: "Allow"
+ Action:
+ - "route53:CreateHostedZone"
+ Resource: "*"
+ - Sid: "ManageRoute53"
+ Effect: "Allow"
+ Action:
+ - "route53:GetHostedZone"
+ - "route53:DeleteHostedZone"
+ - "route53:UpdateHostedZoneComment"
+ - "route53:ChangeResourceRecordSets"
+ - "route53:ListResourceRecordSets"
+ - "route53:ChangeTagsForResource"
+ - "route53:ListTagsForResource"
+ - "route53:GetChange"
+ - "route53:ListQueryLoggingConfigs"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:route53:::hostedzone/*"
+ - !Sub "arn:${AWS::Partition}:route53:::change/*"
+ - Sid: "CreateCertificates"
+ Effect: "Allow"
+ Action:
+ - "acm:RequestCertificate"
+ Resource: "*"
+ - Sid: "ManageCertificates"
+ Effect: "Allow"
+ Action:
+ - "acm:DescribeCertificate"
+ - "acm:DeleteCertificate"
+ - "acm:ListTagsForCertificate"
+ - "acm:AddTagsToCertificate"
+ - "acm:RemoveTagsFromCertificate"
+ - "acm:UpdateCertificateOptions"
+ Resource: !Sub "arn:${AWS::Partition}:acm:${AWS::Region}:${AWS::AccountId}:certificate/*"
+ - Sid: "ElastiCacheManagement"
+ Effect: "Allow"
+ Action:
+ - "elasticache:AddTagsToResource"
+ - "elasticache:AuthorizeCacheSecurityGroupIngress"
+ - "elasticache:CreateCacheCluster"
+ - "elasticache:CreateCacheParameterGroup"
+ - "elasticache:CreateCacheSecurityGroup"
+ - "elasticache:CreateCacheSubnetGroup"
+ - "elasticache:CreateReplicationGroup"
+ - "elasticache:DecreaseReplicaCount"
+ - "elasticache:DeleteCacheCluster"
+ - "elasticache:DeleteCacheParameterGroup"
+ - "elasticache:DeleteReplicationGroup"
+ - "elasticache:DeleteCacheSecurityGroup"
+ - "elasticache:DeleteCacheSubnetGroup"
+ - "elasticache:DescribeCacheClusters"
+ - "elasticache:DescribeCacheParameterGroups"
+ - "elasticache:DescribeCacheParameters"
+ - "elasticache:DescribeCacheParameterGroups"
+ - "elasticache:DescribeReplicationGroups"
+ - "elasticache:DescribeCacheSubnetGroups"
+ - "elasticache:IncreaseReplicaCount"
+ - "elasticache:ListAllowedNodeTypeModifications"
+ - "elasticache:ListTagsForResource"
+ - "elasticache:ModifyCacheCluster"
+ - "elasticache:ModifyCacheParameterGroup"
+ - "elasticache:ModifyCacheSubnetGroup"
+ - "elasticache:ModifyReplicationGroup"
+ - "elasticache:ModifyReplicationGroupShardConfiguration"
+ - "elasticache:RemoveTagsFromResource"
+ - "elasticache:ResetCacheParameterGroup"
+ - "elasticache:RevokeCacheSecurityGroupIngress"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:elasticache:${AWS::Region}:${AWS::AccountId}:cluster:*"
+ - !Sub "arn:${AWS::Partition}:elasticache:${AWS::Region}:${AWS::AccountId}:parametergroup:*"
+ - !Sub "arn:${AWS::Partition}:elasticache:${AWS::Region}:${AWS::AccountId}:replicationgroup:*"
+ - !Sub "arn:${AWS::Partition}:elasticache:${AWS::Region}:${AWS::AccountId}:securitygroup:*"
+ - !Sub "arn:${AWS::Partition}:elasticache:${AWS::Region}:${AWS::AccountId}:subnetgroup:*"
+ - Sid: "ElastiCache"
+ Effect: "Allow"
+ Action:
+ - "elasticache:DescribeCacheEngineVersions"
+ - "elasticache:DescribeEngineDefaultParameters"
+ Resource:
+ - "*"
+ - Sid: "SESPermissions"
+ Effect: "Allow"
+ Action:
+ - "ses:*EmailIdentity"
+ Resource:
+ - "*"
+ - Sid: "ManageUserPool"
+ Effect: "Allow"
+ Action:
+ - "cognito-idp:*ResourceServer"
+ - "cognito-idp:*UserPool"
+ - "cognito-idp:*UserPoolClient"
+ - "cognito-idp:*UserPoolDomain"
+ - "cognito-idp:List*"
+ - "cognito-idp:SetUserPoolMfaConfig"
+ - "cognito-idp:GetLogDeliveryConfiguration"
+ - "cognito-idp:SetLogDeliveryConfiguration"
+ Resource:
+ - "*"
+ - Sid: SNSPublish
+ Effect: "Allow"
+ Action:
+ - "sns:Publish"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*"
+
+ DeployPolicy6:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ # checkov:skip=CKV_AWS_111:test_create_star
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployPolicy6"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "ManageGlue"
+ Effect: "Allow"
+ Action:
+ - "glue:BatchGetPartition"
+ - "glue:BatchCreatePartition"
+ - "glue:BatchDeletePartition"
+ - "glue:BatchUpdatePartition"
+ - "glue:CreateCrawler"
+ - "glue:CreateDatabase"
+ - "glue:CreateTable"
+ - "glue:DeleteTable"
+ - "glue:DeleteCrawler"
+ - "glue:DeleteDatabase"
+ - "glue:GetDatabase"
+ - "glue:GetTable"
+ - "glue:UpdateCrawler"
+ - "glue:UpdateDatabase"
+ - "glue:UpdateTable"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:glue:${AWS::Region}:${AWS::AccountId}:catalog"
+ - !Sub "arn:${AWS::Partition}:glue:${AWS::Region}:${AWS::AccountId}:crawler/*"
+ - !Sub "arn:${AWS::Partition}:glue:${AWS::Region}:${AWS::AccountId}:database/*"
+ - !Sub "arn:${AWS::Partition}:glue:${AWS::Region}:${AWS::AccountId}:table/*"
+ - !Sub "arn:${AWS::Partition}:glue:${AWS::Region}:${AWS::AccountId}:userDefinedFunction/*"
+ - Sid: "GlueSecurityConfig"
+ Effect: "Allow"
+ Action:
+ - "glue:DeleteSecurityConfiguration"
+ - "glue:CreateSecurityConfiguration"
+ - "glue:GetSecurityConfiguration"
+ Resource: "*"
+ - Sid: "WafV2"
+ Effect: "Allow"
+ Action:
+ - "wafv2:*IPSet"
+ - "wafv2:*LoggingConfiguration"
+ - "wafv2:*PermissionPolicy"
+ - "wafv2:*RegexPatternSet"
+ - "wafv2:*RuleGroup"
+ - "wafv2:*WebACL"
+ - "wafv2:*FirewallManager*"
+ - "wafv2:GetSampledRequests"
+ - "wafv2:GetWebACLForResource"
+ - "wafv2:TagResource"
+ - "wafv2:UntagResource"
+ - "wafv2:ListTagsForResource"
+ - "wafv2:UpdateManagedRuleSetVersionExpiryDate"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:wafv2:${AWS::Region}:127546899672:*" # this is an AWS account managing Shield Advanced rules
+ - !Sub "arn:${AWS::Partition}:wafv2:${AWS::Region}:${AWS::AccountId}:*"
+ - !Sub "arn:${AWS::Partition}:elasticloadbalancing:${AWS::Region}:${AWS::AccountId}:*"
+ - !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}::*"
+ - Sid: "WafV2Global"
+ Effect: "Allow"
+ Action:
+ - "wafv2:TagResource"
+ - "wafv2:UntagResource"
+ - "wafv2:GetWebACLForResource"
+ - "wafv2:GetWebACL"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:wafv2:us-east-1:${AWS::AccountId}:*"
+ - Sid: "WafV2List"
+ Effect: "Allow"
+ Action:
+ - "wafv2:List*"
+ Resource:
+ - "*"
+ - Sid: "CloudFront"
+ Effect: "Allow"
+ Action:
+ - "cloudfront:CreateOriginRequestPolicy"
+ - "cloudfront:DeleteOriginRequestPolicy"
+ - "cloudfront:ListDistributionsByCachePolicyId"
+ - "cloudfront:GetCachePolicyConfig"
+ - "cloudfront:TagResource"
+ - "cloudfront:UpdateOriginRequestPolicy"
+ - "cloudfront:ListCachePolicies"
+ - "cloudfront:CreateDistribution"
+ - "cloudfront:ListOriginRequestPolicies"
+ - "cloudfront:GetOriginRequestPolicyConfig"
+ - "cloudfront:CreateCachePolicy"
+ - "cloudfront:GetDistribution"
+ - "cloudfront:UpdateCachePolicy"
+ - "cloudfront:ListTagsForResource"
+ - "cloudfront:GetOriginRequestPolicy"
+ - "cloudfront:ListDistributions"
+ - "cloudfront:DeleteCachePolicy"
+ - "cloudfront:UpdateDistribution"
+ - "cloudfront:GetCachePolicy"
+ - "cloudfront:DeleteDistribution"
+ - "cloudfront:UntagResource"
+ - "cloudfront:*Function*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudfront::${AWS::AccountId}:*"
+ - Sid: "CloudwatchSyntheticLambdaCreate"
+ Effect: "Allow"
+ Action:
+ - "lambda:CreateFunction"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:cwsyn-*"
+ - Sid: "CloudwatchSyntheticLambdaLayer"
+ Effect: "Allow"
+ Action:
+ - "lambda:GetLayerVersion"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:*:layer:Synthetics:*"
+ - Sid: "CloudwatchSyntheticDelete"
+ Effect: "Allow"
+ Action:
+ - "synthetics:TagResource"
+ - "synthetics:*Canary"
+ - "synthetics:DescribeCanaries"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:synthetics:${AWS::Region}:${AWS::AccountId}:canary:*"
+ - Sid: "CloudwatchSyntheticS3ObjectVersion"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObjectVersion"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::aws-synthetics-library-${AWS::Region}/*"
+ - Sid: "UpdatedPipes"
+ Effect: "Allow"
+ Action:
+ - "pipes:*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:pipes:${AWS::Region}:${AWS::AccountId}:pipe/*"
+ - Sid: "ManageOIDCProvider"
+ Effect: "Allow"
+ Action:
+ - "iam:CreateOpenIDConnectProvider"
+ - "iam:DeleteOpenIDConnectProvider"
+ - "iam:GetOpenIDConnectProvider"
+ - "iam:TagOpenIDConnectProvider"
+ - "iam:UntagOpenIDConnectProvider"
+ - "iam:ListOpenIDConnectProviderTags"
+ - "iam:AddClientIDToOpenIDConnectProvider"
+ - "iam:RemoveClientIDFromOpenIDConnectProvider"
+ - "iam:UpdateOpenIDConnectProviderThumbprint"
+ Resource:
+ - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/*.account.gov.uk
+ - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/*.account.gov.uk/
+ - Sid: "ListOIDCProvider"
+ Effect: "Allow"
+ Action:
+ - "iam:ListOpenIDConnectProviders"
+ Resource:
+ - "*"
+ - Sid: "RedshiftWriteConfig"
+ Effect: "Allow"
+ Action:
+ - "redshift-data:ExecuteStatement"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:*"
+ - !Sub "arn:${AWS::Partition}:redshift-serverless:${AWS::Region}:${AWS::AccountId}:*"
+ - Sid: "RedshiftReadConfig"
+ Effect: "Allow"
+ Action:
+ - "redshift-data:DescribeStatement"
+ - "redshift-data:GetStatementResult"
+ Resource:
+ - "*"
+ - Sid: "RDS"
+ Effect: "Allow"
+ Action:
+ - "rds:AddTagsToResource"
+ - "rds:CreateDBSecurityGroup"
+ - "rds:CreateDBInstance"
+ - "rds:CreateDBSubnetGroup"
+ - "rds:DeleteDBSubnetGroup"
+ - "rds:DescribeDBSubnetGroups"
+ - "rds:DescribeDBInstances"
+ - "rds:DeleteDBSecurityGroup"
+ - "rds:ListTagsForResource"
+ - "rds:ModifyDBInstance"
+ - "rds:ModifyDBSubnetGroup"
+ - "rds:RemoveTagsFromResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:rds:${AWS::Region}:${AWS::AccountId}:secgrp:pact*"
+ - !Sub "arn:${AWS::Partition}:rds:${AWS::Region}:${AWS::AccountId}:subgrp:pact*"
+ - !Sub "arn:${AWS::Partition}:rds:${AWS::Region}:${AWS::AccountId}:db:pact*"
+ - Sid: "ManageXRayResourcePolicy"
+ Effect: "Allow"
+ Action:
+ - "xray:DeleteResourcePolicy"
+ - "xray:ListResourcePolicies"
+ - "xray:PutResourcePolicy"
+ Resource:
+ - "*"
+ - Sid: "ManageScheduler"
+ Effect: "Allow"
+ Action:
+ - "scheduler:*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:scheduler:${AWS::Region}:${AWS::AccountId}:schedule/*/*"
+ - Sid: "ClusterCapacityProviders"
+ Effect: "Allow"
+ Action:
+ - "ecs:PutClusterCapacityProviders"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:cluster/*"
+
+ DeployPolicy7:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ # checkov:skip=CKV_AWS_111:test_create_star
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployPolicy7"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Sid: "ManageServiceCatalog"
+ Effect: "Allow"
+ Action:
+ - "servicecatalog:CreatePortfolio"
+ - "servicecatalog:CreatePortfolioShare"
+ - "servicecatalog:CreateProvisionedProductPlan"
+ - "servicecatalog:DeleteProvisionedProductPlan"
+ - "servicecatalog:Describe*"
+ - "servicecatalog:ExecuteProvisionedProduct*"
+ - "servicecatalog:List*"
+ - "servicecatalog:ProvisionProduct"
+ - "servicecatalog:UpdatePortfolio"
+ - "servicecatalog:DeletePortfolio"
+ - "servicecatalog:RejectPortfolioShare"
+ - "servicecatalog:AcceptPortfolioShare"
+ - "servicecatalog:TagResource"
+ - "servicecatalog:UpdateProvisionedProduct"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:catalog:${AWS::Region}:${AWS::AccountId}:portfolio/*"
+ - !Sub "arn:${AWS::Partition}:catalog:${AWS::Region}:${AWS::AccountId}:product/*"
+ - !Sub "arn:${AWS::Partition}:catalog:${AWS::Region}:${AWS::AccountId}:applications/*"
+ - !Sub "arn:${AWS::Partition}:catalog:${AWS::Region}:${AWS::AccountId}:attribute-groups/*"
+
+ - Sid: "ManageServiceCatalogShare"
+ Effect: "Allow"
+ Action:
+ - "servicecatalog:CreateTagOption"
+ - "servicecatalog:DescribePortfolioShareStatus"
+ - "servicecatalog:DescribeProvisionedProduct"
+ - "servicecatalog:DescribeTagOption"
+ - "servicecatalog:DeleteTagOption"
+ - "servicecatalog:ListTagOptions"
+ - "servicecatalog:ListLaunchPaths"
+ - "servicecatalog:UpdateTagOption"
+ - "servicecatalog:UntagResource"
+ - "servicecatalog:TerminateProvisionedProduct"
+ Resource:
+ - "*"
+ - Sid: "ManageServiceCatalogProvisionedProducts"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:DeleteStack"
+ - "cloudformation:DescribeStackEvents"
+ - "cloudformation:DescribeStacks"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/SC-${AWS::AccountId}-pp-*"
+ - Sid: "ClusterCapacityProviders"
+ Effect: "Allow"
+ Action:
+ - "ecs:PutClusterCapacityProviders"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:cluster/*"
+ - Sid: "ManageAdminStackSet"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:CreateStackInstances"
+ - "cloudformation:CreateStackSet"
+ - "cloudformation:DeleteStackInstances"
+ - "cloudformation:DeleteStackSet"
+ - "cloudformation:DescribeStackSet"
+ - "cloudformation:DescribeStackInstance"
+ - "cloudformation:DescribeStackSetOperation"
+ - "cloudformation:DetectStackSetDrift"
+ - "cloudformation:ListStackInstances"
+ - "cloudformation:ListStackSetOperationResults"
+ - "cloudformation:ListStackSetOperations"
+ - "cloudformation:StopStackSetOperation"
+ - "cloudformation:TagResource"
+ - "cloudformation:UntagResource"
+ - "cloudformation:UpdateStackInstances"
+ - "cloudformation:UpdateStackSet"
+ - "cloudformation:UntagResource"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:*:*:stackset*"
+ - !Sub "arn:${AWS::Partition}:cloudformation:*:*:type*"
+ - Sid: "ManageAdminStackSetGlobal"
+ Effect: "Allow"
+ Action:
+ - "cloudformation:GetTemplateSummary"
+ - "organizations:ListDelegatedAdministrators"
+ Resource:
+ - "*"
+
+ DeployRole:
+ Type: AWS::IAM::Role
+ Properties:
+ # The role name is designed to ensure that it cannot match a role name
+ # that a template is allowed to create/modify as otherwise the template
+ # could modify the role that is used to execute it leading to a privilege
+ # escalation vulnerability.
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "DeployRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ Service: "codebuild.amazonaws.com"
+ Action:
+ - "sts:AssumeRole"
+ ManagedPolicyArns:
+ - !Ref CodeBuildPolicy
+ - !Ref DeployPolicy1
+ - !Ref DeployPolicy2
+ - !Ref DeployPolicy3
+ - !Ref DeployPolicy4
+ - !Ref DeployPolicy5
+ - !Ref DeployPolicy6
+ - !Ref DeployPolicy7
+ - !Ref LockToRegionPolicy
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ DeployCodeBuildProject:
+ Type: AWS::CodeBuild::Project
+ Properties:
+ Name: !Sub "Deploy-${AWS::StackName}"
+ ServiceRole: !GetAtt DeployRole.Arn
+ Artifacts:
+ Type: "CODEPIPELINE"
+ Environment:
+ ComputeType: "BUILD_GENERAL1_SMALL"
+ Image: "aws/codebuild/amazonlinux2-x86_64-standard:3.0"
+ Type: "LINUX_CONTAINER"
+ Source:
+ Type: "CODEPIPELINE"
+ # Buildspec syntax: https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec-ref-syntax
+ BuildSpec:
+ Fn::Sub:
+ - |
+ version: 0.2
+ env:
+ shell: bash
+ exported-variables:
+ - METRICS_ARGS
+ # Phase transitions: https://docs.aws.amazon.com/codebuild/latest/userguide/view-build-details.html#view-build-details-phases
+ phases:
+ install:
+ commands:
+ - wget --no-verbose https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
+ - unzip -q aws-sam-cli-linux-x86_64.zip -d sam-installation
+ - ./sam-installation/install
+ - pip3 install "checkov==2.*"
+
+ pre_build:
+ on-failure: ${AbortOnCheckovFailure}
+ commands:
+ - mkdir -p reports/checkov/
+ - echo '\n' > reports/checkov/blank.xml
+ - checkov --framework cloudformation -f cf-template.yaml -o junitxml
+ --output-file-path=reports/checkov/; exit 0
+
+ build:
+ commands:
+ - |
+ echo "Deploying using devplatform sam-deploy-pipeline version: v2.52.4"
+
+ - |
+ stack_state="$(aws cloudformation describe-stacks --stack-name "${SAMStackName}" \
+ --query "Stacks[0].StackStatus" --output text || echo "NO_STACK")"
+
+ - |
+ if [[ "$stack_state" = "ROLLBACK_COMPLETE" ]]; then \
+ echo "Deleting stack ${SAMStackName} (in ROLLBACK_COMPLETE state) ..." \
+ && aws cloudformation delete-stack --stack-name="${SAMStackName}" \
+ && aws cloudformation wait stack-delete-complete --stack-name="${SAMStackName}"; \
+ fi
+
+ - |
+ inherited_tags="$(aws cloudformation describe-stacks \
+ --stack-name ${AWS::StackName} \
+ --query "Stacks[0].Tags[].[Key, Value]" \
+ --output text | awk '{ split($0, pairs, "\t"); print pairs[1]"=\""pairs[2]"\"" }' | tr "\n" " ")"
+
+ - |
+ provenance_tags="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[commitsha,repository]' --o text \
+ | awk '{ split($0, tags, "\t"); print "commitsha=\"" tags[1] "\" repository=\"" tags[2] "\"" }')"
+
+ - |
+ SKIP_CANARY_DEPLOYMENT="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[skipcanary]' --o text)"
+
+ - |
+ commitsha="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[commitsha]' --o text)"
+
+ - |
+ repository="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[repository]' --o text)"
+
+ - |
+ mergetime="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[mergetime]' --o text \
+ | tr " " ",")"
+
+ - |
+ echo "Inherited Tags: $inherited_tags"
+
+ - |
+ echo "Provenance Tags: $provenance_tags"
+
+ - |
+ echo "Skip canary flag: $SKIP_CANARY_DEPLOYMENT"
+
+ - |
+ chmod +x "$CODEBUILD_SRC_DIR_GrafanaScripts/grafana-annotations.sh"
+
+ - |
+ chmod +x "$CODEBUILD_SRC_DIR_DynatraceScripts/dynatrace-metrics.sh"
+
+ - |
+ shortsha=${!provenance_tags:11:7}
+ if [[ $shortsha = *[[:space:]]* ]]; then
+ shortsha=None
+ fi
+
+ - |
+ echo "Short SHA: $shortsha"
+
+ - |
+ ARGS="create \
+ ${!shortsha} \
+ ${Environment} \
+ ${SAMStackName} \
+ ${AWS::AccountId} \
+ v2.52.4"
+
+ - |
+ ANNOTATION_ID=$("$CODEBUILD_SRC_DIR_GrafanaScripts/grafana-annotations.sh" $ARGS)
+
+ - |
+ METRICS_ARGS="create \
+ --repository ${!repository} \
+ --commit-sha ${!commitsha} \
+ --merge-time ${!mergetime} \
+ --environment ${Environment} \
+ --sam-stack-name ${SAMStackName} \
+ --account-id ${AWS::AccountId} \
+ --stage "deploy" \
+ --start-time-ms $CODEBUILD_START_TIME \
+ --pipeline-version v2.52.4"
+
+ - |
+ if [[ "${CodeSigningConfigArn}" == "none" ]]; then \
+ PARAMETER_OVERRIDES="Environment=${Environment} VpcStackName=${VpcStackName} PermissionsBoundary=${AppPermissionsBoundaryArn} TestRoleArn=${TestRoleArn}"; else \
+ PARAMETER_OVERRIDES="Environment=${Environment} VpcStackName=${VpcStackName} CodeSigningConfigArn=${CodeSigningConfigArn} PermissionsBoundary=${AppPermissionsBoundaryArn} TestRoleArn=${TestRoleArn}"; \
+ fi
+
+ - |
+ if [[ ($SKIP_CANARY_DEPLOYMENT -eq 0) && ("${ECSCanaryDeployment}" != "None") ]]; then \
+ PARAMETER_OVERRIDES="$PARAMETER_OVERRIDES DeploymentStrategy=${ECSCanaryDeployment}"; \
+ fi
+
+ - |
+ if [[ ($SKIP_CANARY_DEPLOYMENT -eq 1) && ("${ECSCanaryDeployment}" != "None") ]]; then \
+ PARAMETER_OVERRIDES="$PARAMETER_OVERRIDES DeploymentStrategy=CodeDeployDefault.ECSAllAtOnce"; \
+ fi
+
+ - |
+ if [[ ($SKIP_CANARY_DEPLOYMENT -eq 0) && ("${LambdaCanaryDeployment}" != "None") ]]; then \
+ PARAMETER_OVERRIDES="$PARAMETER_OVERRIDES LambdaDeploymentPreference=${LambdaCanaryDeployment}"; \
+ fi
+
+ - |
+ if [[ ($SKIP_CANARY_DEPLOYMENT -eq 1) && ("${LambdaCanaryDeployment}" != "None") ]]; then \
+ PARAMETER_OVERRIDES="$PARAMETER_OVERRIDES LambdaDeploymentPreference=AllAtOnce"; \
+ fi
+
+ - |
+ if AWS_RETRY_MODE=adaptive AWS_MAX_ATTEMPTS=8 sam deploy \
+ --template-file cf-template.yaml \
+ --s3-bucket "${PipelineBucket}" \
+ --stack-name "${SAMStackName}" \
+ --capabilities ${Capabilities} \
+ --no-confirm-changeset \
+ --no-fail-on-empty-changeset \
+ --parameter-overrides $PARAMETER_OVERRIDES \
+ --region ${AWS::Region} \
+ --tags "$inherited_tags is-pipeline-deployment=True $provenance_tags"; then \
+ "$CODEBUILD_SRC_DIR_GrafanaScripts/grafana-annotations.sh" update "completed" ${Environment} ${SAMStackName} $ANNOTATION_ID; else \
+ "$CODEBUILD_SRC_DIR_GrafanaScripts/grafana-annotations.sh" update "rolled back" ${Environment} ${SAMStackName} $ANNOTATION_ID; exit 1; fi
+
+ finally:
+ # This reads out the two dimensions from the pipeline,
+ # and publishes them to CloudWatch metrics as a release under the
+ # DevPlatform/SecurePipelines Namespace
+ - |
+ echo "build succeeded=$CODEBUILD_BUILD_SUCCEEDING"
+ - |
+ "$CODEBUILD_SRC_DIR_DynatraceScripts/dynatrace-metrics.sh" $METRICS_ARGS \
+ --build-success $CODEBUILD_BUILD_SUCCEEDING
+ - |
+ COMMITSHA="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.commitsha' --o text)"
+ - |
+ aws cloudwatch put-metric-data --namespace DevPlatform/SecurePipelines/Releases \
+ --metric-name CodeBuildSuccess \
+ --unit None \
+ --value $CODEBUILD_BUILD_SUCCEEDING \
+ --dimensions stack_name=${SAMStackName},environment=${Environment},commitsha=$COMMITSHA
+
+ reports:
+ checkov-reports:
+ files:
+ - "reports/checkov/*.xml"
+ file-format: "JUNITXML"
+
+ - CodeSigningConfigArn: !If
+ - SigningProfile
+ - !Ref CodeSigningConfig
+ - "none"
+ AppPermissionsBoundaryArn: !If
+ - UseProgrammaticPermissionsBoundary
+ - !Ref AppProgrammaticPermissionsBoundary
+ - !Ref AppPermissionsBoundary
+ ArtifactBucket: !If
+ - CreateGitHubActionsResources
+ - !Ref GitHubArtifactSourceBucket
+ - !Select [5, !Split [':', !Ref ArtifactSourceBucketArn]]
+ TestRoleArn: !If
+ - CreateTestAction
+ - !GetAtt TestRole.Arn
+ - "none"
+ AbortOnCheckovFailure: !Ref AbortOnCheckovFailure
+ Capabilities: !If
+ - DeployECSCanaryStack
+ - CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND
+ - CAPABILITY_NAMED_IAM
+ ECSCanaryDeployment: !Ref ECSCanaryDeployment
+ LambdaCanaryDeployment: !Ref LambdaCanaryDeployment
+ SecondarySources:
+ - Type: S3
+ Location: "template-bucket-templatebucket-35qbug5k1irh/sam-deploy-pipeline/grafana-scripts-v2.zip"
+ SourceIdentifier: GrafanaScripts
+ - Type: S3
+ Location: "template-bucket-templatebucket-35qbug5k1irh/sam-deploy-pipeline/dynatrace-scripts.zip"
+ SourceIdentifier: DynatraceScripts
+ SecondarySourceVersions:
+ - SourceIdentifier: GrafanaScripts
+ SourceVersion: "iF__IZFI8spqJ8X.nW_6_JWHn.Wa0Cxf"
+ - SourceIdentifier: DynatraceScripts
+ SourceVersion: "TVSIGNYbCkHukYA0jtmABZNwITf_oTH4"
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployCodeBuildProject"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ DeployCodeBuildProjectLogGroup:
+ Type: AWS::Logs::LogGroup
+ Properties:
+ KmsKeyId: !GetAtt LogsKmsKey.Arn
+ LogGroupName: !Sub "/aws/codebuild/${DeployCodeBuildProject}"
+ RetentionInDays: !Ref LogRetentionDays
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeployCodeBuildProjectLogGroup"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # Validate (CodeBuild)
+ #
+
+ ValidateSignaturePolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Condition: CreateTestContainerSignatureValidateStage
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "ValidateSignaturePolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - "logs:DescribeLogGroups"
+ - "logs:DescribeLogStreams"
+ - "logs:DescribeMetricFilters"
+ - "logs:FilterLogEvents"
+ - "logs:GetLogEvents"
+ - "logs:StartQuery"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*"
+ - Effect: "Allow"
+ Action:
+ - "logs:DescribeQueries"
+ - "logs:DescribeQueryDefinitions"
+ - "logs:GetLogDelivery"
+ - "logs:GetLogRecord"
+ - "logs:GetQueryResults"
+ - "logs:ListLogDeliveries"
+ - "logs:StopQuery"
+ - "logs:TestMetricFilter"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "ecr:BatchCheckLayerAvailability"
+ - "ecr:BatchGetImage"
+ - "ecr:GetDownloadUrlForLayer"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ecr:${AWS::Region}:*:repository/*"
+ - Effect: "Allow"
+ Action:
+ - "ecr:GetAuthorizationToken"
+ Resource:
+ - "*"
+ - Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Verify"
+ Resource:
+ - !Ref ContainerSignerKmsKeyArn
+
+ ValidateSignatureRole:
+ Type: AWS::IAM::Role
+ Condition: CreateTestContainerSignatureValidateStage
+ Properties:
+ # The role name is designed to ensure that it cannot match a role name
+ # that a template is allowed to create/modify as otherwise the template
+ # could modify the role that is used to execute it leading to a privilege
+ # escalation vulnerability.
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "ValidateSignatureRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ Service: "codebuild.amazonaws.com"
+ Action:
+ - "sts:AssumeRole"
+ ManagedPolicyArns:
+ - !Ref CodeBuildPolicy
+ - !Ref ValidateSignaturePolicy
+ - !Ref LockToRegionPolicy
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-TestRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ ValidateSignatureCodeBuildProject:
+ Type: AWS::CodeBuild::Project
+ Condition: CreateTestContainerSignatureValidateStage
+ Properties:
+ Name: !Sub "Validate-${AWS::StackName}"
+ ServiceRole: !GetAtt ValidateSignatureRole.Arn
+ Artifacts:
+ Type: "CODEPIPELINE"
+ Environment:
+ ComputeType: "BUILD_GENERAL1_SMALL"
+ Image: "aws/codebuild/amazonlinux2-x86_64-standard:3.0"
+ Type: "LINUX_CONTAINER"
+ Source:
+ Type: "CODEPIPELINE"
+ BuildSpec:
+ Fn::Sub:
+ - |
+ version: 0.2
+ env:
+ shell: bash
+
+ phases:
+ install:
+ commands:
+ - wget --no-verbose "https://github.com/sigstore/cosign/releases/download/v1.9.0/cosign-linux-amd64"
+ - mv cosign-linux-amd64 /usr/local/bin/cosign
+ - chmod +x /usr/local/bin/cosign
+
+ pre_build:
+ commands:
+ - |
+ registryUri=$(echo ${TestImage} | cut -d'/' -f1)
+ - |
+ aws ecr get-login-password --region ${AWS::Region} \
+ | cosign login $registryUri \
+ --username AWS \
+ --password-stdin
+
+ build:
+ commands:
+ - |
+ echo "Deploying using devplatform sam-deploy-pipeline version: v2.52.4"
+
+ - |
+ cosign verify --key awskms:///${ContainerSignerKmsKeyArn} ${TestImage}
+
+ cache:
+ paths:
+ - /usr/local/bin/*
+
+ - ContainerSignerKmsKeyArn: !Ref ContainerSignerKmsKeyArn
+ TestImage: !Sub "${TestImageRepositoryUri}:latest"
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-ValidateSignatureCodeBuildProject"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ ValidateSignatureCodeBuildProjectLogGroup:
+ Type: AWS::Logs::LogGroup
+ Condition: CreateTestContainerSignatureValidateStage
+ Properties:
+ KmsKeyId: !GetAtt LogsKmsKey.Arn
+ LogGroupName: !Sub "/aws/codebuild/${ValidateSignatureCodeBuildProject}"
+ RetentionInDays: !Ref LogRetentionDays
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-ValidateSignatureCodeBuildProjectLogGroup"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # Traffic Test (CodeBuild)
+ #
+
+ TrafficTestPolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Condition: CreateTrafficTest
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "TrafficTestPolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - "cloudformation:DescribeStacks"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${SAMStackName}/*"
+ - Effect: "Allow"
+ Action:
+ - "ssm:GetParameter*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/tests/${SAMStackName}/*"
+ - !If
+ - NotProduction
+ - Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ Resource:
+ - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*"
+ - !Ref AWS::NoValue
+ - !If
+ - NotProduction
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:UpdateItem"
+ - "dynamodb:Query"
+ - "dynamodb:DeleteItem"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:*"
+ - !Ref AWS::NoValue
+ - !If
+ - CreateCustomKMSKeyPolicy
+ - Sid: "CustomKMSKeySigning"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Decrypt"
+ - "kms:Verify"
+ - "kms:GenerateDataKey"
+ Resource: !Ref "CustomKmsKeyArns"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "logs:DescribeLogGroups"
+ - "logs:DescribeLogStreams"
+ - "logs:DescribeMetricFilters"
+ - "logs:FilterLogEvents"
+ - "logs:GetLogEvents"
+ - "logs:StartQuery"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*"
+ - Effect: "Allow"
+ Action:
+ - "logs:DescribeQueries"
+ - "logs:DescribeQueryDefinitions"
+ - "logs:GetLogDelivery"
+ - "logs:GetLogRecord"
+ - "logs:GetQueryResults"
+ - "logs:ListLogDeliveries"
+ - "logs:StopQuery"
+ - "logs:TestMetricFilter"
+ Resource:
+ - "*"
+ - Sid: "AccessSourceArtifacts"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ Resource:
+ - !If
+ - CreateGitHubActionsResources
+ - !GetAtt GitHubArtifactSourceBucket.Arn
+ - !Ref ArtifactSourceBucketArn
+ - !If
+ - CreateGitHubActionsResources
+ - !Sub "${GitHubArtifactSourceBucket.Arn}/*"
+ - !Sub "${ArtifactSourceBucketArn}/*"
+ - Effect: "Allow"
+ Action:
+ - "sns:Publish"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*"
+ - Effect: "Allow"
+ Action:
+ - "sqs:SendMessage"
+ - "sqs:DeleteMessage"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:*"
+ - Sid: "TemplateBucketAccess"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetObjectTagging"
+ - "s3:ListBucket"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh"
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh/*"
+ - !Sub "arn:${AWS::Partition}:s3:::template-storage-templatebucket-1upzyw6v9cs42"
+ - !Sub "arn:${AWS::Partition}:s3:::template-storage-templatebucket-1upzyw6v9cs42/*"
+ - Sid: "ObservabilitySecretsManager"
+ Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecrets" # pragma: allowlist secret
+ Resource:
+ - "arn:aws:secretsmanager:eu-west-2:216552277552:secret:*" # pragma: allowlist secret
+ - Sid: "ObservabilityKMS"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Decrypt"
+ - "kms:Verify"
+ Resource:
+ - "arn:aws:kms:eu-west-2:216552277552:key/*"
+
+ TrafficTestRole:
+ Type: AWS::IAM::Role
+ Condition: CreateTrafficTest
+ Properties:
+ # The role name is designed to ensure that it cannot match a role name
+ # that a template is allowed to create/modify as otherwise the template
+ # could modify the role that is used to execute it leading to a privilege
+ # escalation vulnerability.
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "TrafficTestRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ Service: "codebuild.amazonaws.com"
+ Action:
+ - "sts:AssumeRole"
+ ManagedPolicyArns:
+ - !Ref CodeBuildPolicy
+ - !Ref TrafficTestPolicy
+ - !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
+ - !Ref LockToRegionPolicy
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-TestRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ TrafficTestCodeBuildProject:
+ Type: AWS::CodeBuild::Project
+ Condition: CreateTrafficTest
+ Properties:
+ Name: !Sub "TrafficTest-${AWS::StackName}"
+ ServiceRole: !GetAtt TrafficTestRole.Arn
+ Artifacts:
+ Type: "NO_ARTIFACTS"
+ Environment:
+ ComputeType: !Ref TestComputeType
+ Image: !Sub "${TrafficTestImageRepositoryUri}:latest"
+ Type: "LINUX_CONTAINER"
+ ImagePullCredentialsType: "SERVICE_ROLE"
+ Source:
+ Type: "NO_SOURCE"
+ BuildSpec: !Sub |
+ version: 0.2
+
+ phases:
+ build:
+ commands:
+ - |
+ echo "Deploying using devplatform sam-deploy-pipeline version: v2.52.4"
+ - |
+ aws cloudformation describe-stacks --stack-name "${SAMStackName}" --region "${AWS::Region}" --query 'Stacks[0].Outputs[].{key: OutputKey, value: OutputValue}' --output text > cf-output.txt
+ - |
+ eval $(awk '{ printf("export CFN_%s=\"%s\"\n", $1, $2) }' cf-output.txt)
+ - export SAM_STACK_NAME="${SAMStackName}"
+ - /run-tests.sh
+
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-TrafficTestCodeBuildProject"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ TrafficTestCodeBuildProjectLogGroup:
+ Type: AWS::Logs::LogGroup
+ Condition: CreateTrafficTest
+ Properties:
+ KmsKeyId: !GetAtt LogsKmsKey.Arn
+ LogGroupName: !Sub "/aws/codebuild/${TrafficTestCodeBuildProject}"
+ RetentionInDays: !Ref LogRetentionDays
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-TrafficTestCodeBuildProjectLogGroup"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # Test (CodeBuild)
+ #
+
+ TestPolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Condition: CreateTestAction
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "TestPolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Action:
+ - "cloudformation:DescribeStacks"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${SAMStackName}/*"
+ - Effect: "Allow"
+ Action:
+ - "ssm:GetParameter*"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/tests/${SAMStackName}/*"
+ - !If
+ - NotProduction
+ - Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ Resource:
+ - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*"
+ - !Ref AWS::NoValue
+ - !If
+ - NotProduction
+ - Effect: "Allow"
+ Action:
+ - "dynamodb:UpdateItem"
+ - "dynamodb:Query"
+ - "dynamodb:DeleteItem"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:*"
+ - !Ref AWS::NoValue
+ - !If
+ - CreateCustomKMSKeyPolicy
+ - Sid: "CustomKMSKeySigning"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Decrypt"
+ - "kms:Verify"
+ - "kms:GenerateDataKey"
+ Resource: !Ref "CustomKmsKeyArns"
+ - !Ref AWS::NoValue
+ - Effect: "Allow"
+ Action:
+ - "logs:DescribeLogGroups"
+ - "logs:DescribeLogStreams"
+ - "logs:DescribeMetricFilters"
+ - "logs:FilterLogEvents"
+ - "logs:GetLogEvents"
+ - "logs:StartQuery"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
+ - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*"
+ - Effect: "Allow"
+ Action:
+ - "logs:DescribeQueries"
+ - "logs:DescribeQueryDefinitions"
+ - "logs:GetLogDelivery"
+ - "logs:GetLogRecord"
+ - "logs:GetQueryResults"
+ - "logs:ListLogDeliveries"
+ - "logs:StopQuery"
+ - "logs:TestMetricFilter"
+ Resource:
+ - "*"
+ - Sid: "AccessSourceArtifacts"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ Resource:
+ - !If
+ - CreateGitHubActionsResources
+ - !GetAtt GitHubArtifactSourceBucket.Arn
+ - !Ref ArtifactSourceBucketArn
+ - !If
+ - CreateGitHubActionsResources
+ - !Sub "${GitHubArtifactSourceBucket.Arn}/*"
+ - !Sub "${ArtifactSourceBucketArn}/*"
+ - Effect: "Allow"
+ Action:
+ - "sns:Publish"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*"
+ - Effect: "Allow"
+ Action:
+ - "sqs:SendMessage"
+ - "sqs:PurgeQueue"
+ - "sqs:ReceiveMessage"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:*"
+ - Sid: "TemplateBucketAccess"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetObjectTagging"
+ - "s3:ListBucket"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh"
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh/*"
+ - Sid: "ObservabilitySecretsManager"
+ Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecrets" # pragma: allowlist secret
+ Resource:
+ - "arn:aws:secretsmanager:eu-west-2:216552277552:secret:*" # pragma: allowlist secret
+ - Sid: "ObservabilityKMS"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Decrypt"
+ - "kms:Verify"
+ Resource:
+ - "arn:aws:kms:eu-west-2:216552277552:key/*"
+
+ VPCTestPolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Condition: CreateVPCConfigurationForTestContainer
+ # checkov:skip=CKV_AWS_111:states:The mix of VPC permissions don't take a resource
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "VPCTestPolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Action:
+ - ec2:CreateNetworkInterface
+ - ec2:DescribeDhcpOptions
+ - ec2:DescribeNetworkInterfaces
+ - ec2:DeleteNetworkInterface
+ - ec2:DescribeSubnets
+ - ec2:DescribeSecurityGroups
+ - ec2:DescribeVpcs
+ Resource:
+ - "*"
+ - Effect: Allow
+ Action:
+ - ec2:CreateNetworkInterfacePermission
+ Resource: !Sub "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:network-interface/*"
+ Condition:
+ StringEquals:
+ ec2:AuthorizedService: codebuild.amazonaws.com
+ ArnEquals:
+ ec2:Subnet:
+ - Fn::Sub:
+ - "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${SubnetId}"
+ - SubnetId:
+ Fn::ImportValue:
+ Fn::Sub: "${VpcStackName}-ProtectedSubnetIdA"
+ - Fn::Sub:
+ - "arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${SubnetId}"
+ - SubnetId:
+ Fn::ImportValue:
+ Fn::Sub: "${VpcStackName}-ProtectedSubnetIdB"
+
+
+ TestRole:
+ Type: AWS::IAM::Role
+ Condition: CreateTestAction
+ Properties:
+ # The role name is designed to ensure that it cannot match a role name
+ # that a template is allowed to create/modify as otherwise the template
+ # could modify the role that is used to execute it leading to a privilege
+ # escalation vulnerability.
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "TestRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ Service: "codebuild.amazonaws.com"
+ Action:
+ - "sts:AssumeRole"
+ ManagedPolicyArns:
+ - !Ref CodeBuildPolicy
+ - !Ref TestPolicy
+ - !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
+ - !Ref LockToRegionPolicy
+ - !If
+ - CreateVPCConfigurationForTestContainer
+ - !Ref VPCTestPolicy
+ - !Ref AWS::NoValue
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-TestRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ TestCodeBuildProject:
+ Type: AWS::CodeBuild::Project
+ Condition: CreateTestAction
+ Properties:
+ Name: !Sub "Test-${AWS::StackName}"
+ ServiceRole: !GetAtt TestRole.Arn
+ Artifacts:
+ Type: "CODEPIPELINE"
+ Environment:
+ ComputeType: !Ref TestComputeType
+ Image: !Sub "${TestImageRepositoryUri}:latest"
+ Type: "LINUX_CONTAINER"
+ ImagePullCredentialsType: "SERVICE_ROLE"
+ VpcConfig:
+ !If
+ - CreateVPCConfigurationForTestContainer
+ - SecurityGroupIds:
+ - !GetAtt TestContainerSecurityGroup.GroupId
+ Subnets:
+ - Fn::ImportValue: !Sub "${VpcStackName}-ProtectedSubnetIdA"
+ - Fn::ImportValue: !Sub "${VpcStackName}-ProtectedSubnetIdB"
+ VpcId:
+ Fn::ImportValue: !Sub "${VpcStackName}-VpcId"
+ - !Ref AWS::NoValue
+ Source:
+ Type: "CODEPIPELINE"
+ BuildSpec:
+ Fn::Sub:
+ - |
+ version: 0.2
+
+ env:
+ variables:
+ TEST_REPORT_DIR: results
+ COVERAGE_REPORT_DIR: coverage
+ exported-variables:
+ - METRICS_ARGS
+
+ phases:
+ pre_build:
+ commands:
+ - mkdir -p "$TEST_REPORT_DIR"
+ - mkdir -p "$COVERAGE_REPORT_DIR"
+ - echo '' > coverage/clover.xml
+
+ build:
+ commands:
+ - |
+ echo "Deploying using devplatform sam-deploy-pipeline version: v2.52.4"
+
+ - |
+ commitsha="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[commitsha]' --o text)"
+
+ - |
+ repository="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[repository]' --o text)"
+
+ - |
+ mergetime="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[mergetime]' --o text \
+ | tr " " ",")"
+
+ - |
+ chmod +x "$CODEBUILD_SRC_DIR_DynatraceScripts/dynatrace-metrics.sh"
+
+ - |
+ METRICS_ARGS="create \
+ -r ${!repository} \
+ -c ${!commitsha} \
+ -m ${!mergetime} \
+ -e ${Environment} \
+ -s ${SAMStackName} \
+ -a ${AWS::AccountId} \
+ -l "test" \
+ -t $CODEBUILD_START_TIME \
+ -p v2.52.4"
+
+ - |
+ aws cloudformation describe-stacks --stack-name "${SAMStackName}" --region "${AWS::Region}" --query 'Stacks[0].Outputs[].{key: OutputKey, value: OutputValue}' --output text > cf-output.txt
+
+ - |
+ eval $(awk '{ printf("export CFN_%s=\"%s\"\n", $1, $2) }' cf-output.txt)
+
+ - export TEST_REPORT_ABSOLUTE_DIR="$(pwd)/$TEST_REPORT_DIR"
+ - export COVERAGE_REPORT_ABSOLUTE_DIR="$(pwd)/$COVERAGE_REPORT_DIR"
+ - export TEST_ENVIRONMENT="${Environment}"
+ - export SAM_STACK_NAME="${SAMStackName}"
+ - /run-tests.sh
+
+ finally:
+ - |
+ echo "build succeeded=$CODEBUILD_BUILD_SUCCEEDING"
+ - |
+ echo "METRICS_ARGS=$METRICS_ARGS"
+ - |
+ "$CODEBUILD_SRC_DIR_DynatraceScripts/dynatrace-metrics.sh" $METRICS_ARGS \
+ -b $CODEBUILD_BUILD_SUCCEEDING || exit 0
+
+ reports:
+ TestReports:
+ files:
+ - results/**/*
+ file-format: ${TestReportFormat}
+ CoverageReports:
+ files:
+ - coverage/**/*
+ file-format: ${TestCoverageReportFormat}
+ - ArtifactBucket: !If
+ - CreateGitHubActionsResources
+ - !Ref GitHubArtifactSourceBucket
+ - !Select [5, !Split [':', !Ref ArtifactSourceBucketArn]]
+ SecondarySources:
+ - Type: S3
+ Location: "template-bucket-templatebucket-35qbug5k1irh/sam-deploy-pipeline/dynatrace-scripts.zip"
+ SourceIdentifier: DynatraceScripts
+ SecondarySourceVersions:
+ - SourceIdentifier: DynatraceScripts
+ SourceVersion: "TVSIGNYbCkHukYA0jtmABZNwITf_oTH4"
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-TestCodeBuildProject"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ TestCodeBuildProjectLogGroup:
+ Type: AWS::Logs::LogGroup
+ Condition: CreateTestAction
+ Properties:
+ KmsKeyId: !GetAtt LogsKmsKey.Arn
+ LogGroupName: !Sub "/aws/codebuild/${TestCodeBuildProject}"
+ RetentionInDays: !Ref LogRetentionDays
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-TestCodeBuildProjectLogGroup"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # Promotion (CodeBuild)
+ #
+
+ PromotionPolicy:
+ Condition: CreatePromoteStage
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "PromotionPolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Resource:
+ - !If
+ - CreateGitHubActionsResources
+ - !GetAtt GitHubArtifactSourceBucket.Arn
+ - !Ref ArtifactSourceBucketArn
+ - !If
+ - CreateGitHubActionsResources
+ - !Sub "${GitHubArtifactSourceBucket.Arn}/*"
+ - !Sub "${ArtifactSourceBucketArn}/*"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetBucketVersioning"
+ - "s3:ListBucket"
+ - "s3:ListBucketVersions"
+ Effect: "Allow"
+ - Resource:
+ - !GetAtt ArtifactPromotionBucket.Arn
+ - !Sub "${ArtifactPromotionBucket.Arn}/*"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetObjectTagging"
+ - "s3:PutObject"
+ - "s3:PutObjectAcl"
+ - "s3:ListBucket"
+ Effect: "Allow"
+ - Sid: "TemplateBucketAccess"
+ Effect: "Allow"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetObjectTagging"
+ - "s3:ListBucket"
+ Resource:
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh"
+ - !Sub "arn:${AWS::Partition}:s3:::template-bucket-templatebucket-35qbug5k1irh/*"
+ - Sid: "ObservabilitySecretsManager"
+ Effect: "Allow"
+ Action:
+ - "secretsmanager:GetSecretValue" # pragma: allowlist secret
+ - "secretsmanager:ListSecrets" # pragma: allowlist secret
+ Resource:
+ - "arn:aws:secretsmanager:eu-west-2:216552277552:secret:*" # pragma: allowlist secret
+ - Sid: "ObservabilityKMS"
+ Effect: "Allow"
+ Action:
+ - "kms:DescribeKey"
+ - "kms:GetPublicKey"
+ - "kms:Decrypt"
+ - "kms:Verify"
+ Resource:
+ - "arn:aws:kms:eu-west-2:216552277552:key/*"
+
+ PromotionRole:
+ Condition: CreatePromoteStage
+ Type: AWS::IAM::Role
+ Properties:
+ # The role name is designed to ensure that it cannot match a role name
+ # that a template is allowed to create/modify as otherwise the template
+ # could modify the role that is used to execute it leading to a privilege
+ # escalation vulnerability.
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "PromotionRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ Service: "codebuild.amazonaws.com"
+ Action:
+ - "sts:AssumeRole"
+ ManagedPolicyArns:
+ - !Ref CodeBuildPolicy
+ - !Ref PromotionPolicy
+ - !Ref LockToRegionPolicy
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "PromotionRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ PromotionCodeBuildProject:
+ Condition: CreatePromoteStage
+ Type: AWS::CodeBuild::Project
+ Properties:
+ Name: !Sub "Promotion-${AWS::StackName}"
+ ServiceRole: !GetAtt PromotionRole.Arn
+ Artifacts:
+ Type: "CODEPIPELINE"
+ Environment:
+ ComputeType: "BUILD_GENERAL1_SMALL"
+ Image: "aws/codebuild/amazonlinux2-x86_64-standard:3.0"
+ Type: "LINUX_CONTAINER"
+ Source:
+ Type: "CODEPIPELINE"
+ BuildSpec: !Sub
+ - |
+ version: 0.2
+
+ env:
+ variables:
+ PROMOTION_BUCKET_NAME: "${PromotionBucketName}"
+ SOURCE_ARTIFACT_BUCKET_NAME: "${ArtifactBucket}"
+ exported-variables:
+ - METRICS_ARGS
+
+ phases:
+ install:
+ runtime-versions:
+ python: 3.x
+
+ pre_build:
+ commands:
+ - pip install -r "$CODEBUILD_SRC_DIR_PromotionScript/requirements.txt"
+
+ build:
+ commands:
+ - |
+ echo "Deploying using devplatform sam-deploy-pipeline version: v2.52.4"
+
+ - |
+ commitsha="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[commitsha]' --o text)"
+
+ - |
+ repository="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[repository]' --o text)"
+
+ - |
+ mergetime="$(aws s3api head-object \
+ --version-id $CODEBUILD_RESOLVED_SOURCE_VERSION \
+ --bucket ${ArtifactBucket} \
+ --key template.zip \
+ --query='Metadata.[mergetime]' --o text \
+ | tr " " ",")"
+
+ - |
+ METRICS_ARGS="create \
+ --repository ${!repository} \
+ --commit-sha ${!commitsha} \
+ --merge-time ${!mergetime} \
+ --environment ${Environment} \
+ --sam-stack-name ${SAMStackName} \
+ --account-id ${AWS::AccountId} \
+ --stage "promote" \
+ --start-time-ms $CODEBUILD_START_TIME \
+ --pipeline-version v2.52.4"
+
+ - |
+ chmod +x "$CODEBUILD_SRC_DIR_DynatraceScripts/dynatrace-metrics.sh"
+
+ - PYTHONPATH=$CODEBUILD_SRC_DIR_PromotionScript python -c "import promote; promote.main('$PROMOTION_BUCKET_NAME', '$SOURCE_ARTIFACT_BUCKET_NAME', '$CODEBUILD_RESOLVED_SOURCE_VERSION')"
+
+ finally:
+ - |
+ echo "build succeeded=$CODEBUILD_BUILD_SUCCEEDING"
+ - |
+ "$CODEBUILD_SRC_DIR_DynatraceScripts/dynatrace-metrics.sh" $METRICS_ARGS \
+ --build-success $CODEBUILD_BUILD_SUCCEEDING
+
+ - PromotionBucketName: !Select [5, !Split [':', !GetAtt ArtifactPromotionBucket.Arn]]
+ ArtifactBucket: !If
+ - CreateGitHubActionsResources
+ - !Ref GitHubArtifactSourceBucket
+ - !Select [ 5, !Split [ ':', !Ref ArtifactSourceBucketArn ] ]
+ SecondarySources:
+ - Type: S3
+ Location: "template-bucket-templatebucket-35qbug5k1irh/sam-deploy-pipeline/dynatrace-scripts.zip"
+ SourceIdentifier: DynatraceScripts
+ - Type: S3
+ Location: "template-bucket-templatebucket-35qbug5k1irh/sam-deploy-pipeline/promotion_sources.zip"
+ SourceIdentifier: PromotionScript
+ SecondarySourceVersions:
+ - SourceIdentifier: DynatraceScripts
+ SourceVersion: "TVSIGNYbCkHukYA0jtmABZNwITf_oTH4"
+ - SourceIdentifier: PromotionScript
+ SourceVersion: "dyg4lZ6HyUp1jMyRxMZqw4fStm_1DlSE"
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "PromotionCodeBuildProject"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ PromotionCodeBuildProjectLogGroup:
+ Type: AWS::Logs::LogGroup
+ Condition: CreatePromoteStage
+ Properties:
+ KmsKeyId: !GetAtt LogsKmsKey.Arn
+ LogGroupName: !Sub "/aws/codebuild/${PromotionCodeBuildProject}"
+ RetentionInDays: !Ref LogRetentionDays
+ Tags:
+ - Key: "Name"
+ Value: !Sub "${AWS::StackName}-PromotionCodeBuildProjectLogGroup"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # Pipeline
+ #
+
+ PipelineBucket:
+ Type: AWS::S3::Bucket
+ Properties:
+ LifecycleConfiguration:
+ Rules:
+ - Id: artifactBucketExpiry
+ Status: Enabled
+ ExpirationInDays: 180
+ VersioningConfiguration:
+ Status: "Enabled"
+ PublicAccessBlockConfiguration:
+ BlockPublicAcls: true
+ BlockPublicPolicy: true
+ IgnorePublicAcls: true
+ RestrictPublicBuckets: true
+ LoggingConfiguration:
+ DestinationBucketName: !Ref S3AccessLogsBucket
+ LogFilePrefix: "pipeline/"
+ BucketEncryption:
+ ServerSideEncryptionConfiguration:
+ - ServerSideEncryptionByDefault:
+ SSEAlgorithm: "AES256"
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "pipelinebucket"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ PipelineBucketPolicy:
+ Type: AWS::S3::BucketPolicy
+ Properties:
+ Bucket: !Ref PipelineBucket
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Deny"
+ Resource:
+ - !GetAtt PipelineBucket.Arn
+ - !Sub "${PipelineBucket.Arn}/*"
+ Principal: "*"
+ Action: "*"
+ Condition:
+ Bool:
+ "aws:SecureTransport": false
+
+ CodePipelinePolicy:
+ Type: AWS::IAM::ManagedPolicy
+ Properties:
+ ManagedPolicyName:
+ Fn::Join:
+ - "-"
+ - - !Ref AWS::StackName
+ - "CodePipelinePolicy"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Resource:
+ - !If
+ - CreateGitHubActionsResources
+ - !GetAtt GitHubArtifactSourceBucket.Arn
+ - !Ref ArtifactSourceBucketArn
+ - !If
+ - CreateGitHubActionsResources
+ - !Sub "${GitHubArtifactSourceBucket.Arn}/*"
+ - !Sub "${ArtifactSourceBucketArn}/*"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetBucketVersioning"
+ Effect: "Allow"
+ - Resource:
+ - !GetAtt PipelineBucket.Arn
+ - !Sub "${PipelineBucket.Arn}/*"
+ Action:
+ - "s3:GetObject"
+ - "s3:GetObjectVersion"
+ - "s3:GetBucketVersioning"
+ - "s3:PutObjectAcl"
+ - "s3:PutObject"
+ Effect: "Allow"
+ - Resource:
+ - !GetAtt DeployCodeBuildProject.Arn
+ - !If [CreateTestContainerSignatureValidateStage, !GetAtt ValidateSignatureCodeBuildProject.Arn, !Ref "AWS::NoValue"]
+ - !If [CreateTestAction, !GetAtt TestCodeBuildProject.Arn, !Ref "AWS::NoValue"]
+ - !If [CreateTrafficTest, !GetAtt TrafficTestCodeBuildProject.Arn, !Ref "AWS::NoValue"]
+ - !If [CreatePromoteStage, !GetAtt PromotionCodeBuildProject.Arn, !Ref "AWS::NoValue"]
+ Action:
+ - "codebuild:BatchGetBuilds"
+ - "codebuild:StartBuild"
+ - "codebuild:BatchGetBuildBatches"
+ - "codebuild:StartBuildBatch"
+ Effect: "Allow"
+
+ CodePipelineRole:
+ Type: AWS::IAM::Role
+ Properties:
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: "Allow"
+ Principal:
+ Service: "codepipeline.amazonaws.com"
+ Action:
+ - "sts:AssumeRole"
+ ManagedPolicyArns:
+ - !Ref CodePipelinePolicy
+ - !Ref LockToRegionPolicy
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "CodePipelineRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ Pipeline:
+ Type: AWS::CodePipeline::Pipeline
+ Properties:
+ RoleArn: !GetAtt CodePipelineRole.Arn
+ ArtifactStore:
+ Type: "S3"
+ Location: !Ref PipelineBucket
+ Name: !If
+ - PipelineEnvironmentNameEnabled
+ - !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - !Ref Environment
+ - "Pipeline"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - '-'
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - /
+ - Ref: AWS::StackId
+ - !Ref AWS::NoValue
+ Stages:
+ - Name: "Fetch"
+ Actions:
+ - Name: "Get-Artifacts"
+ ActionTypeId:
+ Category: "Source"
+ Version: "1"
+ Provider: "S3"
+ Owner: "AWS"
+ Configuration:
+ S3Bucket: !If
+ - CreateGitHubActionsResources
+ - !Ref GitHubArtifactSourceBucket
+ - !Select [5, !Split [':', !Ref ArtifactSourceBucketArn]]
+ S3ObjectKey: "template.zip"
+ PollForSourceChanges: !If [EnablePipelinePolling, "true", "false"]
+ OutputArtifacts:
+ - Name: "sam-artifacts"
+ - !If
+ - CreateManualApprovalStage
+ - Name: "Approval"
+ Actions:
+ - Name: "Deploy-Approval"
+ ActionTypeId:
+ Category: "Approval"
+ Version: "1"
+ Provider: "Manual"
+ Owner: "AWS"
+ Configuration:
+ CustomData: "Click approve to proceed to Deploy stage"
+ - !Ref AWS::NoValue
+ - Name: "Deploy"
+ Actions:
+ - Name: "Deploy"
+ ActionTypeId:
+ Category: "Build"
+ Version: "1"
+ Provider: "CodeBuild"
+ Owner: "AWS"
+ Configuration:
+ ProjectName: !Ref DeployCodeBuildProject
+ InputArtifacts:
+ - Name: "sam-artifacts"
+ RunOrder: 1
+ - !If
+ - CreateTestContainerSignatureValidateStage
+ - Name: ValidateTestSignature
+ ActionTypeId:
+ Category: "Build"
+ Version: "1"
+ Provider: "CodeBuild"
+ Owner: "AWS"
+ Configuration:
+ ProjectName: !Ref ValidateSignatureCodeBuildProject
+ InputArtifacts:
+ - Name: "sam-artifacts"
+ RunOrder: 2
+ - !Ref AWS::NoValue
+ - !If
+ - CreateTestAction
+ - Name: Test
+ ActionTypeId:
+ Category: "Build"
+ Version: "1"
+ Provider: "CodeBuild"
+ Owner: "AWS"
+ Configuration:
+ ProjectName: !Ref TestCodeBuildProject
+ InputArtifacts:
+ - Name: "sam-artifacts"
+ RunOrder: 3
+ - !Ref AWS::NoValue
+ - !If
+ - CreatePromoteStage
+ - Name: "Promote"
+ Actions:
+ - Name: "Promote"
+ ActionTypeId:
+ Category: "Build"
+ Version: "1"
+ Provider: "CodeBuild"
+ Owner: "AWS"
+ Configuration:
+ ProjectName: !Ref PromotionCodeBuildProject
+ InputArtifacts:
+ - Name: "sam-artifacts"
+ - !Ref AWS::NoValue
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "Pipeline"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ #
+ # Event driven triggers
+ #
+
+ DeploymentTriggerCloudWatchEventRole:
+ Type: AWS::IAM::Role
+ Properties:
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "DepTrigRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - events.amazonaws.com
+ Action: sts:AssumeRole
+ Path: /
+ Policies:
+ - PolicyName: cwe-pipeline-execution
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Action: codepipeline:StartPipelineExecution
+ Resource: !Sub "arn:${AWS::Partition}:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}"
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "DeploymentTriggerCloudWatchEventRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ DeploymentTriggerCloudWatchEventRule:
+ Type: AWS::Events::Rule
+ Properties:
+ EventPattern:
+ source:
+ - aws.s3
+ detail-type:
+ - 'AWS API Call via CloudTrail'
+ detail:
+ eventSource:
+ - s3.amazonaws.com
+ eventName:
+ - CopyObject
+ - PutObject
+ - CompleteMultipartUpload
+ requestParameters:
+ bucketName:
+ - !If
+ - CreateGitHubActionsResources
+ - !Ref GitHubArtifactSourceBucket
+ - !Select [5, !Split [':', !Ref ArtifactSourceBucketArn]]
+ key:
+ - "template.zip"
+ Targets:
+ - Arn: !Sub "arn:${AWS::Partition}:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}"
+ RoleArn: !GetAtt DeploymentTriggerCloudWatchEventRole.Arn
+ Id: codepipeline-Pipeline
+
+ DeploymentTriggerEventBusPolicy:
+ Condition: CreateDeploymentTriggerEventBusPolicy
+ Type: AWS::Events::EventBusPolicy
+ Properties:
+ StatementId: !Sub "${AWS::StackName}-DepTrigEventBusPolicy"
+ Statement:
+ Effect: "Allow"
+ Principal:
+ AWS: !Ref ArtifactSourceBucketEventTriggerRoleArn
+ Action: "events:PutEvents"
+ Resource: !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:event-bus/default"
+
+ TrafficTestTriggerCloudWatchEventRole:
+ Type: AWS::IAM::Role
+ Condition: CreateTrafficTest
+ Properties:
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "TrfTrigRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - events.amazonaws.com
+ Action: sts:AssumeRole
+ Path: /
+ Policies:
+ - PolicyName: cwe-codebuild-execution
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Action:
+ - codebuild:StartBuild
+ - codebuild:StopBuild
+
+ Resource: !Sub "arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/${TrafficTestCodeBuildProject}"
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "TrafficTestTriggerCloudWatchEventRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ TrafficTestTriggerCloudWatchEventRule:
+ Condition: CreateTrafficTest
+ Type: AWS::Events::Rule
+ Properties:
+ EventPattern:
+ source:
+ - aws.codebuild
+ detail-type:
+ - CodeBuild Build State Change
+ detail:
+ project-name:
+ - !Ref DeployCodeBuildProject
+ build-status:
+ - "IN_PROGRESS"
+ State: ENABLED
+ Targets:
+ - Id: codepipeline-Pipeline
+ Arn: !GetAtt TrafficTestCodeBuildProject.Arn
+ RoleArn: !GetAtt TrafficTestTriggerCloudWatchEventRole.Arn
+
+ PromotionTriggerCloudWatchEventRole:
+ Condition: CreatePromoteStage
+ Type: AWS::IAM::Role
+ Properties:
+ RoleName:
+ Fn::Join:
+ - "-"
+ - - "PL"
+ - !If
+ - UseTruncatedPipelineStackName
+ - !Ref TruncatedPipelineStackName
+ - !Ref AWS::StackName
+ - "PromoTrigRole"
+ - Fn::Select:
+ - 4
+ - Fn::Split:
+ - "-"
+ - Fn::Select:
+ - 2
+ - Fn::Split:
+ - "/"
+ - Ref: AWS::StackId
+ AssumeRolePolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - events.amazonaws.com
+ Action: sts:AssumeRole
+ Path: /
+ Policies:
+ - PolicyName: event-bus-putevents
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Action: events:PutEvents
+ Resource:
+ !Sub
+ - "arn:${AWS::Partition}:events:${AWS::Region}:${AllowedAccount}:event-bus/default"
+ - AllowedAccount: !Select [0, !Split [',', !Ref AllowedAccounts]]
+ - !If
+ - UseTwoAllowedAccounts
+ - Effect: Allow
+ Action: events:PutEvents
+ Resource:
+ !Sub
+ - "arn:${AWS::Partition}:events:${AWS::Region}:${AllowedAccount}:event-bus/default"
+ - AllowedAccount: !Select [1, !Split [',', !Ref AllowedAccounts]]
+ - !Ref AWS::NoValue
+ Tags:
+ - Key: "Name"
+ Value: !Join
+ - "-"
+ - - !Ref AWS::StackName
+ - "PromotionTriggerCloudWatchEventRole"
+ - Key: "Service"
+ Value: "ci/cd"
+ - Key: "Source"
+ Value: "govuk-one-login/devplatform-deploy/sam-deploy-pipeline/template.yaml"
+
+ PromotionTriggerCloudWatchEventRule:
+ Condition: CreatePromoteStage
+ Type: AWS::Events::Rule
+ Properties:
+ EventPattern:
+ source:
+ - aws.s3
+ detail-type:
+ - 'AWS API Call via CloudTrail'
+ detail:
+ eventSource:
+ - s3.amazonaws.com
+ eventName:
+ - CopyObject
+ - PutObject
+ - CompleteMultipartUpload
+ requestParameters:
+ bucketName:
+ - !Ref ArtifactPromotionBucket
+ key:
+ - "template.zip"
+ Targets:
+ - Arn:
+ !Sub
+ - "arn:${AWS::Partition}:events:${AWS::Region}:${AllowedAccount}:event-bus/default"
+ - AllowedAccount: !Select [0, !Split [',', !Ref AllowedAccounts]]
+ RoleArn: !GetAtt PromotionTriggerCloudWatchEventRole.Arn
+ Id: Upstream-event-bus1
+ - !If
+ - UseTwoAllowedAccounts
+ - Arn:
+ !Sub
+ - "arn:${AWS::Partition}:events:${AWS::Region}:${AllowedAccount}:event-bus/default"
+ - AllowedAccount: !Select [1, !Split [',', !Ref AllowedAccounts]]
+ RoleArn: !GetAtt PromotionTriggerCloudWatchEventRole.Arn
+ Id: Upstream-event-bus2
+ - !Ref AWS::NoValue
+
+ TestContainerSecurityGroup:
+ Type: "AWS::EC2::SecurityGroup"
+ Condition: CreateVPCConfigurationForTestContainer
+ Properties:
+ GroupDescription: >-
+ Permits unrestricted outbound on 443 to allow the testcontainer to access the internet over SSL.
+ SecurityGroupEgress:
+ - CidrIp: 0.0.0.0/0
+ Description: Allow to the wider internet on port 443
+ FromPort: 443
+ IpProtocol: tcp
+ ToPort: 443
+ - CidrIp: 0.0.0.0/0
+ Description: Allow 8089 for splunk api access
+ FromPort: 8089
+ IpProtocol: tcp
+ ToPort: 8089
+ VpcId:
+ Fn::ImportValue: !Sub "${VpcStackName}-VpcId"
+
+ #
+ # Slack build notification rule
+ #
+
+ NotificationRule:
+ Type: AWS::CodeStarNotifications::NotificationRule
+ Condition: EmitBuildNotifications
+ Properties:
+ Name: !Sub
+ - "${StackName}-build-notifications"
+ - StackName: !If [UseTruncatedPipelineStackName, !Ref TruncatedPipelineStackName, !Ref AWS::StackName]
+ Resource: !Sub
+ - "arn:${AWS::Partition}:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}"
+ - Pipeline: !Ref Pipeline
+ DetailType: "BASIC"
+ EventTypeIds:
+ !FindInMap [ BuildNotifications, !Ref SlackNotificationType, "EventTypeIds" ]
+ Targets:
+ - TargetType: "SNS"
+ TargetAddress:
+ Fn::ImportValue:
+ !Sub "${BuildNotificationStackName}-BuildNotificationTopicArn"