Parcourir la source

Merge pull request #121 from mdr-engineering/feature/bp_MSOCI-1569_codecommit_ecr_gc

Feature/bp msoci 1569 codecommit ecr gc
Brad Poulton il y a 4 ans
Parent
commit
1c6cf5f492

+ 15 - 0
base/codebuild_artifact/README.md

@@ -0,0 +1,15 @@
+# How to Use this Module
+
+This module is where the CodeBuild artifacts are created. It uses the Terraform GitHub Provider and requires a Personal Access Token. This should be your Personal Access Token not mdr-aws-codebuild's token. The provider will look in the environmental variables for the token. 
+
+```
+export GITHUB_TOKEN=<gihub_token>
+```
+
+This module should NOT create the github repo. That is a manual process. I am not comfortable with terraform adding/removing github repos. The github repo should have the same name as the name variable in the terrafgrunt.hcl file. The user associated with the Personal Access Token needs to have admin permissions on the github repo. 
+
+## Github Service Account ( mdr-aws-codebuild )
+
+AWS CodeBuild needs a Github Personal Access Token to pull code after the code in a repository has been updated. Terraform is capable of storing the Github Personal Access Token, but that is a bad idea. A better idea is a service account in Github that gives CodeBuild access to specific repositories. This user will need access to repositories in different organizations. The login credentials as well as the Personal Access Token for mdr-aws-codebuild are stored in Vault. 
+
+The service account (mdr-aws-codebuild) needs to have a personal access token manually placed into the aws console. 

+ 56 - 0
base/codebuild_artifact/main.tf

@@ -0,0 +1,56 @@
+data "github_repository" "this" {
+    name    = var.name
+}
+
+resource "aws_codebuild_project" "this" {
+  count                 = var.artifact_s3_bucket=="" ? 0 : 1
+
+  name                  = var.name
+  description           = "Project for ${var.name}"
+  service_role          = var.service_role
+  encryption_key        = var.kms_key
+  badge_enabled         = var.badge_enabled
+
+  source {
+    type                = "GITHUB_ENTERPRISE"
+    location            = data.github_repository.this.http_clone_url
+    report_build_status = true
+  }
+
+  environment {
+    compute_type        = "BUILD_GENERAL1_SMALL"
+    image               = var.codebuild_image
+    type                = "LINUX_CONTAINER"
+  }
+
+  artifacts {
+    type                = "S3"
+    location            = var.artifact_s3_bucket
+    name                = "/"
+    path                = var.name
+    namespace_type      = "BUILD_ID"
+    packaging           = "NONE"
+  }
+
+  tags = merge(var.standard_tags, var.tags)
+}
+
+resource "aws_codebuild_webhook" "this" {
+  project_name  = var.name
+  branch_filter = var.webhook_branch_filter
+
+  depends_on = [ aws_codebuild_project.this  ]
+}
+
+resource "github_repository_webhook" "this" {
+  active     = true
+  events     = ["push"]
+  repository = data.github_repository.this.name
+
+  configuration {
+    url          = aws_codebuild_webhook.this.payload_url
+    secret       = aws_codebuild_webhook.this.secret
+    content_type = "json"
+    insecure_ssl = false
+  }
+}

+ 29 - 0
base/codebuild_artifact/vars.tf

@@ -0,0 +1,29 @@
+variable "tags" {
+  description = "Tags to add to the resource (in addition to global standard tags)"
+  type        = map
+  default     = { }
+}
+variable "standard_tags" { type = map }
+variable "environment" { type = string }
+variable "aws_partition" { type = string }
+variable "aws_partition_alias" { type = string }
+variable "aws_account_id" { type = string }
+variable "name" { type = string }
+variable "service_role" { type = string }
+variable "artifact_s3_bucket" { type = string }
+variable "codebuild_image" {type = string }
+
+variable "kms_key" {
+    type = string
+    default = ""
+}
+
+variable "badge_enabled" {
+    type = string
+    default = "false"
+}
+
+variable "webhook_branch_filter" {
+    type = string
+    default = "^(master|develop)$"
+}

+ 9 - 0
base/codebuild_ecr_base/README.md

@@ -0,0 +1,9 @@
+# CodeBuild ECR Base
+
+This module is the building blocks for the AWS CodeBuild projects. No CodeBuild projects should be included in this module. This module is for AWS objects that all or many CodeBuild projects require. 
+
+When starting from scratch, the RHEL image needs to be manually uploaded to ECR. The TF creates the ECR repo.
+
+- Run the TF
+- Upload the RHEL docker images needed for the CodeBuild projects
+

+ 162 - 0
base/codebuild_ecr_base/iam.tf

@@ -0,0 +1,162 @@
+resource "aws_iam_role" "codebuild_role" {
+  name     = "codebuild_role"
+
+  assume_role_policy = <<EOF
+{
+    "Version": "2012-10-17",
+    "Statement": [
+      {
+        "Effect": "Allow",
+        "Principal": {
+          "Service": [
+            "codebuild.amazonaws.com"
+            ]
+        },
+        "Action": "sts:AssumeRole"
+      }
+    ]
+  }
+EOF
+}
+
+resource "aws_iam_role_policy_attachment" "codebuild_role_policy_attach" {
+  role       = aws_iam_role.codebuild_role.name
+  policy_arn = aws_iam_policy.codebuild_policy.arn
+}
+
+# Some things about this policy I'm not perfectly sure about, like
+# should the account number be hardcoded?  Also, it reads like we'll have to
+# update it each time we have a new repository added to codecommit - that
+# or we'll need to authorize the codebuild role to be able to pull from any 
+# codecommit repo.  Which may be fine?
+resource "aws_iam_policy" "codebuild_policy" {
+  name        = "codebuild_policy"
+  description = "Policy for AWS codebuild to build and store artifacts"
+
+  policy = <<EOF
+{
+    "Version": "2012-10-17",
+    "Statement": [
+        {
+            "Effect": "Allow",
+            "Resource": [
+                "arn:${var.aws_partition}:logs:${var.aws_region}:${var.common_services_account}:log-group:/aws/codebuild/*"
+            ],
+            "Action": [
+                "logs:CreateLogGroup",
+                "logs:CreateLogStream",
+                "logs:PutLogEvents"
+            ]
+        },
+        {
+            "Effect": "Allow",
+            "Resource": [
+                "arn:${var.aws_partition}:s3:::codepipeline-${var.aws_region}-*"
+            ],
+            "Action": [
+                "s3:PutObject",
+                "s3:GetObject",
+                "s3:GetObjectVersion"
+            ]
+        },
+        {
+            "Effect": "Allow",
+            "Resource": [
+                "arn:${var.aws_partition}:codecommit:${var.aws_region}:${var.common_services_account}:*"
+            ],
+            "Action": [
+                "codecommit:GitPull"
+            ]
+        },
+        {
+            "Effect": "Allow",
+            "Resource": [
+                "arn:${var.aws_partition}:s3:::xdr-codebuild-artifacts/*",
+                "arn:${var.aws_partition}:s3:::*"
+            ],
+            "Action": [
+                "s3:PutObject",
+                "s3:GetObject*",
+                "s3:ListBucket"
+            ]
+        },
+        {
+            "Effect": "Allow",
+            "Resource": [
+                "*"
+            ],
+            "Action": [
+              "ecr:GetAuthorizationToken",
+              "ecr:BatchCheckLayerAvailability",
+              "ecr:CompleteLayerUpload",
+              "ecr:GetAuthorizationToken",
+              "ecr:InitiateLayerUpload",
+              "ecr:PutImage",
+              "ecr:UploadLayerPart"
+            ]
+        }
+    ]
+}
+EOF
+}
+
+# !!!!!     RETAINED FOR FUTURE USE   !!!!!
+# Defines an IAM user that can only download ECR images, intended for
+# use in POP nodes where we need containers, but won't necessarily have
+# EC2 instance role credentials.  Maybe one day this goes to vault, I
+# hope.   It would be nice.
+
+# data "aws_iam_policy_document" "ecr_policy_pop" {
+#   statement {
+#     sid       = "AllowECRReadOnly"
+#     effect    = "Allow"
+
+#     actions   = [
+#       "ecr:GetAuthorizationToken",
+#       "ecr:BatchCheckLayerAvailability",
+#       "ecr:GetDownloadUrlForLayer",
+#       "ecr:GetRepositoryPolicy",
+#       "ecr:DescribeRepositories",
+#       "ecr:ListImages",
+#       "ecr:DescribeImages",
+#       "ecr:BatchGetImage"
+#     ]
+    
+#     resources = [
+#       "*"
+#     ]
+
+#   }
+# }
+
+# resource "aws_iam_policy" "ecr_policy_pop" {
+#   name   = "ecr_policy_pop"
+#   path   = "/"
+#   policy = "${data.aws_iam_policy_document.ecr_policy_pop.json}"
+# }
+
+# resource "aws_iam_user" "pop_service_account" {
+#   name = "svc-mdrpop"
+#   path = "/service/"
+# }
+
+# resource "aws_iam_user_policy_attachment" "pop_service_account_1" {
+#   user       = "${aws_iam_user.pop_service_account.name}"
+#   policy_arn = "${aws_iam_policy.ecr_policy_pop.arn}"
+# }
+
+
+# resource "aws_iam_access_key" "pop_service_account" {
+#   user    = "${aws_iam_user.pop_service_account.name}"
+#   pgp_key = "${file("../00-organizations-and-iam/duane_waddle.pgp")}"
+# }
+
+# output "pop_service_account_key_id" {
+#   value = "${aws_iam_access_key.pop_service_account.id}"
+# }
+
+# output "pop_service_account_secret" {
+#   value = "${aws_iam_access_key.pop_service_account.encrypted_secret}"
+# }
+
+# !!!!!    END OF RETAINED FOR FUTURE USE   !!!!!

+ 148 - 0
base/codebuild_ecr_base/kms.tf

@@ -0,0 +1,148 @@
+# Codebuild artifacts by rule must be encrypted by a KMS key
+# using the default aws/s3 key doesn't work with cross-account access
+resource "aws_kms_key" "s3_codebuild_artifacts" {
+  description             = "Codebuild Artifacts S3 bucket"
+  enable_key_rotation     = true
+  policy                  = data.aws_iam_policy_document.codebuild_kms_key_encryption_policy.json
+}
+
+resource "aws_kms_alias" "codebuilt-artifacts" {
+  name          = "alias/codebuild-artifacts"
+  target_key_id = aws_kms_key.s3_codebuild_artifacts.key_id
+}
+
+
+data "aws_iam_policy_document" "codebuild_kms_key_encryption_policy" {
+  #policy_id = "key-consolepolicy-3"
+  statement {
+    sid = "Enable IAM User Permissions"
+    effect = "Allow"
+    principals {
+      type = "AWS"
+      identifiers = [ 
+        "arn:${var.aws_partition}:iam::${var.aws_account_id}:role/user/mdr_terraformer",
+        "arn:${var.aws_partition}:iam::${var.aws_account_id}:user/MDRAdmin"
+        ]
+    }
+    actions   = [ "kms:*" ]
+    resources = [ "*" ]
+  }
+
+  statement {
+    sid = "Allow access for Key Administrators"
+    effect = "Allow"
+    principals {
+      type = "AWS"
+      identifiers = [
+        "arn:${var.aws_partition}:iam::${var.aws_account_id}:role/user/mdr_terraformer",
+      ]
+    }
+
+    actions = [
+      "kms:Create*",
+      "kms:Describe*",
+      "kms:Enable*",
+      "kms:List*",
+      "kms:Put*",
+      "kms:Update*",
+      "kms:Revoke*",
+      "kms:Disable*",
+      "kms:Get*",
+      "kms:Delete*",
+      "kms:TagResource",
+      "kms:UntagResource",
+      "kms:ScheduleKeyDeletion",
+      "kms:CancelKeyDeletion"
+    ]
+    resources = [ "*" ]
+  }
+
+  statement {
+    sid =  "Allow use of the key"
+    effect = "Allow"
+    principals {
+      type = "AWS"
+      identifiers = [
+        "arn:${var.aws_partition}:iam::${var.aws_account_id}:role/msoc-default-instance-role"
+      ]
+    }
+    actions = [
+      "kms:Encrypt",
+      "kms:Decrypt",
+      "kms:ReEncrypt*",
+      "kms:GenerateDataKey*",
+      "kms:DescribeKey"
+    ]
+    resources = [ "*" ]
+  }
+
+  statement  {
+    sid = "Allow access through Amazon S3 for all principals in the account that are authorized to use Amazon S3"
+    effect = "Allow"
+    principals {
+      type = "AWS"
+      identifiers = [ "*" ]
+    }
+    actions = [
+        "kms:Encrypt",
+        "kms:Decrypt",
+        "kms:ReEncrypt*",
+        "kms:GenerateDataKey*",
+        "kms:DescribeKey"
+    ]
+    resources = [ "*" ]
+
+    condition {
+      test = "StringEquals"
+      variable = "kms.ViaService"
+      values = [ "s3.${var.aws_region}.amazonaws.com" ]
+    }
+
+    condition {
+      test = "StringEquals"
+      variable = "kms.CallerAccount"
+      values = [ var.aws_account_id ]
+    }
+  }
+
+  statement  {
+    sid = "Allow access from the codebuild role"
+    effect = "Allow"
+    principals {
+      type = "AWS"
+    
+      # FIXME this needs to be a better role by far
+      identifiers = [ aws_iam_role.codebuild_role.arn ]
+    }
+    actions = [
+      "kms:Encrypt",
+      "kms:Decrypt",
+      "kms:ReEncrypt*",
+      "kms:GenerateDataKey*",
+      "kms:DescribeKey"
+    ]
+    resources = [ "*" ]
+  }
+  
+  statement {
+    sid = "Allow attachment of persistent resources"
+    effect = "Allow"
+    principals {
+      type = "AWS"
+      identifiers = [
+        "arn:${var.aws_partition}:iam::${var.aws_account_id}:role/msoc-default-instance-role"
+      ]
+    }
+    actions = [
+      "kms:CreateGrant",
+      "kms:ListGrants",
+      "kms:RevokeGrant"
+    ]
+    resources = [ "*" ]
+    condition {
+      test = "Bool"
+      variable =  "kms:GrantIsForAWSResource"
+      values = [ "true" ]
+      }
+    }
+}

+ 63 - 0
base/codebuild_ecr_base/main.tf

@@ -0,0 +1,63 @@
+
+#Base RHEL repository used for building XDR RPMs like syslog-ng in CodeBuild
+resource "aws_ecr_repository" "codebuild-rhel7" {
+  name  = "codebuild-rhel7"
+  tags = merge(var.standard_tags, var.tags)
+}
+
+#Allow codebuild to access the ECR Repository
+resource "aws_ecr_repository_policy" "codebuild-rhel7" {
+  repository = aws_ecr_repository.codebuild-rhel7.name
+
+  policy = <<EOF
+{
+    "Version": "2008-10-17",
+    "Statement": [
+        {
+            "Sid": "new statement",
+            "Effect": "Allow",
+            "Principal": {
+                "Service": "codebuild.amazonaws.com"
+            },
+            "Action": [
+                "ecr:GetDownloadUrlForLayer",
+                "ecr:BatchGetImage",
+                "ecr:BatchCheckLayerAvailability"
+            ]
+        }
+    ]
+}
+EOF
+}
+
+# not needed, but leaving the code for possible future use. 
+# #base centos7 image used for building portal
+# resource "aws_ecr_repository" "codebuild-centos7" {
+#   name     = "codebuild-centos7"
+#   tags = merge(var.standard_tags, var.tags)
+# }
+
+# #Allow codebuild to access the ECR Repository
+# resource "aws_ecr_repository_policy" "codebuild-centos7" {
+#   repository = aws_ecr_repository.codebuild-centos7.name
+
+#   policy = <<EOF
+# {
+#     "Version": "2008-10-17",
+#     "Statement": [
+#         {
+#             "Sid": "new statement",
+#             "Effect": "Allow",
+#             "Principal": {
+#                 "Service": "codebuild.amazonaws.com"
+#             },
+#             "Action": [
+#                 "ecr:GetDownloadUrlForLayer",
+#                 "ecr:BatchGetImage",
+#                 "ecr:BatchCheckLayerAvailability"
+#             ]
+#         }
+#     ]
+# }
+# EOF
+# }

+ 19 - 0
base/codebuild_ecr_base/outputs.tf

@@ -0,0 +1,19 @@
+output service_role {
+  value = aws_iam_role.codebuild_role.arn
+}
+
+output kms_key {
+  value = aws_kms_key.s3_codebuild_artifacts.arn
+}
+
+output artifact_s3_bucket {
+  value = aws_s3_bucket.artifacts.id
+}
+
+# output codebuild_image_centos7 {
+#   value = aws_ecr_repository.codebuild-centos7.repository_url
+# }
+
+output codebuild_image_rhel7 {
+  value = aws_ecr_repository.codebuild-rhel7.repository_url
+}

+ 34 - 0
base/codebuild_ecr_base/s3.tf

@@ -0,0 +1,34 @@
+#S3 bucket for codebuild output
+resource "aws_s3_bucket" "artifacts" {
+  bucket        = "xdr-codebuild-artifacts"
+  force_destroy = true
+  acl           = "private"
+
+  server_side_encryption_configuration {
+    rule {
+      apply_server_side_encryption_by_default {
+        kms_master_key_id = aws_kms_key.s3_codebuild_artifacts.arn
+        sse_algorithm     = "aws:kms"
+      }
+    }
+  }
+}
+
+resource "aws_s3_bucket_policy" "artifacts" {
+  bucket = aws_s3_bucket.artifacts.id
+  policy = data.aws_iam_policy_document.artifacts.json
+}
+
+data "aws_iam_policy_document" "artifacts" {
+  statement {
+    sid = "AllowS3Access"
+    actions = [ "s3:GetObject", "s3:GetObjectVersion" ]
+    effect = "Allow"
+    resources = [ "${aws_s3_bucket.artifacts.arn}/*" ]
+    principals {
+      type = "AWS"
+      identifiers = [ for a in var.responsible_accounts[var.environment]: "arn:${var.aws_partition}:iam::${a}:root" ]
+    }
+  }
+}
+

+ 13 - 0
base/codebuild_ecr_base/vars.tf

@@ -0,0 +1,13 @@
+variable "tags" {
+  description = "Tags to add to the resource (in addition to global standard tags)"
+  type        = map
+  default     = { }
+}
+variable "standard_tags" { type = map }
+variable "environment" { type = string }
+variable "aws_partition" { type = string }
+variable "aws_region" { type = string }
+variable "aws_partition_alias" { type = string }
+variable "aws_account_id" { type = string }
+variable "common_services_account" { type = string }
+variable "responsible_accounts" { type = map(list(string)) }

+ 17 - 0
base/codebuild_ecr_customer_portal/README.md

@@ -0,0 +1,17 @@
+# How to Use this Module
+
+Customer Portal was different enough that it needed its own module. 
+
+This module is where the CodeBuild projects are created. It uses the Terraform GitHub Provider and requires a Personal Access Token. This should be your Personal Access Token not mdr-aws-codebuild's token. The provider will look in the environmental variables for the token. 
+
+```
+export GITHUB_TOKEN=<gihub_token>
+```
+
+This module should NOT create the github repo. That is a manual process. I am not comfortable with terraform adding/removing github repos. The github repo should have the same name as the name variable in the terrafgrunt.hcl file. 
+
+## Github Service Account ( mdr-aws-codebuild )
+
+AWS CodeBuild needs a Github Personal Access Token to pull code after the code in a repository has been updated. Terraform is capable of storing the Github Personal Access Token, but that is a bad idea. A better idea is a service account in Github that gives CodeBuild access to specific repositories. This user will need access to repositories in different organizations. The login credentials as well as the Personal Access Token for mdr-aws-codebuild are stored in Vault. 
+
+The service account (mdr-aws-codebuild) needs to have a personal access token manually placed into the aws console. 

+ 94 - 0
base/codebuild_ecr_customer_portal/main.tf

@@ -0,0 +1,94 @@
+data "github_repository" "this" {
+    name    = var.name
+}
+
+resource "aws_codebuild_project" "this_no_artifact" {
+  count                 = var.artifact_s3_bucket=="" ? 1 : 0
+
+  name                  = var.name
+  description           = "Container for ${var.name}"
+  service_role          = var.service_role
+  encryption_key        = var.kms_key
+  badge_enabled         = var.badge_enabled
+
+  source {
+    type                = "GITHUB_ENTERPRISE"
+    location            = data.github_repository.this.http_clone_url
+    report_build_status = true
+  }
+
+  environment {
+    compute_type        = "BUILD_GENERAL1_SMALL"
+    image               = var.codebuild_image
+    type                = "LINUX_CONTAINER"
+    privileged_mode     = true
+  }
+
+  artifacts {
+    type                = "NO_ARTIFACTS"
+  }
+
+  tags = merge(var.standard_tags, var.tags)
+}
+ 
+resource "aws_ecr_repository" "this-api" {
+    name  = "portal-api"
+}
+
+resource "aws_ecr_repository" "this-nginx" {
+    name  = "portal-nginx"
+}
+
+data "aws_iam_policy_document" "ecr_cross_account_policy" {
+  statement {
+    sid = "ECRWrite"
+    effect = "Allow"
+    actions = [
+      "ecr:GetAuthorizationToken",
+      "ecr:GetDownloadUrlForLayer",
+      "ecr:BatchGetImage",
+      "ecr:BatchCheckLayerAvailability",
+      "ecr:PutImage",
+      "ecr:InitiateLayerUpload",
+      "ecr:UploadLayerPart",
+      "ecr:CompleteLayerUpload",
+      "ecr:DescribeRepositories",
+      "ecr:ListImages",
+      "ecr:DescribeImages",
+    ]
+    principals {
+      identifiers = [ for a in var.responsible_accounts[var.environment]: "arn:${var.aws_partition}:iam::${a}:root" ]
+      type        = "AWS"
+    }
+  }
+}
+
+resource "aws_ecr_repository_policy" "this-api" {
+  repository = aws_ecr_repository.this-api.name
+  policy = data.aws_iam_policy_document.ecr_cross_account_policy.json
+}
+
+resource "aws_ecr_repository_policy" "this-nginx" {
+  repository = aws_ecr_repository.this-nginx.name
+  policy = data.aws_iam_policy_document.ecr_cross_account_policy.json
+}
+
+resource "aws_codebuild_webhook" "this" {
+  project_name  = var.name
+  branch_filter = var.webhook_branch_filter
+
+  depends_on = [ aws_codebuild_project.this_no_artifact  ]
+}
+
+resource "github_repository_webhook" "this" {
+  active     = true
+  events     = ["push"]
+  repository = data.github_repository.this.name
+
+  configuration {
+    url          = aws_codebuild_webhook.this.payload_url
+    secret       = aws_codebuild_webhook.this.secret
+    content_type = "json"
+    insecure_ssl = false
+  }
+}

+ 32 - 0
base/codebuild_ecr_customer_portal/vars.tf

@@ -0,0 +1,32 @@
+variable "tags" {
+  description = "Tags to add to the resource (in addition to global standard tags)"
+  type        = map
+  default     = { }
+}
+variable "standard_tags" { type = map }
+variable "environment" { type = string }
+variable "aws_partition" { type = string }
+variable "aws_partition_alias" { type = string }
+variable "aws_region" { type = string }
+variable "aws_account_id" { type = string }
+variable "common_services_account" { type = string }
+variable "responsible_accounts" { type = map(list(string)) }
+variable "name" { type = string }
+variable "service_role" { type = string }
+variable "artifact_s3_bucket" { type = string }
+variable "codebuild_image" {type = string }
+
+variable "kms_key" {
+    type = string
+    default = ""
+}
+
+variable "badge_enabled" {
+    type = string
+    default = "false"
+}
+
+variable "webhook_branch_filter" {
+    type = string
+    default = "^(master|develop)$"
+}

+ 15 - 0
base/codebuild_ecr_project/README.md

@@ -0,0 +1,15 @@
+# How to Use this Module
+
+This module is where the CodeBuild projects are created. It uses the Terraform GitHub Provider and requires a Personal Access Token. This should be your Personal Access Token not mdr-aws-codebuild's token. The provider will look in the environmental variables for the token. 
+
+```
+export GITHUB_TOKEN=<gihub_token>
+```
+
+This module should NOT create the github repo. That is a manual process. I am not comfortable with terraform adding/removing github repos. The github repo should have the same name as the name variable in the terrafgrunt.hcl file. The user associated with the Personal Access Token needs to have admin permissions on the github repo. 
+
+## Github Service Account ( mdr-aws-codebuild )
+
+AWS CodeBuild needs a Github Personal Access Token to pull code after the code in a repository has been updated. Terraform is capable of storing the Github Personal Access Token, but that is a bad idea. A better idea is a service account in Github that gives CodeBuild access to specific repositories. This user will need access to repositories in different organizations. The login credentials as well as the Personal Access Token for mdr-aws-codebuild are stored in Vault. 
+
+The service account (mdr-aws-codebuild) needs to have a personal access token manually placed into the aws console. 

+ 88 - 0
base/codebuild_ecr_project/main.tf

@@ -0,0 +1,88 @@
+data "github_repository" "this" {
+    name    = var.name
+}
+
+resource "aws_codebuild_project" "this_no_artifact" {
+  count                 = var.artifact_s3_bucket=="" ? 1 : 0
+
+  name                  = var.name
+  description           = "Container for ${var.name}"
+  service_role          = var.service_role
+  encryption_key        = var.kms_key
+  badge_enabled         = var.badge_enabled
+
+  source {
+    type                = "GITHUB_ENTERPRISE"
+    location            = data.github_repository.this.http_clone_url
+    report_build_status = true
+    git_submodules_config {
+      fetch_submodules = false
+    }
+  }
+
+  environment {
+    compute_type        = "BUILD_GENERAL1_SMALL"
+    image               = var.codebuild_image
+    type                = "LINUX_CONTAINER"
+    privileged_mode     = true
+  }
+
+  artifacts {
+    type                = "NO_ARTIFACTS"
+  }
+
+  tags = merge(var.standard_tags, var.tags)
+}
+ 
+resource "aws_ecr_repository" "this" {
+    name  = var.name
+}
+
+data "aws_iam_policy_document" "ecr_cross_account_policy" {
+  statement {
+    sid = "ECRWrite"
+    effect = "Allow"
+    actions = [
+      "ecr:GetAuthorizationToken",
+      "ecr:GetDownloadUrlForLayer",
+      "ecr:BatchGetImage",
+      "ecr:BatchCheckLayerAvailability",
+      "ecr:PutImage",
+      "ecr:InitiateLayerUpload",
+      "ecr:UploadLayerPart",
+      "ecr:CompleteLayerUpload",
+      "ecr:DescribeRepositories",
+      "ecr:ListImages",
+      "ecr:DescribeImages",
+    ]
+    principals {
+      type = "AWS"
+      identifiers = [ for a in var.responsible_accounts[var.environment]: "arn:${var.aws_partition}:iam::${a}:root" ]
+    }
+  }
+}
+
+resource "aws_ecr_repository_policy" "this" {
+  repository = aws_ecr_repository.this.name
+  policy = data.aws_iam_policy_document.ecr_cross_account_policy.json
+}
+
+resource "aws_codebuild_webhook" "this" {
+  project_name  = var.name
+  branch_filter = var.webhook_branch_filter
+
+  depends_on = [ aws_codebuild_project.this_no_artifact ]
+}
+
+resource "github_repository_webhook" "this" {
+  active     = true
+  events     = ["push"]
+  repository = data.github_repository.this.name
+
+  configuration {
+    url          = aws_codebuild_webhook.this.payload_url
+    secret       = aws_codebuild_webhook.this.secret
+    content_type = "json"
+    insecure_ssl = false
+  }
+}

+ 29 - 0
base/codebuild_ecr_project/vars.tf

@@ -0,0 +1,29 @@
+variable "tags" {
+  description = "Tags to add to the resource (in addition to global standard tags)"
+  type        = map
+  default     = { }
+}
+variable "standard_tags" { type = map }
+variable "environment" { type = string }
+variable "aws_partition" { type = string }
+variable "aws_partition_alias" { type = string }
+variable "aws_account_id" { type = string }
+variable "name" { type = string }
+variable "service_role" { type = string }
+variable "artifact_s3_bucket" { type = string }
+variable "codebuild_image" {type = string }
+
+variable "kms_key" {
+    type = string
+    default = ""
+}
+
+variable "badge_enabled" {
+    type = string
+    default = "false"
+}
+
+variable "webhook_branch_filter" {
+    type = string
+    default = "^(master|develop)$"
+}