Skip to content

Commit

Permalink
Fix codebuild policy length (#774)
Browse files Browse the repository at this point in the history
### Feature or Bugfix
<!-- please choose -->
- Bugfix

### Detail
- There is a limit of 10,240 characters aggregate across all inline
policies that are able to be attached to an IAM Role
- By default, codebuild adds its own IAM permission statements as inline
policies to the attached execution role to the Build Project unless
otherwise specified
- On certain deployment configurations we will exceed the 10,240
character limit because we use the same IAM role for many CodeBuild
Steps and each CodeBuild Project will add addition IAM inline statements

In this PR, to resolve we:
- Add the missing IAM permissions that CodeBuild would add by default to
the IAM Role
- Switch the IAM policy we add to the IAM Role from inline to customer
managed policy (as a best practice)
- Pass a copy of the IAM Role with `.without_policy_updates()` to each
`CodeBuildStep` to prevent CodeBuild from adding additional permissions
statements and exceeding the character limit


### Relates
- #773 

### Security
Please answer the questions below briefly where applicable, or write
`N/A`. Based on
[OWASP 10](https://owasp.org/Top10/en/).

- Does this PR introduce or modify any input fields or queries - this
includes
fetching data from storage outside the application (e.g. a database, an
S3 bucket)?
  - Is the input sanitized?
- What precautions are you taking before deserializing the data you
consume?
  - Is injection prevented by parametrizing queries?
  - Have you ensured no `eval` or similar functions are used?
- Does this PR introduce any functionality or component that requires
authorization?
- How have you ensured it respects the existing AuthN/AuthZ mechanisms?
  - Are you logging failed auth attempts?
- Are you using or adding any cryptographic features?
  - Do you use a standard proven implementations?
  - Are the used keys controlled by the customer? Where are they stored?
- Are you introducing any new policies/roles/users?
  - Have you used the least-privilege principle? How?


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.
  • Loading branch information
noah-paige authored Sep 28, 2023
1 parent 4e0c552 commit 5ecec01
Showing 1 changed file with 45 additions and 29 deletions.
74 changes: 45 additions & 29 deletions deploy/stacks/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def __init__(
'cdk synth',
'echo ${CODEBUILD_SOURCE_VERSION}'
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
cross_account_keys=True,
Expand Down Expand Up @@ -225,10 +225,10 @@ def set_codebuild_iam_roles(self):
assumed_by=iam.ServicePrincipal('codebuild.amazonaws.com'),
)

self.baseline_codebuild_policy = iam.Policy(
self.baseline_codebuild_policy = iam.ManagedPolicy(
self,
'BaselineCodeBuildPolicy',
policy_name=f'{self.resource_prefix}-{self.git_branch}-baseline-codebuild-policy',
'BaselineCodeBuildManagedPolicy',
managed_policy_name=f'{self.resource_prefix}-{self.git_branch}-baseline-cb-policy',
roles=[self.baseline_codebuild_role, self.expanded_codebuild_role],
statements= [
iam.PolicyStatement(
Expand All @@ -252,7 +252,14 @@ def set_codebuild_iam_roles(self):
actions=[
'ecr:GetAuthorizationToken',
'ec2:DescribePrefixLists',
'ec2:DescribeManagedPrefixLists'
'ec2:DescribeManagedPrefixLists',
'ec2:CreateNetworkInterface',
'ec2:DescribeNetworkInterfaces',
'ec2:DeleteNetworkInterface',
'ec2:DescribeSubnets',
'ec2:DescribeSecurityGroups',
'ec2:DescribeDhcpOptions',
'ec2:DescribeVpcs',
],
resources=['*'],
),
Expand All @@ -272,6 +279,8 @@ def set_codebuild_iam_roles(self):
'kms:Decrypt',
'kms:Encrypt',
'kms:GenerateDataKey',
'kms:ReEncrypt*',
'kms:DescribeKey',
'secretsmanager:GetSecretValue',
'secretsmanager:DescribeSecret',
'ssm:GetParametersByPath',
Expand All @@ -285,12 +294,17 @@ def set_codebuild_iam_roles(self):
'codebuild:UpdateReport',
'codebuild:BatchPutTestCases',
'codebuild:BatchPutCodeCoverages',
'ec2:GetManagedPrefixListEntries'
'ec2:GetManagedPrefixListEntries',
'ec2:CreateNetworkInterfacePermission',
'logs:CreateLogGroup',
'logs:CreateLogStream',
'logs:PutLogEvents',
],
resources=[
f'arn:aws:s3:::{self.resource_prefix}*',
f'arn:aws:s3:::{self.resource_prefix}*/*',
f'arn:aws:codebuild:{self.region}:{self.account}:project/*{self.resource_prefix}*',
f'arn:aws:codebuild:{self.region}:{self.account}:report-group/{self.resource_prefix}*',
f'arn:aws:secretsmanager:{self.region}:{self.account}:secret:*{self.resource_prefix}*',
f'arn:aws:secretsmanager:{self.region}:{self.account}:secret:*dataall*',
f'arn:aws:kms:{self.region}:{self.account}:key/*',
Expand All @@ -300,14 +314,16 @@ def set_codebuild_iam_roles(self):
f'arn:aws:codeartifact:{self.region}:{self.account}:repository/{self.resource_prefix}*',
f'arn:aws:codeartifact:{self.region}:{self.account}:domain/{self.resource_prefix}*',
f'arn:aws:ec2:{self.region}:{self.account}:prefix-list/*',
f'arn:aws:ec2:{self.region}:{self.account}:network-interface/*',
f'arn:aws:logs:{self.region}:{self.account}:log-group:/aws/codebuild/{self.resource_prefix}*',
],
),
],
)
self.expanded_codebuild_policy = iam.Policy(
self.expanded_codebuild_policy = iam.ManagedPolicy(
self,
'ExpandedCodeBuildPolicy',
policy_name=f'{self.resource_prefix}-{self.git_branch}-expanded-codebuild-policy',
'ExpandedCodeBuildManagedPolicy',
managed_policy_name=f'{self.resource_prefix}-{self.git_branch}-expanded-cb-policy',
roles=[self.expanded_codebuild_role],
statements= [
iam.PolicyStatement(
Expand All @@ -334,10 +350,10 @@ def set_codebuild_iam_roles(self):
)
self.expanded_codebuild_policy.attach_to_role(self.git_project_role)
self.baseline_codebuild_policy.attach_to_role(self.git_project_role)
self.git_release_policy = iam.Policy(
self.git_release_policy = iam.ManagedPolicy(
self,
'GitReleasePolicy',
policy_name=f'{self.resource_prefix}-{self.git_branch}-git-release-policy',
'GitReleaseManagedPolicy',
managed_policy_name=f'{self.resource_prefix}-{self.git_branch}-gitrelease-policy',
roles=[self.git_project_role],
statements= [
iam.PolicyStatement(
Expand Down Expand Up @@ -416,7 +432,7 @@ def set_quality_gate_stage(self):
'make drop-tables',
'make upgrade-db',
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
security_groups=[self.codebuild_sg],
),
Expand All @@ -432,7 +448,7 @@ def set_quality_gate_stage(self):
'. env/bin/activate',
'make check-security',
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
pipelines.CodeBuildStep(
Expand All @@ -452,7 +468,7 @@ def set_quality_gate_stage(self):
'npm run copy-config',
'npm run lint -- --quiet',
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
)
Expand Down Expand Up @@ -487,7 +503,7 @@ def set_quality_gate_stage(self):
)
),
commands=[],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
security_groups=[self.codebuild_sg],
),
Expand All @@ -503,7 +519,7 @@ def set_quality_gate_stage(self):
'cd source_build/ && zip -r ../source_build/source_build.zip *',
f'aws s3api put-object --bucket {self.pipeline_bucket.bucket_name} --key source_build.zip --body source_build.zip',
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
security_groups=[self.codebuild_sg],
),
Expand All @@ -523,7 +539,7 @@ def set_quality_gate_stage(self):
'cd source_build/ && zip -r ../source_build/source_build.zip *',
f'aws s3api put-object --bucket {self.pipeline_bucket.bucket_name} --key source_build.zip --body source_build.zip',
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
security_groups=[self.codebuild_sg],
),
Expand Down Expand Up @@ -564,7 +580,7 @@ def set_ecr_stage(
commands=[
f"make deploy-image type=lambda image-tag=$IMAGE_TAG account={target_env['account']} region={target_env['region']} repo={repository_name}",
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
pipelines.CodeBuildStep(
Expand All @@ -582,7 +598,7 @@ def set_ecr_stage(
commands=[
f"make deploy-image type=ecs image-tag=$IMAGE_TAG account={target_env['account']} region={target_env['region']} repo={repository_name}",
],
role=self.baseline_codebuild_role,
role=self.baseline_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
)
Expand Down Expand Up @@ -648,7 +664,7 @@ def set_db_migration_stage(
'if [ "$(jq -r .builds[0].buildStatus codebuild-output.json)" = "FAILED" ]; then echo "Failed"; cat codebuild-output.json; exit -1; fi',
'cat codebuild-output.json ',
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
)
Expand Down Expand Up @@ -680,7 +696,7 @@ def set_stacks_updater_stage(
f'cluster_arn="arn:aws:ecs:{target_env["region"]}:{target_env["account"]}:cluster/$cluster_name"',
f'aws --profile buildprofile ecs run-task --task-definition $task_definition --cluster "$cluster_arn" --launch-type "FARGATE" --network-configuration "$network_config" --launch-type FARGATE --propagate-tags TASK_DEFINITION',
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
)
Expand Down Expand Up @@ -735,7 +751,7 @@ def set_cloudfront_stage(self, target_env):
'aws s3 sync build/ s3://$bucket --profile buildprofile',
"aws cloudfront create-invalidation --distribution-id $distributionId --paths '/*' --profile buildprofile",
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
self.cognito_config_action(target_env),
Expand Down Expand Up @@ -770,7 +786,7 @@ def set_cloudfront_stage(self, target_env):
'aws s3 sync site/ s3://$bucket',
"aws cloudfront create-invalidation --distribution-id $distributionId --paths '/*'",
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
)
Expand All @@ -797,7 +813,7 @@ def cw_rum_config_action(self, target_env):
'pip install boto3==1.20.46',
'python deploy/configs/rum_config.py',
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
)

Expand All @@ -824,7 +840,7 @@ def cognito_config_action(self, target_env):
'pip install boto3==1.20.46',
'python deploy/configs/cognito_urls_config.py',
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
)

Expand Down Expand Up @@ -882,7 +898,7 @@ def set_albfront_stage(self, target_env, repository_name):
'docker tag $IMAGE_TAG:$IMAGE_TAG $REPOSITORY_URI:$IMAGE_TAG',
'docker push $REPOSITORY_URI:$IMAGE_TAG',
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
pipelines.CodeBuildStep(
Expand All @@ -906,7 +922,7 @@ def set_albfront_stage(self, target_env, repository_name):
'docker tag $IMAGE_TAG:$IMAGE_TAG $REPOSITORY_URI:$IMAGE_TAG',
'docker push $REPOSITORY_URI:$IMAGE_TAG',
],
role=self.expanded_codebuild_role,
role=self.expanded_codebuild_role.without_policy_updates(),
vpc=self.vpc,
),
],
Expand Down Expand Up @@ -957,7 +973,7 @@ def set_release_stage(
},
)
),
role=self.git_project_role,
role=self.git_project_role.without_policy_updates(),
vpc=self.vpc,
security_groups=[self.codebuild_sg],
commands=[],
Expand Down

0 comments on commit 5ecec01

Please sign in to comment.