From 16f9b35cb829c4fe11d6e3ceaca0e419caff3cb2 Mon Sep 17 00:00:00 2001 From: jakebark Date: Mon, 7 Jul 2025 19:15:36 +0100 Subject: [PATCH 01/14] added dynamic vpc config to codebuild project --- modules/codebuild/main.tf | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/codebuild/main.tf b/modules/codebuild/main.tf index afc23de..41ba72c 100644 --- a/modules/codebuild/main.tf +++ b/modules/codebuild/main.tf @@ -22,7 +22,6 @@ resource "aws_codebuild_project" "this" { value = environment_variable.value } } - } logs_config { @@ -39,5 +38,14 @@ resource "aws_codebuild_project" "this" { insecure_ssl = false report_build_status = false } + + dynamic "vpc_config" { + for_each = var.vpc == null ? [] : [var.vpc] + content { + vpc_id = vpc_config.value.vpc_id + subnets = vpc_config.value.subnets + security_group_ids = vpc_config.value.security_group_ids + } + } } From 04950e66f03e4378e1326885a89511e93fd0781e Mon Sep 17 00:00:00 2001 From: jakebark Date: Mon, 7 Jul 2025 19:16:11 +0100 Subject: [PATCH 02/14] module vars --- modules/codebuild/variables.tf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/codebuild/variables.tf b/modules/codebuild/variables.tf index 8a3a7c0..a3b7eb3 100644 --- a/modules/codebuild/variables.tf +++ b/modules/codebuild/variables.tf @@ -29,3 +29,12 @@ variable "log_group" { variable "image" { type = string } + +variable "vpc" { + type = object({ + vpc_id = string + subnets = list(string) + security_group_ids = list(string) + }) + default = null +} From 8fc964a78228e3cc1b55e5a4c6e93bb21e36facc Mon Sep 17 00:00:00 2001 From: jakebark Date: Mon, 7 Jul 2025 19:16:39 +0100 Subject: [PATCH 03/14] main vars --- variables.tf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/variables.tf b/variables.tf index 839012a..10f560a 100644 --- a/variables.tf +++ b/variables.tf @@ -119,3 +119,12 @@ variable "workspace_directory" { type = string default = "" } + +variable "vpc" { + type = object({ + vpc_id = string + subnets = list(string) + security_group_ids = list(string) + }) + default = null +} From 610d160d9fb7a3b6b7d2ffca1af900a05dc15739 Mon Sep 17 00:00:00 2001 From: jakebark Date: Mon, 7 Jul 2025 19:29:25 +0100 Subject: [PATCH 04/14] module inputs --- codebuild.tf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/codebuild.tf b/codebuild.tf index a72b217..1771278 100644 --- a/codebuild.tf +++ b/codebuild.tf @@ -11,6 +11,7 @@ module "validation" { build_spec = "${each.key}.yml" log_group = aws_cloudwatch_log_group.this.name image = each.value + vpc = var.vpc } module "plan" { @@ -22,6 +23,7 @@ module "plan" { build_spec = "plan.yml" log_group = aws_cloudwatch_log_group.this.name image = "hashicorp/terraform:${var.terraform_version}" + vpc = var.vpc } module "apply" { @@ -33,6 +35,7 @@ module "apply" { build_spec = "apply.yml" log_group = aws_cloudwatch_log_group.this.name image = "hashicorp/terraform:${var.terraform_version}" + vpc = var.vpc } resource "aws_iam_role" "codebuild" { From d14df09d54652e0af1a7036644691ead9fb91f2a Mon Sep 17 00:00:00 2001 From: jakebark Date: Mon, 7 Jul 2025 19:30:22 +0100 Subject: [PATCH 05/14] vpc permissions --- codebuild.tf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/codebuild.tf b/codebuild.tf index 1771278..2d73ebb 100644 --- a/codebuild.tf +++ b/codebuild.tf @@ -161,6 +161,21 @@ data "aws_iam_policy_document" "codebuild" { "*" ] } + + dynamic "statement" { + for_each = var.vpc == null ? [] : [var.vpc] + content { + effect = "Allow" + actions = [ + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs" + ] + resources = [ + "*" + ] + } + } } resource "aws_codebuild_report_group" "sast" { From a2f3f02e90db80c114eaa8995255bacb522d9a3c Mon Sep 17 00:00:00 2001 From: jakebark Date: Mon, 7 Jul 2025 19:31:53 +0100 Subject: [PATCH 06/14] policy whitespace --- codebuild.tf | 7 ------- codepipeline.tf | 3 --- eventbridge.tf | 3 --- 3 files changed, 13 deletions(-) diff --git a/codebuild.tf b/codebuild.tf index 2d73ebb..448370a 100644 --- a/codebuild.tf +++ b/codebuild.tf @@ -81,7 +81,6 @@ data "aws_iam_policy_document" "codebuild" { "logs:CreateLogStream", "logs:PutLogEvents" ] - resources = [ "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*" ] @@ -94,7 +93,6 @@ data "aws_iam_policy_document" "codebuild" { "codebuild:UpdateReport", "codebuild:BatchPutTestCases" ] - resources = [ aws_codebuild_report_group.sast.arn ] @@ -106,7 +104,6 @@ data "aws_iam_policy_document" "codebuild" { "s3:GetObject", "s3:PutObject" ] - resources = [ "${aws_s3_bucket.this.arn}/*", ] @@ -117,7 +114,6 @@ data "aws_iam_policy_document" "codebuild" { actions = [ "sts:AssumeRole" ] - resources = [ "*" ] @@ -130,7 +126,6 @@ data "aws_iam_policy_document" "codebuild" { "dynamodb:PutItem", "dynamodb:DeleteItem" ] - resources = [ "*" // for s3 backend ] @@ -144,7 +139,6 @@ data "aws_iam_policy_document" "codebuild" { "s3:DeleteObject", "s3:ListBucket" ] - resources = [ "*" // for s3 backend ] @@ -156,7 +150,6 @@ data "aws_iam_policy_document" "codebuild" { "kms:GenerateDataKey*", "kms:Decrypt" ] - resources = [ "*" ] diff --git a/codepipeline.tf b/codepipeline.tf index dbff432..5572842 100644 --- a/codepipeline.tf +++ b/codepipeline.tf @@ -186,7 +186,6 @@ data "aws_iam_policy_document" "codepipeline" { "s3:PutObjectAcl", "s3:PutObject" ] - resources = [ "${aws_s3_bucket.this.arn}", "${aws_s3_bucket.this.arn}/*" @@ -203,7 +202,6 @@ data "aws_iam_policy_document" "codepipeline" { "codecommit:CancelUploadArchive", "codestar-connections:UseConnection" ] - resources = [ var.connection == null ? "arn:aws:codecommit:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:${var.repo}" : var.connection ] @@ -215,7 +213,6 @@ data "aws_iam_policy_document" "codepipeline" { "codebuild:BatchGetBuilds", "codebuild:StartBuild" ] - resources = [ "arn:aws:codebuild:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:project/${var.pipeline_name}-*" ] diff --git a/eventbridge.tf b/eventbridge.tf index 7d5885f..9a62d89 100644 --- a/eventbridge.tf +++ b/eventbridge.tf @@ -47,12 +47,10 @@ data "aws_iam_policy_document" "eventbridge_assume" { statement { effect = "Allow" actions = ["sts:AssumeRole"] - principals { type = "Service" identifiers = ["events.amazonaws.com"] } - condition { test = "StringEquals" variable = "aws:SourceAccount" @@ -79,7 +77,6 @@ data "aws_iam_policy_document" "eventbridge" { actions = [ "codepipeline:StartPipelineExecution" ] - resources = [ aws_codepipeline.this.arn ] From f648f03f46602336c86dcb2d20db11d4a2de3419 Mon Sep 17 00:00:00 2001 From: jakebark Date: Mon, 7 Jul 2025 19:52:16 +0100 Subject: [PATCH 07/14] updated module inputs --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 038530e..32ae86d 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,12 @@ module "pipeline" { checkov_version = "3.2.0" tflint_version = "0.55.0" + vpc = { + vpc_id = "vpc-011a22334455bb66c", + subnets = ["subnet-011aabbcc2233d4ef"], + security_group_ids = ["sg-001abcd2233ee4455"], + } + tags = join(",", [ "Environment[Dev,Prod]", "Source" @@ -125,6 +131,8 @@ module "pipeline" { `tflint_version` controls the [tflint](https://github.com/terraform-linters/tflint) version. It defaults to 0.48.0. +`vpc` configures the CodeBuild projects to [run in a VPC](https://docs.aws.amazon.com/codebuild/latest/userguide/vpc-support.html). + `tags` enables tag validation with [tag-nag](https://github.com/jakebark/tag-nag). Input a list of tag keys and/or tag keys and values to enforce. Input must be passed as a string, see [commands](https://github.com/jakebark/tag-nag?tab=readme-ov-file#commands). `tagnag_version` controls the [tag-nag](https://github.com/jakebark/tag-nag) version. It defaults to 0.5.8. From 8f417bf165ab27d8b2a9d8f5d02d83f5f6782a04 Mon Sep 17 00:00:00 2001 From: jakebark Date: Thu, 10 Jul 2025 08:15:18 +0100 Subject: [PATCH 08/14] docs dir, optional inputs moved --- README.md | 30 +----------------------------- docs/optional_inputs.md | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 docs/optional_inputs.md diff --git a/README.md b/README.md index 32ae86d..12713d0 100644 --- a/README.md +++ b/README.md @@ -109,35 +109,7 @@ module "pipeline" { } ``` -`branch` is the branch to source. It defaults to `main`. - -`mode` is [pipeline execution mode](https://docs.aws.amazon.com/codepipeline/latest/userguide/concepts-how-it-works.html#concepts-how-it-works-executions). It defaults to `SUPERSEDED`.`detect_changes` is used with third-party services, like GitHub. It enables AWS CodeConnections to invoke the pipeline when there is a commit to the repo. It defaults to `false`. - -`kms_key` is the arn of an *existing* AWS KMS key. This input will encrypt the Amazon S3 bucket with a AWS KMS key of your choice. Otherwise the bucket will be encrypted using SSE-S3. Your AWS KMS key policy will need to allow codebuild and codepipeline to `kms:GenerateDataKey*` and `kms:Decrypt`. - -`access_logging_bucket` S3 server access logs bucket ARN, enables server access logging on the S3 artifact bucket. - -`artifact_retention` controls the S3 artifact bucket retention period. It defaults to 90 (days). - -`workspace_directory` enables the use of workspace variable files (eg ./workspaces/.tfvars. The input is the directory name that you wish to use. This input is recommended for advanced variable management, where complex and/or signficant amounts of different variables are applied to different AWS accounts. - -`codebuild_policy` replaces the [AWSAdministratorAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess.html) IAM policy. This can be used if you want to scope the permissions of the pipeline. - -`build_timeout` is the CodeBuild project build timeout. It defaults to 10 (minutes). - -`terraform_version` controls the terraform version. It defaults to 1.5.7. - -`checkov_version` controls the [Checkov](https://www.checkov.io/) version. It defaults to latest. - -`tflint_version` controls the [tflint](https://github.com/terraform-linters/tflint) version. It defaults to 0.48.0. - -`vpc` configures the CodeBuild projects to [run in a VPC](https://docs.aws.amazon.com/codebuild/latest/userguide/vpc-support.html). - -`tags` enables tag validation with [tag-nag](https://github.com/jakebark/tag-nag). Input a list of tag keys and/or tag keys and values to enforce. Input must be passed as a string, see [commands](https://github.com/jakebark/tag-nag?tab=readme-ov-file#commands). - -`tagnag_version` controls the [tag-nag](https://github.com/jakebark/tag-nag) version. It defaults to 0.5.8. - -`checkov_skip` defines [Checkov](https://www.checkov.io/) skips for the pipeline. This is useful for organization-wide policies, removing the need to add individual resource skips. +See [optional inputs](./docs/optional_inputs.md) for descriptions. ## Architecture diff --git a/docs/optional_inputs.md b/docs/optional_inputs.md new file mode 100644 index 0000000..0e6260b --- /dev/null +++ b/docs/optional_inputs.md @@ -0,0 +1,33 @@ +# Optional inputs + +`branch` is the branch to source. It defaults to `main`. + +`mode` is [pipeline execution mode](https://docs.aws.amazon.com/codepipeline/latest/userguide/concepts-how-it-works.html#concepts-how-it-works-executions). It defaults to `SUPERSEDED`.`detect_changes` is used with third-party services, like GitHub. It enables AWS CodeConnections to invoke the pipeline when there is a commit to the repo. It defaults to `false`. + +`kms_key` is the arn of an *existing* AWS KMS key. This input will encrypt the Amazon S3 bucket with a AWS KMS key of your choice. Otherwise the bucket will be encrypted using SSE-S3. Your AWS KMS key policy will need to allow codebuild and codepipeline to `kms:GenerateDataKey*` and `kms:Decrypt`. + +`access_logging_bucket` S3 server access logs bucket ARN, enables server access logging on the S3 artifact bucket. + +`artifact_retention` controls the S3 artifact bucket retention period. It defaults to 90 (days). + +`workspace_directory` enables the use of workspace variable files (eg ./workspaces/.tfvars. The input is the directory name that you wish to use. This input is recommended for advanced variable management, where complex and/or signficant amounts of different variables are applied to different AWS accounts. + +`codebuild_policy` replaces the [AWSAdministratorAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess.html) IAM policy. This can be used if you want to scope the permissions of the pipeline. + +`build_timeout` is the CodeBuild project build timeout. It defaults to 10 (minutes). + +`terraform_version` controls the terraform version. It defaults to 1.5.7. + +`checkov_version` controls the [Checkov](https://www.checkov.io/) version. It defaults to latest. + +`tflint_version` controls the [tflint](https://github.com/terraform-linters/tflint) version. It defaults to 0.48.0. + +`vpc` configures the CodeBuild projects to [run in a VPC](https://docs.aws.amazon.com/codebuild/latest/userguide/vpc-support.html). + +`tags` enables tag validation with [tag-nag](https://github.com/jakebark/tag-nag). Input a list of tag keys and/or tag keys and values to enforce. Input must be passed as a string, see [commands](https://github.com/jakebark/tag-nag?tab=readme-ov-file#commands). + +`tagnag_version` controls the [tag-nag](https://github.com/jakebark/tag-nag) version. It defaults to 0.5.8. + +`checkov_skip` defines [Checkov](https://www.checkov.io/) skips for the pipeline. This is useful for organization-wide policies, removing the need to add individual resource skips. + + From 10016ce20382ce7d3f4ed730180032acc9cb6a72 Mon Sep 17 00:00:00 2001 From: jakebark Date: Thu, 10 Jul 2025 08:16:16 +0100 Subject: [PATCH 09/14] mv architecture docs --- docs/architecture.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 docs/architecture.md diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..e96f09a --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,18 @@ +# Architecture + +![image info](./img/architecture.png) + +1. **(1a)** User commits to a third-party repository, this invokes the AWS Codepipeline pipeline; *or* **(1b)** User commits to a CodeCommit repository, this invokes an Amazon EventBridge rule, which runs the pipeline. +2. The pipeline validates the code and then runs a terraform plan against all of the target AWS accounts. Manual approval is then required to run the terraform apply. +3. Resources are deployed to the target AWS accounts using [Terraform Workspaces](https://developer.hashicorp.com/terraform/language/state/workspaces). Each AWS account is assigned their own Workspace using their AWS Account ID. +4. Artifacts and logs are exported to Amazon S3 and CloudWatch logs. + +## Pipeline Validation + +| Check | Description | +|---|---| +| validate | runs `terraform validate` to make sure that the code is syntactically valid. | +| lint | runs [tfLint](https://github.com/terraform-linters/tflint) which will find errors, depreciated syntax, and check naming conventions. | +| fmt | runs `terraform fmt --recursive --check` to ensure code is consistently formatted. | +| sast | runs [checkov](https://www.checkov.io/) for security best practices. | +| tags (optional)| runs [tag-nag](https://github.com/jakebark/tag-nag) to validate tags.| From ebde99957d7e65da55489b4d1fb456362c0e952f Mon Sep 17 00:00:00 2001 From: jakebark Date: Thu, 10 Jul 2025 08:16:59 +0100 Subject: [PATCH 10/14] mv troubleshooting docs --- README.md | 21 --------------------- docs/troubleshooting.md | 11 +++++++++++ 2 files changed, 11 insertions(+), 21 deletions(-) create mode 100644 docs/troubleshooting.md diff --git a/README.md b/README.md index 12713d0..80b69de 100644 --- a/README.md +++ b/README.md @@ -111,27 +111,6 @@ module "pipeline" { See [optional inputs](./docs/optional_inputs.md) for descriptions. -## Architecture - -![image info](./img/architecture.png) - -1. **(1a)** User commits to a third-party repository, this invokes the AWS Codepipeline pipeline; *or* **(1b)** User commits to a CodeCommit repository, this invokes an Amazon EventBridge rule, which runs the pipeline. -2. The pipeline validates the code and then runs a terraform plan against all of the target AWS accounts. Manual approval is then required to run the terraform apply. -3. Resources are deployed to the target AWS accounts using [Terraform Workspaces](https://developer.hashicorp.com/terraform/language/state/workspaces). Each AWS account is assigned their own Workspace using their AWS Account ID. -4. Artifacts and logs are exported to Amazon S3 and CloudWatch logs. - -## Troubleshooting - -| Issue | Fix | -|---|---| -| Failed lint or validate | Read the report or logs to discover why the code has failed, then make a new commit. | -| Failed fmt | This means your code is not formatted. Run `terraform fmt --recursive` on your code, then make a new commit. | -| Failed SAST | Read the Checkov logs (Details > Reports) and either make the correction in code or add a skip to the module inputs. | -| Failed plan or apply stage | Read the report or logs to discover error in terraform code, then make a new commit. | -| Pipeline fails on apply with `the action failed because no branch named main was found ...` | Either nothing has been committed to the repo or the branch is incorrect (Eg using `Master` not `Main`). Either commit to the Main branch or change the module input to fix this. | -| `Invalid count argument` for `aws_s3_bucket_server_side_encryption_configuration` | The AWS KMS key must exist before the pipeline is created. If you create both at the same time, there is a dependency issue. | -| Unable to find state file | Check state storage :env > AWS Account ID > backend key | - ## Best Practices Permissions to your CodeCommit repository, CodeBuild projects, and CodePipeline pipeline should be tightly controlled. Here are some ideas: diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..8db9c4f --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,11 @@ +# Troubleshooting + +| Issue | Fix | +|---|---| +| Failed lint or validate | Read the report or logs to discover why the code has failed, then make a new commit. | +| Failed fmt | This means your code is not formatted. Run `terraform fmt --recursive` on your code, then make a new commit. | +| Failed SAST | Read the Checkov logs (Details > Reports) and either make the correction in code or add a skip to the module inputs. | +| Failed plan or apply stage | Read the report or logs to discover error in terraform code, then make a new commit. | +| Pipeline fails on apply with `the action failed because no branch named main was found ...` | Either nothing has been committed to the repo or the branch is incorrect (Eg using `Master` not `Main`). Either commit to the Main branch or change the module input to fix this. | +| `Invalid count argument` for `aws_s3_bucket_server_side_encryption_configuration` | The AWS KMS key must exist before the pipeline is created. If you create both at the same time, there is a dependency issue. | +| Unable to find state file | Check state storage :env > AWS Account ID > backend key | From cce515096164365aef46251b0c2110d43763aa9c Mon Sep 17 00:00:00 2001 From: jakebark Date: Thu, 10 Jul 2025 08:17:32 +0100 Subject: [PATCH 11/14] mv best practices docs --- README.md | 9 --------- docs/best_practices.md | 8 ++++++++ 2 files changed, 8 insertions(+), 9 deletions(-) create mode 100644 docs/best_practices.md diff --git a/README.md b/README.md index 80b69de..0b7f6a4 100644 --- a/README.md +++ b/README.md @@ -111,15 +111,6 @@ module "pipeline" { See [optional inputs](./docs/optional_inputs.md) for descriptions. -## Best Practices - -Permissions to your CodeCommit repository, CodeBuild projects, and CodePipeline pipeline should be tightly controlled. Here are some ideas: -- [Specify approval permission for specific pipelines and approval actions](https://docs.aws.amazon.com/codepipeline/latest/userguide/approvals-iam-permissions.html#approvals-iam-permissions-limited) -- [Using identity-based policies for AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html) -- [Limit pushes and merges to branches in AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-conditional-branch.html) - -Checkov skips can be used where Checkov policies conflict with your organization's practices or design decisions. The `checkov_skip` module input allows you to set skips for all resources in your repository. For example, if your organization operates in a single region you may want to add `CKV_AWS_144` (Ensure that S3 bucket has cross-region replication enabled). For individual resource skips, you can still use [inline code comments](https://www.checkov.io/2.Basics/Suppressing%20and%20Skipping%20Policies.html). - ## Related Resources - [aws-terraform-pipeline](https://github.com/aws-samples/aws-terraform-pipeline) diff --git a/docs/best_practices.md b/docs/best_practices.md new file mode 100644 index 0000000..b7d85e4 --- /dev/null +++ b/docs/best_practices.md @@ -0,0 +1,8 @@ +# Best Practices + +Permissions to your CodeCommit repository, CodeBuild projects, and CodePipeline pipeline should be tightly controlled. Here are some ideas: +- [Specify approval permission for specific pipelines and approval actions](https://docs.aws.amazon.com/codepipeline/latest/userguide/approvals-iam-permissions.html#approvals-iam-permissions-limited) +- [Using identity-based policies for AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html) +- [Limit pushes and merges to branches in AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-conditional-branch.html) + +Checkov skips can be used where Checkov policies conflict with your organization's practices or design decisions. The `checkov_skip` module input allows you to set skips for all resources in your repository. For example, if your organization operates in a single region you may want to add `CKV_AWS_144` (Ensure that S3 bucket has cross-region replication enabled). For individual resource skips, you can still use [inline code comments](https://www.checkov.io/2.Basics/Suppressing%20and%20Skipping%20Policies.html). From adb8ffaf04babf6ba5b701727e40196378bcaf42 Mon Sep 17 00:00:00 2001 From: jakebark Date: Thu, 10 Jul 2025 08:18:17 +0100 Subject: [PATCH 12/14] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b7f6a4..4bd8196 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ pipeline repo main.tf <--module deployed here ``` -Segregation enables the pipeline to run commands against the code in "your repo" without affecting the pipeline infrastructure. Typically this could be an infrastructure or bootstrap repo for the AWS account thats used to provision infrastructure and/or multiple pipelines. +Segregation enables the pipeline to run commands against the code in "your repo" without affecting the pipeline infrastructure. Review the [example code directory](./example-code) and ensure the code in your repo is compatible. From 19b163b17717958cdb5458f8f4bde070644cabfc Mon Sep 17 00:00:00 2001 From: Jake <94998878+jakebark@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:00:57 +0100 Subject: [PATCH 13/14] codebuild vpc (#19) Added optional support for CodeBuild VPC deployment --- codebuild.tf | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/codebuild.tf b/codebuild.tf index 448370a..ee3924f 100644 --- a/codebuild.tf +++ b/codebuild.tf @@ -155,13 +155,19 @@ data "aws_iam_policy_document" "codebuild" { ] } + + // https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html#customer-managed-policies-example-create-vpc-network-interface dynamic "statement" { for_each = var.vpc == null ? [] : [var.vpc] content { effect = "Allow" actions = [ - "ec2:DescribeSecurityGroups", + "ec2:CreateNetworkInterface", + "ec2:DescribeDhcpOptions", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", "ec2:DescribeSubnets", + "ec2:DescribeSecurityGroups", "ec2:DescribeVpcs" ] resources = [ @@ -169,6 +175,35 @@ data "aws_iam_policy_document" "codebuild" { ] } } + + dynamic "statement" { + for_each = var.vpc == null ? [] : [var.vpc] + content { + effect = "Allow" + actions = [ + "ec2:CreateNetworkInterfacePermission" + + ] + resources = [ + "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:network-interface/*" + ] + condition { + test = "StringEquals" + variable = "ec2:AuthorizedService" + values = [ + "codebuild.amazonaws.com" + ] + } + condition { + test = "ArnEquals" + variable = "ec2:Subnet" + values = [ + for id in var.vpc["subnets"] : + "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:subnet/${id}" + ] + } + } + } } resource "aws_codebuild_report_group" "sast" { From d076846e8769a7cb9949073005c2dd6e78fff978 Mon Sep 17 00:00:00 2001 From: Jake <94998878+jakebark@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:00:57 +0100 Subject: [PATCH 14/14] codebuild vpc (#19) Added optional support for CodeBuild VPC deployment --- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ codebuild.tf | 1 - 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4bd8196..4e41a75 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,69 @@ module "pipeline" { } ``` +<<<<<<< HEAD See [optional inputs](./docs/optional_inputs.md) for descriptions. +======= +`branch` is the branch to source. It defaults to `main`. + +`mode` is [pipeline execution mode](https://docs.aws.amazon.com/codepipeline/latest/userguide/concepts-how-it-works.html#concepts-how-it-works-executions). It defaults to `SUPERSEDED`.`detect_changes` is used with third-party services, like GitHub. It enables AWS CodeConnections to invoke the pipeline when there is a commit to the repo. It defaults to `false`. + +`kms_key` is the arn of an *existing* AWS KMS key. This input will encrypt the Amazon S3 bucket with a AWS KMS key of your choice. Otherwise the bucket will be encrypted using SSE-S3. Your AWS KMS key policy will need to allow codebuild and codepipeline to `kms:GenerateDataKey*` and `kms:Decrypt`. + +`access_logging_bucket` S3 server access logs bucket ARN, enables server access logging on the S3 artifact bucket. + +`artifact_retention` controls the S3 artifact bucket retention period. It defaults to 90 (days). + +`workspace_directory` enables the use of workspace variable files (eg ./workspaces/.tfvars. The input is the directory name that you wish to use. This input is recommended for advanced variable management, where complex and/or signficant amounts of different variables are applied to different AWS accounts. + +`codebuild_policy` replaces the [AWSAdministratorAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess.html) IAM policy. This can be used if you want to scope the permissions of the pipeline. + +`build_timeout` is the CodeBuild project build timeout. It defaults to 10 (minutes). + +`terraform_version` controls the terraform version. It defaults to 1.5.7. + +`checkov_version` controls the [Checkov](https://www.checkov.io/) version. It defaults to latest. + +`tflint_version` controls the [tflint](https://github.com/terraform-linters/tflint) version. It defaults to 0.48.0. + +`vpc` configures the CodeBuild projects to [run in a VPC](https://docs.aws.amazon.com/codebuild/latest/userguide/vpc-support.html). + +`tags` enables tag validation with [tag-nag](https://github.com/jakebark/tag-nag). Input a list of tag keys and/or tag keys and values to enforce. Input must be passed as a string, see [commands](https://github.com/jakebark/tag-nag?tab=readme-ov-file#commands). + +`tagnag_version` controls the [tag-nag](https://github.com/jakebark/tag-nag) version. It defaults to 0.5.8. + +`checkov_skip` defines [Checkov](https://www.checkov.io/) skips for the pipeline. This is useful for organization-wide policies, removing the need to add individual resource skips. + +## Architecture + +![image info](./img/architecture.png) + +1. **(1a)** User commits to a third-party repository, this invokes the AWS Codepipeline pipeline; *or* **(1b)** User commits to a CodeCommit repository, this invokes an Amazon EventBridge rule, which runs the pipeline. +2. The pipeline validates the code and then runs a terraform plan against all of the target AWS accounts. Manual approval is then required to run the terraform apply. +3. Resources are deployed to the target AWS accounts using [Terraform Workspaces](https://developer.hashicorp.com/terraform/language/state/workspaces). Each AWS account is assigned their own Workspace using their AWS Account ID. +4. Artifacts and logs are exported to Amazon S3 and CloudWatch logs. + +## Troubleshooting + +| Issue | Fix | +|---|---| +| Failed lint or validate | Read the report or logs to discover why the code has failed, then make a new commit. | +| Failed fmt | This means your code is not formatted. Run `terraform fmt --recursive` on your code, then make a new commit. | +| Failed SAST | Read the Checkov logs (Details > Reports) and either make the correction in code or add a skip to the module inputs. | +| Failed plan or apply stage | Read the report or logs to discover error in terraform code, then make a new commit. | +| Pipeline fails on apply with `the action failed because no branch named main was found ...` | Either nothing has been committed to the repo or the branch is incorrect (Eg using `Master` not `Main`). Either commit to the Main branch or change the module input to fix this. | +| `Invalid count argument` for `aws_s3_bucket_server_side_encryption_configuration` | The AWS KMS key must exist before the pipeline is created. If you create both at the same time, there is a dependency issue. | +| Unable to find state file | Check state storage :env > AWS Account ID > backend key | + +## Best Practices + +Permissions to your CodeCommit repository, CodeBuild projects, and CodePipeline pipeline should be tightly controlled. Here are some ideas: +- [Specify approval permission for specific pipelines and approval actions](https://docs.aws.amazon.com/codepipeline/latest/userguide/approvals-iam-permissions.html#approvals-iam-permissions-limited) +- [Using identity-based policies for AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html) +- [Limit pushes and merges to branches in AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-conditional-branch.html) + +Checkov skips can be used where Checkov policies conflict with your organization's practices or design decisions. The `checkov_skip` module input allows you to set skips for all resources in your repository. For example, if your organization operates in a single region you may want to add `CKV_AWS_144` (Ensure that S3 bucket has cross-region replication enabled). For individual resource skips, you can still use [inline code comments](https://www.checkov.io/2.Basics/Suppressing%20and%20Skipping%20Policies.html). +>>>>>>> 50d0801 (codebuild vpc (#19)) ## Related Resources diff --git a/codebuild.tf b/codebuild.tf index ee3924f..ed1e171 100644 --- a/codebuild.tf +++ b/codebuild.tf @@ -155,7 +155,6 @@ data "aws_iam_policy_document" "codebuild" { ] } - // https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html#customer-managed-policies-example-create-vpc-network-interface dynamic "statement" { for_each = var.vpc == null ? [] : [var.vpc]