From f2db62d6021a29bdcf5dc322203e29ba90674506 Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Sat, 13 Jul 2024 13:21:27 +0100 Subject: [PATCH 01/18] DP-187 Provision Orchestrator's core componenets - Update Github workflow (locked to the feature branch for now) --- .github/workflows/main-build-test-deploy.yaml | 143 ++++++++++++++++++ .../{build.yml => main-pr-check.yml} | 15 +- docs/Makefile | 8 + .../common/networking/terragrunt.hcl | 2 +- .../components/core/networking/terragrunt.hcl | 2 +- .../core/security-groups/terragrunt.hcl | 2 +- .../orchestrator/ecr/terragrunt.hcl | 31 ++++ .../orchestrator/iam/terragrunt.hcl | 26 ++++ .../components/orchestrator/orchestrator.hcl | 9 ++ .../service/api-gateway/terragrunt.hcl | 2 +- .../service/database/terragrunt.hcl | 2 +- .../components/service/ecs/terragrunt.hcl | 2 +- .../service/telemetry/terragrunt.hcl | 2 +- terragrunt/components/terragrunt.hcl | 22 +++ terragrunt/modules/core-iam/ci-datasource.tf | 3 + terragrunt/modules/core-iam/ci.tf | 3 + .../modules/orchestrator/ecr/datasource.tf | 75 +++++++++ terragrunt/modules/orchestrator/ecr/iam.tf | 7 + terragrunt/modules/orchestrator/ecr/locals.tf | 14 ++ terragrunt/modules/orchestrator/ecr/main.tf | 12 ++ .../modules/orchestrator/ecr/variables.tf | 34 +++++ .../modules/orchestrator/iam/ci-datasource.tf | 1 + terragrunt/modules/orchestrator/iam/ci.tf | 1 + .../modules/orchestrator/iam/datasource.tf | 45 ++++++ terragrunt/modules/orchestrator/iam/github.tf | 20 +++ terragrunt/modules/orchestrator/iam/locals.tf | 3 + .../modules/orchestrator/iam/outputs.tf | 12 ++ .../modules/orchestrator/iam/variables.tf | 23 +++ 28 files changed, 502 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/main-build-test-deploy.yaml rename .github/workflows/{build.yml => main-pr-check.yml} (82%) create mode 100644 terragrunt/components/orchestrator/ecr/terragrunt.hcl create mode 100644 terragrunt/components/orchestrator/iam/terragrunt.hcl create mode 100644 terragrunt/components/orchestrator/orchestrator.hcl create mode 100644 terragrunt/modules/orchestrator/ecr/datasource.tf create mode 100644 terragrunt/modules/orchestrator/ecr/iam.tf create mode 100644 terragrunt/modules/orchestrator/ecr/locals.tf create mode 100644 terragrunt/modules/orchestrator/ecr/main.tf create mode 100644 terragrunt/modules/orchestrator/ecr/variables.tf create mode 120000 terragrunt/modules/orchestrator/iam/ci-datasource.tf create mode 120000 terragrunt/modules/orchestrator/iam/ci.tf create mode 100644 terragrunt/modules/orchestrator/iam/datasource.tf create mode 100644 terragrunt/modules/orchestrator/iam/github.tf create mode 100644 terragrunt/modules/orchestrator/iam/locals.tf create mode 100644 terragrunt/modules/orchestrator/iam/outputs.tf create mode 100644 terragrunt/modules/orchestrator/iam/variables.tf diff --git a/.github/workflows/main-build-test-deploy.yaml b/.github/workflows/main-build-test-deploy.yaml new file mode 100644 index 000000000..641beee44 --- /dev/null +++ b/.github/workflows/main-build-test-deploy.yaml @@ -0,0 +1,143 @@ +name: CI/CD Pipeline + +on: + push: + branches: [DP-187] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Build .NET Project + run: | + dotnet tool restore + dotnet restore + dotnet build + + - name: Build Docker Images + run: make build-docker + + - name: Save Docker Images + run: | + docker save -o cdp-images.tar cabinetoffice/cdp-organisation-information-migrations:latest cabinetoffice/cdp-data-sharing:latest cabinetoffice/cdp-entity-verification:latest cabinetoffice/cdp-forms:latest cabinetoffice/cdp-organisation-app:latest cabinetoffice/cdp-organisation:latest cabinetoffice/cdp-person:latest cabinetoffice/cdp-tenant:latest cabinetoffice/cdp-authority:latest + + - name: Upload Docker Images as Artifacts + uses: actions/upload-artifact@v4 + with: + name: docker-images + path: cdp-images.tar + + test: + runs-on: ubuntu-latest + needs: build + env: + CDP_ORGANISATION_APP_PORT: 8888 + CDP_TENANT_PORT: 8811 + CDP_ORGANISATION_PORT: 8822 + CDP_PERSON_PORT: 8833 + CDP_FORMS_PORT: 8844 + CDP_DATA_SHARING_PORT: 8855 + + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Download Docker Images + uses: actions/download-artifact@v4 + with: + name: docker-images + + - name: Load Docker Images + run: docker load -i cdp-images.tar + + - name: Start services + run: make up + + - name: Run Tests + run: | + dotnet test --logger trx --results-directory TestResults + + - name: Stop services + run: make down + + deploy: + runs-on: ubuntu-latest + needs: test + if: github.ref == 'refs/heads/DP-187' && github.repository_owner == 'cabinetoffice' + + steps: + - uses: actions/checkout@v4 + + - name: Download Docker Images + uses: actions/download-artifact@v4 + with: + name: docker-images + + - name: Load Docker Images + run: docker load -i cdp-images.tar + + - name: Set up AWS CLI + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: eu-west-2 + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + + - name: Generate Image Version + id: image_version + run: | + IMAGE_VERSION=$(date +%Y%m%d)-$(git rev-parse --short HEAD) + echo "IMAGE_VERSION=$IMAGE_VERSION" >> $GITHUB_ENV + + - name: Tag and Push Docker Images + run: | + for image in cabinetoffice/cdp-organisation-information-migrations cabinetoffice/cdp-data-sharing cabinetoffice/cdp-entity-verification cabinetoffice/cdp-forms cabinetoffice/cdp-organisation-app cabinetoffice/cdp-organisation cabinetoffice/cdp-person cabinetoffice/cdp-tenant cabinetoffice/cdp-authority; do + CLEAN_IMAGE_NAME=$(echo $image | sed 's/^cabinetoffice\///') + docker tag $image:latest ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-west-2.amazonaws.com/$CLEAN_IMAGE_NAME:${{ env.IMAGE_VERSION }} + docker push ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-west-2.amazonaws.com/$CLEAN_IMAGE_NAME:${{ env.IMAGE_VERSION }} + done + + - name: Create Git Tag + run: | + git config --global user.name "github-actions" + git config --global user.email "github-actions@github.com" + git tag ${{ env.IMAGE_VERSION }} + git push origin ${{ env.IMAGE_VERSION }} + + - name: Store Version in SSM Parameter Store + run: | + aws ssm put-parameter --name "cdp-sirsi-service-version" --value "${{ env.IMAGE_VERSION }}" --type String --overwrite + + document: + runs-on: ubuntu-latest + name: Publish documentation + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Build + run: cd docs && make build + - name: Publish + if: github.ref == 'refs/heads/DP-187' && github.repository_owner == 'cabinetoffice' + run: cd docs && make publish-docs-during-cd + - name: Upload Documentation + uses: actions/upload-artifact@v4 + with: + name: Documentation + path: docs/build/* diff --git a/.github/workflows/build.yml b/.github/workflows/main-pr-check.yml similarity index 82% rename from .github/workflows/build.yml rename to .github/workflows/main-pr-check.yml index 02fbd511a..a3d072438 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/main-pr-check.yml @@ -1,9 +1,8 @@ name: Build on: - push: - branches: [main] pull_request: + branches: [DP-187] jobs: test: @@ -61,20 +60,12 @@ jobs: - name: Stop services run: make down - docs: + document: runs-on: ubuntu-latest - name: Build documentation + name: Publish documentation steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build run: cd docs && make build - - name: Publish - if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' - run: cd docs && make publish - - name: Upload Documentation - uses: actions/upload-artifact@v4 - with: - name: Documentation - path: docs/build/* diff --git a/docs/Makefile b/docs/Makefile index 90b5d1970..5744919b4 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -15,6 +15,14 @@ publish: build/cdp.html git add index.html && git commit -m 'Update the documentation' && git push origin gh-pages .PHONY: publish +publish-docs-during-cd: build/cdp.html + git config --global user.name 'github-actions' + git config --global user.email 'github-actions@github.com' + git checkout gh-pages + cp build/cdp.html index.html + git add index.html && git commit -m 'Update the documentation' && git push origin gh-pages +.PHONY: publish-docs-during-cd + build-docker: docker build -t cabinetoffice/asciidoctor . .PHONY: build-docker diff --git a/terragrunt/components/common/networking/terragrunt.hcl b/terragrunt/components/common/networking/terragrunt.hcl index 4641d1d18..be80c736a 100644 --- a/terragrunt/components/common/networking/terragrunt.hcl +++ b/terragrunt/components/common/networking/terragrunt.hcl @@ -1,5 +1,5 @@ terraform { - source = "../../../modules//networking" + source = local.global_vars.locals.environment != "orchestrator" ? "../../../modules//networking" : null } include { diff --git a/terragrunt/components/core/networking/terragrunt.hcl b/terragrunt/components/core/networking/terragrunt.hcl index e67f5cee3..ff76130e5 100644 --- a/terragrunt/components/core/networking/terragrunt.hcl +++ b/terragrunt/components/core/networking/terragrunt.hcl @@ -1,5 +1,5 @@ terraform { - source = "../../../modules//core-networking" + source = local.global_vars.locals.environment != "orchestrator" ? "../../../modules//core-networking" : null } include { diff --git a/terragrunt/components/core/security-groups/terragrunt.hcl b/terragrunt/components/core/security-groups/terragrunt.hcl index 30114376b..4deb53cb5 100644 --- a/terragrunt/components/core/security-groups/terragrunt.hcl +++ b/terragrunt/components/core/security-groups/terragrunt.hcl @@ -1,5 +1,5 @@ terraform { - source = "../../../modules//core-security-groups" + source = local.global_vars.locals.environment != "orchestrator" ? "../../../modules//core-security-groups" : null } include { diff --git a/terragrunt/components/orchestrator/ecr/terragrunt.hcl b/terragrunt/components/orchestrator/ecr/terragrunt.hcl new file mode 100644 index 000000000..7de2c9588 --- /dev/null +++ b/terragrunt/components/orchestrator/ecr/terragrunt.hcl @@ -0,0 +1,31 @@ +terraform { + source = local.global_vars.locals.environment == "orchestrator" ? "../../../modules//orchestrator/ecr" : null +} + +include { + path = find_in_parent_folders() +} + +locals { + + global_vars = read_terragrunt_config(find_in_parent_folders("terragrunt.hcl")) + core_vars = read_terragrunt_config(find_in_parent_folders("orchestrator.hcl")) + + tags = merge( + local.global_vars.inputs.tags, + local.core_vars.inputs.tags, + { + component = "orchestrator-ecr" + } + ) + + account_ids = { + for name, env in local.global_vars.locals.environments : name => env.account_id + } +} + +inputs = { + account_ids = local.account_ids + service_configs = local.global_vars.locals.service_configs + tags = local.tags +} diff --git a/terragrunt/components/orchestrator/iam/terragrunt.hcl b/terragrunt/components/orchestrator/iam/terragrunt.hcl new file mode 100644 index 000000000..38e3a2569 --- /dev/null +++ b/terragrunt/components/orchestrator/iam/terragrunt.hcl @@ -0,0 +1,26 @@ +terraform { + source = local.global_vars.locals.environment == "orchestrator" ? "../../../modules//orchestrator/iam" : null +} + +include { + path = find_in_parent_folders() +} + +locals { + + global_vars = read_terragrunt_config(find_in_parent_folders("terragrunt.hcl")) + core_vars = read_terragrunt_config(find_in_parent_folders("orchestrator.hcl")) + + tags = merge( + local.global_vars.inputs.tags, + local.core_vars.inputs.tags, + { + component = "orchestrator-iam" + } + ) +} + +inputs = { + tags = local.tags + terraform_operators = local.global_vars.locals.terraform_operators +} diff --git a/terragrunt/components/orchestrator/orchestrator.hcl b/terragrunt/components/orchestrator/orchestrator.hcl new file mode 100644 index 000000000..d814bde32 --- /dev/null +++ b/terragrunt/components/orchestrator/orchestrator.hcl @@ -0,0 +1,9 @@ +locals { + tags = { + component_root = "orchestrator" + } +} + +inputs = { + tags = local.tags +} diff --git a/terragrunt/components/service/api-gateway/terragrunt.hcl b/terragrunt/components/service/api-gateway/terragrunt.hcl index 09cf106ff..d56f10253 100644 --- a/terragrunt/components/service/api-gateway/terragrunt.hcl +++ b/terragrunt/components/service/api-gateway/terragrunt.hcl @@ -1,5 +1,5 @@ terraform { - source = "../../../modules//api-gateway" + source = local.global_vars.locals.environment != "orchestrator" ? "../../../modules//api-gateway" : null } include { diff --git a/terragrunt/components/service/database/terragrunt.hcl b/terragrunt/components/service/database/terragrunt.hcl index 58e7b4efe..c85aecace 100644 --- a/terragrunt/components/service/database/terragrunt.hcl +++ b/terragrunt/components/service/database/terragrunt.hcl @@ -1,5 +1,5 @@ terraform { - source = "../../../modules//database" + source = local.global_vars.locals.environment != "orchestrator" ? "../../../modules//database" : null } include { diff --git a/terragrunt/components/service/ecs/terragrunt.hcl b/terragrunt/components/service/ecs/terragrunt.hcl index f52d3a17a..969ad6792 100644 --- a/terragrunt/components/service/ecs/terragrunt.hcl +++ b/terragrunt/components/service/ecs/terragrunt.hcl @@ -1,5 +1,5 @@ terraform { - source = "../../../modules//ecs" + source = local.global_vars.locals.environment != "orchestrator" ? "../../../modules//ecs" : null } include { diff --git a/terragrunt/components/service/telemetry/terragrunt.hcl b/terragrunt/components/service/telemetry/terragrunt.hcl index a875e8e85..d5bf583e6 100644 --- a/terragrunt/components/service/telemetry/terragrunt.hcl +++ b/terragrunt/components/service/telemetry/terragrunt.hcl @@ -1,5 +1,5 @@ terraform { - source = "../../../modules//telemetry" + source = local.global_vars.locals.environment != "orchestrator" ? "../../../modules//telemetry" : null } include { diff --git a/terragrunt/components/terragrunt.hcl b/terragrunt/components/terragrunt.hcl index 8341d3b46..22f95938e 100644 --- a/terragrunt/components/terragrunt.hcl +++ b/terragrunt/components/terragrunt.hcl @@ -2,14 +2,33 @@ locals { cidr_b_development = 3 cidr_b_integration = 4 + cidr_b_orchestrator = 5 cidr_b_production = 1 cidr_b_staging = 2 environment = get_env("TG_ENVIRONMENT", "development") environments = { + orchestrator = { + cidr_block = "10.${local.cidr_b_orchestrator}.0.0/16" + account_id = 891377225335 + name = "orchestrator" + postgres_instance_type = "db.t4g.micro" + private_subnets = [ + "10.${local.cidr_b_orchestrator}.101.0/24", + "10.${local.cidr_b_orchestrator}.102.0/24", + "10.${local.cidr_b_orchestrator}.103.0/24" + ] + public_subnets = [ + "10.${local.cidr_b_orchestrator}.1.0/24", + "10.${local.cidr_b_orchestrator}.2.0/24", + "10.${local.cidr_b_orchestrator}.3.0/24" + ] + top_level_domain = "findatender.codatt.net" + } development = { cidr_block = "10.${local.cidr_b_development}.0.0/16" + account_id = 471112892058 name = "dev" postgres_instance_type = "db.t4g.micro" private_subnets = [ @@ -26,6 +45,7 @@ locals { } staging = { cidr_block = "10.${local.cidr_b_staging}.0.0/16" + account_id = 905418042182 name = "staging" postgres_instance_type = "db.t4g.micro" private_subnets = [ @@ -42,6 +62,7 @@ locals { } integration = { cidr_block = "10.${local.cidr_b_integration}.0.0/16" + account_id = 767397666448 name = "integration" postgres_instance_type = "db.t4g.micro" private_subnets = [ @@ -58,6 +79,7 @@ locals { } production = { cidr_block = "10.${local.cidr_b_production}.0.0/16" + account_id = 471112843276 name = "production" postgres_instance_type = "db.t4g.micro" private_subnets = [ diff --git a/terragrunt/modules/core-iam/ci-datasource.tf b/terragrunt/modules/core-iam/ci-datasource.tf index 411a9d3d9..876389d09 100644 --- a/terragrunt/modules/core-iam/ci-datasource.tf +++ b/terragrunt/modules/core-iam/ci-datasource.tf @@ -1,3 +1,6 @@ +# Note! +# Resources in this file are shared with orchestrator/iam module + data "aws_iam_policy_document" "terraform_assume" { statement { actions = ["sts:AssumeRole"] diff --git a/terragrunt/modules/core-iam/ci.tf b/terragrunt/modules/core-iam/ci.tf index 4af0333b9..d2ffdc497 100644 --- a/terragrunt/modules/core-iam/ci.tf +++ b/terragrunt/modules/core-iam/ci.tf @@ -1,3 +1,6 @@ +# Note! +# Resources in this file are shared with orchestrator/iam module + resource "aws_iam_role" "terraform" { assume_role_policy = data.aws_iam_policy_document.terraform_assume.json name = "${local.name_prefix}-${var.environment}-terraform" diff --git a/terragrunt/modules/orchestrator/ecr/datasource.tf b/terragrunt/modules/orchestrator/ecr/datasource.tf new file mode 100644 index 000000000..bba4fe0f8 --- /dev/null +++ b/terragrunt/modules/orchestrator/ecr/datasource.tf @@ -0,0 +1,75 @@ +data "aws_caller_identity" "current" {} + +data "aws_organizations_organization" "this" {} + +data "aws_iam_policy_document" "ecr_repo_policy_document" { + statement { + sid = "ECRRead" + + principals { + type = "AWS" + identifiers = local.read_principals + } + actions = [ + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:GetRepositoryPolicy", + "ecr:DescribeRepositories", + "ecr:ListImages", + "ecr:DescribeImages", + "ecr:BatchGetImage", + ] + } + + statement { + sid = "ECRPull" + effect = "Allow" + principals { + type = "*" + identifiers = ["*"] + } + + condition { + test = "StringLike" + variable = "aws:PrincipalOrgID" + values = [data.aws_organizations_organization.this.id] + } + + actions = [ + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:GetRepositoryPolicy", + "ecr:DescribeRepositories", + "ecr:ListImages", + "ecr:DescribeImages", + "ecr:BatchGetImage", + ] + } + + 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 = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + type = "AWS" + } + } +} diff --git a/terragrunt/modules/orchestrator/ecr/iam.tf b/terragrunt/modules/orchestrator/ecr/iam.tf new file mode 100644 index 000000000..52f184aaa --- /dev/null +++ b/terragrunt/modules/orchestrator/ecr/iam.tf @@ -0,0 +1,7 @@ +resource "aws_ecr_repository_policy" "policy" { + for_each = toset(local.repositories) + + repository = aws_ecr_repository.this[each.key].name + + policy = data.aws_iam_policy_document.ecr_repo_policy_document.json +} diff --git a/terragrunt/modules/orchestrator/ecr/locals.tf b/terragrunt/modules/orchestrator/ecr/locals.tf new file mode 100644 index 000000000..f7cf49712 --- /dev/null +++ b/terragrunt/modules/orchestrator/ecr/locals.tf @@ -0,0 +1,14 @@ +locals { + + name_prefix = var.product.resource_name + + read_principals = [for name, id in var.account_ids : "arn:aws:iam::${id}:root"] + + repositories = concat( + [ + for name, config in var.service_configs : + config.name + ], + ["cdp-grafana"]) + +} diff --git a/terragrunt/modules/orchestrator/ecr/main.tf b/terragrunt/modules/orchestrator/ecr/main.tf new file mode 100644 index 000000000..ede436c27 --- /dev/null +++ b/terragrunt/modules/orchestrator/ecr/main.tf @@ -0,0 +1,12 @@ +resource "aws_ecr_repository" "this" { + for_each = toset(local.repositories) + + name = "cdp-${each.value}" + image_tag_mutability = "IMMUTABLE" + + image_scanning_configuration { + scan_on_push = true + } + + tags = var.tags +} diff --git a/terragrunt/modules/orchestrator/ecr/variables.tf b/terragrunt/modules/orchestrator/ecr/variables.tf new file mode 100644 index 000000000..eb676dbf8 --- /dev/null +++ b/terragrunt/modules/orchestrator/ecr/variables.tf @@ -0,0 +1,34 @@ +variable "account_ids" { + description = "Map of all accounts and their IDs" + type = map(string) +} + +variable "environment" { + description = "The environment we are provisioning" + type = string +} + +variable "product" { + description = "product's common attributes" + type = object({ + name = string + resource_name = string + public_hosted_zone = string + }) +} + +variable "service_configs" { + description = "Map of services to their ports" + type = map(object({ + cpu = number + memory = number + name = string + port = number + port_host = number + })) +} + +variable "tags" { + description = "Tags to apply to all resources in this module" + type = map(string) +} diff --git a/terragrunt/modules/orchestrator/iam/ci-datasource.tf b/terragrunt/modules/orchestrator/iam/ci-datasource.tf new file mode 120000 index 000000000..c4f324399 --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/ci-datasource.tf @@ -0,0 +1 @@ +../../core-iam/ci-datasource.tf \ No newline at end of file diff --git a/terragrunt/modules/orchestrator/iam/ci.tf b/terragrunt/modules/orchestrator/iam/ci.tf new file mode 120000 index 000000000..ac040b6c8 --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/ci.tf @@ -0,0 +1 @@ +../../core-iam/ci.tf \ No newline at end of file diff --git a/terragrunt/modules/orchestrator/iam/datasource.tf b/terragrunt/modules/orchestrator/iam/datasource.tf new file mode 100644 index 000000000..fbf8c87e2 --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/datasource.tf @@ -0,0 +1,45 @@ +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + +data "aws_iam_policy_document" "ecr_push_policy" { + statement { + actions = [ + "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:CompleteLayerUpload", + "ecr:GetDownloadUrlForLayer", + "ecr:InitiateLayerUpload", + "ecr:PutImage", + "ecr:UploadLayerPart", + ] + resources = [ + "arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/cdp-*" + ] + effect = "Allow" + } + + statement { + actions = [ + "ecr:GetAuthorizationToken", + ] + resources = [ + "*" + ] + effect = "Allow" + } +} + +data "aws_iam_policy_document" "ssm_update_policy" { + statement { + actions = [ + "ssm:PutParameter", + "ssm:GetParameter", + "ssm:DeleteParameter" + ] + resources = ["*"] # @TODO: (ABN) Limit me + effect = "Allow" + } +} + + diff --git a/terragrunt/modules/orchestrator/iam/github.tf b/terragrunt/modules/orchestrator/iam/github.tf new file mode 100644 index 000000000..7eb8684c6 --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/github.tf @@ -0,0 +1,20 @@ +resource "aws_iam_user" "github_user" { + name = "github-user" + tags = var.tags +} + +resource "aws_iam_user_policy" "ecr_push_policy" { + name = "ECRPushPolicy" + user = aws_iam_user.github_user.name + policy = data.aws_iam_policy_document.ecr_push_policy.json +} + +resource "aws_iam_user_policy" "ssm_update_policy" { + name = "SSMUpdatePolicy" + user = aws_iam_user.github_user.name + policy = data.aws_iam_policy_document.ssm_update_policy.json +} + +resource "aws_iam_access_key" "github_user_access_key" { + user = aws_iam_user.github_user.name +} \ No newline at end of file diff --git a/terragrunt/modules/orchestrator/iam/locals.tf b/terragrunt/modules/orchestrator/iam/locals.tf new file mode 100644 index 000000000..879480b91 --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/locals.tf @@ -0,0 +1,3 @@ +locals { + name_prefix = var.product.resource_name +} diff --git a/terragrunt/modules/orchestrator/iam/outputs.tf b/terragrunt/modules/orchestrator/iam/outputs.tf new file mode 100644 index 000000000..aca1cc88f --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/outputs.tf @@ -0,0 +1,12 @@ +output "github_user_access_key_id" { + value = aws_iam_access_key.github_user_access_key.id +} + +output "github_user_secret_access_key" { + value = aws_iam_access_key.github_user_access_key.secret + sensitive = true +} + +output "terraform_role_arn" { + value = aws_iam_role.terraform.arn +} diff --git a/terragrunt/modules/orchestrator/iam/variables.tf b/terragrunt/modules/orchestrator/iam/variables.tf new file mode 100644 index 000000000..d06372afe --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/variables.tf @@ -0,0 +1,23 @@ +variable "environment" { + description = "The environment we are provisioning" + type = string +} + +variable "product" { + description = "product's common attributes" + type = object({ + name = string + resource_name = string + public_hosted_zone = string + }) +} + +variable "terraform_operators" { + description = "List of IAM user ARNs allowed to assume terraform roles" + type = list(string) +} + +variable "tags" { + description = "Tags to apply to all resources in this module" + type = map(string) +} From 2dc38082dd5179ec5d0fbd91fc8761f7e005a5b7 Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Sun, 14 Jul 2024 12:27:27 +0100 Subject: [PATCH 02/18] DP-187 Move ECR to the Orchestrator account - Reconfigure ECS services to pull images and the latest published version from Orchestrator --- ...ploy.yaml => main-build-test-publish.yaml} | 2 +- terragrunt/components/core/iam/terragrunt.hcl | 1 + .../orchestrator/ecr/terragrunt.hcl | 9 ++-- .../orchestrator/iam/terragrunt.hcl | 5 +- .../components/service/ecs/terragrunt.hcl | 2 + terragrunt/components/terragrunt.hcl | 4 ++ terragrunt/modules/core-iam/ci-datasource.tf | 18 ++++++-- terragrunt/modules/core-iam/ci.tf | 11 +++++ terragrunt/modules/core-iam/locals.tf | 6 ++- terragrunt/modules/core-iam/variables.tf | 5 ++ terragrunt/modules/ecs/cloudwatch.tf | 29 ------------ terragrunt/modules/ecs/datasource.tf | 30 ++++++++++++ terragrunt/modules/ecs/ecr.tf | 12 ----- terragrunt/modules/ecs/iam.tf | 11 +++++ terragrunt/modules/ecs/locals.tf | 16 ++++--- terragrunt/modules/ecs/service-authority.tf | 2 +- .../modules/ecs/service-data-sharing.tf | 2 +- .../ecs/service-entity-verification.tf | 2 +- terragrunt/modules/ecs/service-forms.tf | 2 +- .../modules/ecs/service-organisation-app.tf | 2 +- .../modules/ecs/service-organisation.tf | 2 +- terragrunt/modules/ecs/service-person.tf | 2 +- terragrunt/modules/ecs/service-tenant.tf | 2 +- ...ask-organisation-information-migrations.tf | 2 +- terragrunt/modules/ecs/variables.tf | 5 ++ .../modules/orchestrator/ecr/cloudwatch.tf | 28 +++++++++++ .../modules/orchestrator/ecr/datasource.tf | 46 ++++++++++++------- terragrunt/modules/orchestrator/ecr/iam.tf | 18 +++++++- terragrunt/modules/orchestrator/ecr/locals.tf | 2 +- terragrunt/modules/orchestrator/ecr/main.tf | 2 +- terragrunt/modules/orchestrator/iam/github.tf | 2 +- terragrunt/modules/orchestrator/iam/locals.tf | 4 +- .../modules/orchestrator/iam/variables.tf | 5 ++ 33 files changed, 195 insertions(+), 96 deletions(-) rename .github/workflows/{main-build-test-deploy.yaml => main-build-test-publish.yaml} (99%) delete mode 100644 terragrunt/modules/ecs/ecr.tf create mode 100644 terragrunt/modules/orchestrator/ecr/cloudwatch.tf mode change 100644 => 120000 terragrunt/modules/orchestrator/iam/locals.tf diff --git a/.github/workflows/main-build-test-deploy.yaml b/.github/workflows/main-build-test-publish.yaml similarity index 99% rename from .github/workflows/main-build-test-deploy.yaml rename to .github/workflows/main-build-test-publish.yaml index 641beee44..6e752f64f 100644 --- a/.github/workflows/main-build-test-deploy.yaml +++ b/.github/workflows/main-build-test-publish.yaml @@ -72,7 +72,7 @@ jobs: - name: Stop services run: make down - deploy: + publish: runs-on: ubuntu-latest needs: test if: github.ref == 'refs/heads/DP-187' && github.repository_owner == 'cabinetoffice' diff --git a/terragrunt/components/core/iam/terragrunt.hcl b/terragrunt/components/core/iam/terragrunt.hcl index d557a697e..f6711f95e 100644 --- a/terragrunt/components/core/iam/terragrunt.hcl +++ b/terragrunt/components/core/iam/terragrunt.hcl @@ -20,6 +20,7 @@ locals { } inputs = { + account_ids = local.global_vars.locals.account_ids tags = local.tags terraform_operators = local.global_vars.locals.terraform_operators tfstate_bucket_name = local.global_vars.locals.tg.state_bucket diff --git a/terragrunt/components/orchestrator/ecr/terragrunt.hcl b/terragrunt/components/orchestrator/ecr/terragrunt.hcl index 7de2c9588..c41e9023c 100644 --- a/terragrunt/components/orchestrator/ecr/terragrunt.hcl +++ b/terragrunt/components/orchestrator/ecr/terragrunt.hcl @@ -9,23 +9,20 @@ include { locals { global_vars = read_terragrunt_config(find_in_parent_folders("terragrunt.hcl")) - core_vars = read_terragrunt_config(find_in_parent_folders("orchestrator.hcl")) + orchestrator_vars = read_terragrunt_config(find_in_parent_folders("orchestrator.hcl")) tags = merge( local.global_vars.inputs.tags, - local.core_vars.inputs.tags, + local.orchestrator_vars.inputs.tags, { component = "orchestrator-ecr" } ) - account_ids = { - for name, env in local.global_vars.locals.environments : name => env.account_id - } } inputs = { - account_ids = local.account_ids + account_ids = local.global_vars.locals.account_ids service_configs = local.global_vars.locals.service_configs tags = local.tags } diff --git a/terragrunt/components/orchestrator/iam/terragrunt.hcl b/terragrunt/components/orchestrator/iam/terragrunt.hcl index 38e3a2569..51bede0f4 100644 --- a/terragrunt/components/orchestrator/iam/terragrunt.hcl +++ b/terragrunt/components/orchestrator/iam/terragrunt.hcl @@ -9,11 +9,11 @@ include { locals { global_vars = read_terragrunt_config(find_in_parent_folders("terragrunt.hcl")) - core_vars = read_terragrunt_config(find_in_parent_folders("orchestrator.hcl")) + orchestrator_vars = read_terragrunt_config(find_in_parent_folders("orchestrator.hcl")) tags = merge( local.global_vars.inputs.tags, - local.core_vars.inputs.tags, + local.orchestrator_vars.inputs.tags, { component = "orchestrator-iam" } @@ -21,6 +21,7 @@ locals { } inputs = { + account_ids = local.global_vars.locals.account_ids tags = local.tags terraform_operators = local.global_vars.locals.terraform_operators } diff --git a/terragrunt/components/service/ecs/terragrunt.hcl b/terragrunt/components/service/ecs/terragrunt.hcl index 969ad6792..a759bb977 100644 --- a/terragrunt/components/service/ecs/terragrunt.hcl +++ b/terragrunt/components/service/ecs/terragrunt.hcl @@ -76,6 +76,8 @@ dependency service_database { } inputs = { + + account_ids = local.global_vars.locals.account_ids service_configs = local.global_vars.locals.service_configs tags = local.tags diff --git a/terragrunt/components/terragrunt.hcl b/terragrunt/components/terragrunt.hcl index 22f95938e..db77a1fc7 100644 --- a/terragrunt/components/terragrunt.hcl +++ b/terragrunt/components/terragrunt.hcl @@ -1,5 +1,9 @@ locals { + account_ids = { + for name, env in local.environments : name => env.account_id + } + cidr_b_development = 3 cidr_b_integration = 4 cidr_b_orchestrator = 5 diff --git a/terragrunt/modules/core-iam/ci-datasource.tf b/terragrunt/modules/core-iam/ci-datasource.tf index 876389d09..d7fed6129 100644 --- a/terragrunt/modules/core-iam/ci-datasource.tf +++ b/terragrunt/modules/core-iam/ci-datasource.tf @@ -16,6 +16,14 @@ data "aws_iam_policy_document" "terraform_assume" { } } +data "aws_iam_policy_document" "terraform_assume_orchestrator_role" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + resources = ["arn:aws:iam::${local.orchestrator_account_id}:role/cdp-sirsi-orchestrator-read-service-version"] + } +} + data "aws_iam_policy_document" "terraform" { statement { @@ -205,8 +213,9 @@ data "aws_iam_policy_document" "terraform_global" { statement { actions = [ - "ecr:CreateRepository", + "ecr:BatchGetImage", "ecr:GetAuthorizationToken", + "ecr:GetDownloadUrlForLayer", "ecs:Create*", "ecs:DeregisterTaskDefinition", "ecs:DescribeTaskDefinition", @@ -271,7 +280,8 @@ data "aws_iam_policy_document" "terraform_product" { resources = [ "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/cdp-sirsi-*", "arn:aws:iam::${data.aws_caller_identity.current.account_id}:policy/cdp-sirsi-*", - "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/*" + "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/*", + "arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/cdp-sirsi-*" ] sid = "ManageProductIAMs" } @@ -293,9 +303,7 @@ data "aws_iam_policy_document" "terraform_product" { actions = ["ec2:*"] effect = "Allow" resources = [ - "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*/cdp-sirsi-*", - "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:vpc/cdp-sirsi-*", - "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:elastic-ip/cdp-sirsi-*" + "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*/cdp-sirsi-*" ] sid = "ManageProductEC2" } diff --git a/terragrunt/modules/core-iam/ci.tf b/terragrunt/modules/core-iam/ci.tf index d2ffdc497..8d6ddc38f 100644 --- a/terragrunt/modules/core-iam/ci.tf +++ b/terragrunt/modules/core-iam/ci.tf @@ -28,6 +28,12 @@ resource "aws_iam_policy" "terraform_product" { tags = var.tags } +resource "aws_iam_policy" "terraform_assume_orchestrator_role" { + name = "${local.name_prefix}-terraform-assume-orchestrator-role" + description = "Policy to allow assuming the orchestrator role" + policy = data.aws_iam_policy_document.terraform_assume_orchestrator_role.json +} + resource "aws_iam_role_policy_attachment" "terraform" { policy_arn = aws_iam_policy.terraform.arn role = aws_iam_role.terraform.name @@ -42,3 +48,8 @@ resource "aws_iam_role_policy_attachment" "terraform_production" { policy_arn = aws_iam_policy.terraform_product.arn role = aws_iam_role.terraform.name } + +resource "aws_iam_role_policy_attachment" "terraform_assume_orchestrator_role" { + role = aws_iam_role.terraform.name + policy_arn = aws_iam_policy.terraform_assume_orchestrator_role.arn +} diff --git a/terragrunt/modules/core-iam/locals.tf b/terragrunt/modules/core-iam/locals.tf index 879480b91..374804d49 100644 --- a/terragrunt/modules/core-iam/locals.tf +++ b/terragrunt/modules/core-iam/locals.tf @@ -1,3 +1,7 @@ +# Note! +# Resources in this file are shared with orchestrator/iam module + locals { - name_prefix = var.product.resource_name + name_prefix = var.product.resource_name + orchestrator_account_id = var.account_ids["orchestrator"] } diff --git a/terragrunt/modules/core-iam/variables.tf b/terragrunt/modules/core-iam/variables.tf index fb28182c2..7b4f57047 100644 --- a/terragrunt/modules/core-iam/variables.tf +++ b/terragrunt/modules/core-iam/variables.tf @@ -1,3 +1,8 @@ +variable "account_ids" { + description = "Map of all accounts and their IDs" + type = map(string) +} + variable "environment" { description = "The environment we are provisioning" type = string diff --git a/terragrunt/modules/ecs/cloudwatch.tf b/terragrunt/modules/ecs/cloudwatch.tf index 5ebdc4e21..a51e33267 100644 --- a/terragrunt/modules/ecs/cloudwatch.tf +++ b/terragrunt/modules/ecs/cloudwatch.tf @@ -35,32 +35,3 @@ resource "aws_cloudwatch_log_group" "tasks" { tags = var.tags } - -resource "aws_cloudwatch_event_rule" "ecr_push" { - for_each = aws_ecr_repository.this - - name = "${local.name_prefix}-ecr-push-to-${each.value.name}" - description = "CloudWatch Event rule to detect ECR push events to ${each.value.name}" - - event_pattern = jsonencode( - { - "source" : ["aws.ecr"], - "detail-type" : ["ECR Image Action"], - "detail" : { - "action-type" : ["PUSH"], - "image-tag" : ["latest"], - "repository-name" : [each.value.name] - "result" : ["SUCCESS"], - } - } - ) - - tags = var.tags -} - -resource "aws_cloudwatch_event_target" "trigger_service_deployment" { - for_each = aws_cloudwatch_event_rule.ecr_push - rule = each.value.name - arn = each.key == "organisation-information-migrations" ? aws_sfn_state_machine.ecs_run_migration.arn : aws_sfn_state_machine.ecs_force_deploy[each.key].arn - role_arn = var.role_cloudwatch_events_arn -} diff --git a/terragrunt/modules/ecs/datasource.tf b/terragrunt/modules/ecs/datasource.tf index 42cf70abd..96ec796ad 100644 --- a/terragrunt/modules/ecs/datasource.tf +++ b/terragrunt/modules/ecs/datasource.tf @@ -83,3 +83,33 @@ data "aws_iam_policy_document" "step_function_manage_services" { sid = "MangeIAM" } } + +data "aws_iam_policy_document" "ecr_pull_from_orchestrator" { + statement { + actions = [ + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:GetAuthorizationToken" + ] + resources = ["*"] + } +} + +# Configure the provider to assume the role in the orchestrator account and fetch the latest service version +provider "aws" { + alias = "orchestrator" + region = "eu-west-2" +} + +provider "aws" { + alias = "orchestrator_assume_role" + region = "eu-west-2" + assume_role { + role_arn = "arn:aws:iam::${local.orchestrator_account_id}:role/cdp-sirsi-orchestrator-read-service-version" + } +} + +data "aws_ssm_parameter" "orchestrator_service_version" { + provider = aws.orchestrator_assume_role + name = "/cdp-sirsi-service-version" +} diff --git a/terragrunt/modules/ecs/ecr.tf b/terragrunt/modules/ecs/ecr.tf deleted file mode 100644 index 0080b476d..000000000 --- a/terragrunt/modules/ecs/ecr.tf +++ /dev/null @@ -1,12 +0,0 @@ -resource "aws_ecr_repository" "this" { - for_each = toset(local.tasks) - - name = "cdp-${each.value}" - image_tag_mutability = "MUTABLE" - - image_scanning_configuration { - scan_on_push = true - } - - tags = var.tags -} diff --git a/terragrunt/modules/ecs/iam.tf b/terragrunt/modules/ecs/iam.tf index d84f27cb8..762aaa604 100644 --- a/terragrunt/modules/ecs/iam.tf +++ b/terragrunt/modules/ecs/iam.tf @@ -9,6 +9,17 @@ resource "aws_iam_role_policy_attachment" "ecs_task_access_secrets" { role = var.role_ecs_task_exec_name } +resource "aws_iam_policy" "ecr_pull_from_orchestrator" { + name = "${local.name_prefix}-ecr-pull-from-orchestrator" + policy = data.aws_iam_policy_document.ecr_pull_from_orchestrator.json + tags = var.tags +} + +resource "aws_iam_role_policy_attachment" "ecr_pull_from_orchestrator" { + policy_arn = aws_iam_policy.ecr_pull_from_orchestrator.arn + role = var.role_ecs_task_exec_name +} + resource "aws_iam_policy" "cloudwatch_event_invoke_deployer_step_function" { name = "${local.name_prefix}-invoke-deployer-step-function" description = "Policy for CloudWatch Events to invoke Step Functions" diff --git a/terragrunt/modules/ecs/locals.tf b/terragrunt/modules/ecs/locals.tf index f79fde192..f5a277421 100644 --- a/terragrunt/modules/ecs/locals.tf +++ b/terragrunt/modules/ecs/locals.tf @@ -1,12 +1,8 @@ locals { - service_environment = var.environment == "production" ? "Production" : "Development" - - ecr_urls = [ - for repos in aws_ecr_repository.this.* : { for repo, attr in repos : repo => attr.repository_url } - ][ - 0 - ] + ecr_urls = { + for task in local.tasks : task => "${local.orchestrator_account_id}.dkr.ecr.eu-west-2.amazonaws.com/cdp-${task}" + } name_prefix = var.product.resource_name @@ -18,11 +14,17 @@ locals { } } + orchestrator_account_id = var.account_ids["orchestrator"] + + orchestrator_service_version = data.aws_ssm_parameter.orchestrator_service_version.value + services = [ for name, config in var.service_configs : config.name if config.name != "organisation-information-migrations" ] + service_environment = var.environment == "production" ? "Production" : "Development" + tasks = [ for name, config in var.service_configs : config.name diff --git a/terragrunt/modules/ecs/service-authority.tf b/terragrunt/modules/ecs/service-authority.tf index 3cc2724b8..692a11af4 100644 --- a/terragrunt/modules/ecs/service-authority.tf +++ b/terragrunt/modules/ecs/service-authority.tf @@ -10,7 +10,7 @@ module "ecs_service_authority" { conn_string_location = var.db_connection_secret_arn environment = local.service_environment host_port = var.service_configs.authority.port - image = "${local.ecr_urls[var.service_configs.authority.name]}:latest" + image = "${local.ecr_urls[var.service_configs.authority.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.authority.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/service-data-sharing.tf b/terragrunt/modules/ecs/service-data-sharing.tf index 96f9f9895..9a3398155 100644 --- a/terragrunt/modules/ecs/service-data-sharing.tf +++ b/terragrunt/modules/ecs/service-data-sharing.tf @@ -8,7 +8,7 @@ module "ecs_service_data_sharing" { cpu = var.service_configs.data_sharing.cpu environment = local.service_environment host_port = var.service_configs.data_sharing.port - image = "${local.ecr_urls[var.service_configs.data_sharing.name]}:latest" + image = "${local.ecr_urls[var.service_configs.data_sharing.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.data_sharing.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/service-entity-verification.tf b/terragrunt/modules/ecs/service-entity-verification.tf index ee72aabb1..66c2ea682 100644 --- a/terragrunt/modules/ecs/service-entity-verification.tf +++ b/terragrunt/modules/ecs/service-entity-verification.tf @@ -8,7 +8,7 @@ module "ecs_service_entity_verification" { cpu = var.service_configs.entity_verification.cpu environment = local.service_environment host_port = var.service_configs.entity_verification.port - image = "${local.ecr_urls[var.service_configs.entity_verification.name]}:latest" + image = "${local.ecr_urls[var.service_configs.entity_verification.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.entity_verification.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/service-forms.tf b/terragrunt/modules/ecs/service-forms.tf index 1a6dcdad1..3ca19c714 100644 --- a/terragrunt/modules/ecs/service-forms.tf +++ b/terragrunt/modules/ecs/service-forms.tf @@ -8,7 +8,7 @@ module "ecs_service_forms" { cpu = var.service_configs.forms.cpu environment = local.service_environment host_port = var.service_configs.forms.port - image = "${local.ecr_urls[var.service_configs.forms.name]}:latest" + image = "${local.ecr_urls[var.service_configs.forms.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.forms.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/service-organisation-app.tf b/terragrunt/modules/ecs/service-organisation-app.tf index 33fef699f..285ab8d48 100644 --- a/terragrunt/modules/ecs/service-organisation-app.tf +++ b/terragrunt/modules/ecs/service-organisation-app.tf @@ -8,7 +8,7 @@ module "ecs_service_organisation_app" { cpu = var.service_configs.organisation_app.cpu environment = local.service_environment host_port = var.service_configs.organisation_app.port - image = "${local.ecr_urls[var.service_configs.organisation_app.name]}:latest" + image = "${local.ecr_urls[var.service_configs.organisation_app.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.organisation_app.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/service-organisation.tf b/terragrunt/modules/ecs/service-organisation.tf index 0bc5eb6dd..f93a7faf2 100644 --- a/terragrunt/modules/ecs/service-organisation.tf +++ b/terragrunt/modules/ecs/service-organisation.tf @@ -9,7 +9,7 @@ module "ecs_service_organisation" { conn_string_location = var.db_connection_secret_arn environment = local.service_environment host_port = var.service_configs.organisation.port - image = "${local.ecr_urls[var.service_configs.organisation.name]}:latest" + image = "${local.ecr_urls[var.service_configs.organisation.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.organisation.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/service-person.tf b/terragrunt/modules/ecs/service-person.tf index 6ce33ac8a..9112f4a76 100644 --- a/terragrunt/modules/ecs/service-person.tf +++ b/terragrunt/modules/ecs/service-person.tf @@ -9,7 +9,7 @@ module "ecs_service_person" { conn_string_location = var.db_connection_secret_arn environment = local.service_environment host_port = var.service_configs.person.port - image = "${local.ecr_urls[var.service_configs.person.name]}:latest" + image = "${local.ecr_urls[var.service_configs.person.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.person.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/service-tenant.tf b/terragrunt/modules/ecs/service-tenant.tf index 40b480756..8ad85e1e8 100644 --- a/terragrunt/modules/ecs/service-tenant.tf +++ b/terragrunt/modules/ecs/service-tenant.tf @@ -9,7 +9,7 @@ module "ecs_service_tenant" { conn_string_location = var.db_connection_secret_arn environment = local.service_environment host_port = var.service_configs.tenant.port - image = "${local.ecr_urls[var.service_configs.tenant.name]}:latest" + image = "${local.ecr_urls[var.service_configs.tenant.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.tenant.name].name lg_prefix = "app" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/task-organisation-information-migrations.tf b/terragrunt/modules/ecs/task-organisation-information-migrations.tf index b87719041..65b29c1cd 100644 --- a/terragrunt/modules/ecs/task-organisation-information-migrations.tf +++ b/terragrunt/modules/ecs/task-organisation-information-migrations.tf @@ -7,7 +7,7 @@ module "ecs_service_organisation_information_migrations" { cpu = var.service_configs.organisation_information_migrations.cpu conn_string_location = var.db_connection_secret_arn environment = local.service_environment - image = "${local.ecr_urls[var.service_configs.organisation_information_migrations.name]}:latest" + image = "${local.ecr_urls[var.service_configs.organisation_information_migrations.name]}:${local.orchestrator_service_version}" lg_name = aws_cloudwatch_log_group.tasks[var.service_configs.organisation_information_migrations.name].name lg_prefix = "db" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/ecs/variables.tf b/terragrunt/modules/ecs/variables.tf index 2fbbcdb18..8088de13b 100644 --- a/terragrunt/modules/ecs/variables.tf +++ b/terragrunt/modules/ecs/variables.tf @@ -1,3 +1,8 @@ +variable "account_ids" { + description = "Map of all accounts and their IDs" + type = map(string) +} + variable "alb_sg_id" { description = "Application load-balancer security group ID" type = string diff --git a/terragrunt/modules/orchestrator/ecr/cloudwatch.tf b/terragrunt/modules/orchestrator/ecr/cloudwatch.tf new file mode 100644 index 000000000..2a76bcc10 --- /dev/null +++ b/terragrunt/modules/orchestrator/ecr/cloudwatch.tf @@ -0,0 +1,28 @@ +resource "aws_cloudwatch_event_rule" "ecr_push" { + for_each = aws_ecr_repository.this + + name = "${local.name_prefix}-ecr-push-to-${each.value.name}" + description = "CloudWatch Event rule to detect ECR push events to ${each.value.name}" + + event_pattern = jsonencode( + { + "source" : ["aws.ecr"], + "detail-type" : ["ECR Image Action"], + "detail" : { + "action-type" : ["PUSH"], + "image-tag" : ["latest"], + "repository-name" : [each.value.name] + "result" : ["SUCCESS"], + } + } + ) + + tags = var.tags +} + +# resource "aws_cloudwatch_event_target" "trigger_service_deployment" { +# for_each = aws_cloudwatch_event_rule.ecr_push +# rule = each.value.name +# arn = each.key == "organisation-information-migrations" ? aws_sfn_state_machine.ecs_run_migration.arn : aws_sfn_state_machine.ecs_force_deploy[each.key].arn +# role_arn = var.role_cloudwatch_events_arn +# } \ No newline at end of file diff --git a/terragrunt/modules/orchestrator/ecr/datasource.tf b/terragrunt/modules/orchestrator/ecr/datasource.tf index bba4fe0f8..253663ee4 100644 --- a/terragrunt/modules/orchestrator/ecr/datasource.tf +++ b/terragrunt/modules/orchestrator/ecr/datasource.tf @@ -1,6 +1,6 @@ data "aws_caller_identity" "current" {} -data "aws_organizations_organization" "this" {} +data "aws_region" "current" {} data "aws_iam_policy_document" "ecr_repo_policy_document" { statement { @@ -11,14 +11,14 @@ data "aws_iam_policy_document" "ecr_repo_policy_document" { identifiers = local.read_principals } actions = [ - "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:DescribeImages", + "ecr:DescribeRepositories", + "ecr:GetAuthorizationToken", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", - "ecr:DescribeRepositories", "ecr:ListImages", - "ecr:DescribeImages", - "ecr:BatchGetImage", ] } @@ -26,25 +26,19 @@ data "aws_iam_policy_document" "ecr_repo_policy_document" { sid = "ECRPull" effect = "Allow" principals { - type = "*" - identifiers = ["*"] - } - - condition { - test = "StringLike" - variable = "aws:PrincipalOrgID" - values = [data.aws_organizations_organization.this.id] + type = "AWS" + identifiers = local.read_principals } actions = [ - "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:DescribeImages", + "ecr:DescribeRepositories", + "ecr:GetAuthorizationToken", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", - "ecr:DescribeRepositories", "ecr:ListImages", - "ecr:DescribeImages", - "ecr:BatchGetImage", ] } @@ -73,3 +67,21 @@ data "aws_iam_policy_document" "ecr_repo_policy_document" { } } } + +data "aws_iam_policy_document" "orchestrator_read_service_version_assume_role" { + statement { + actions = ["sts:AssumeRole"] + principals { + type = "AWS" + identifiers = [for name, id in var.account_ids : "arn:aws:iam::${id}:role/cdp-sirsi-${name}-terraform"] + } + } +} + + +data "aws_iam_policy_document" "orchestrator_read_service_version" { + statement { + actions = ["ssm:GetParameter"] + resources = ["arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter/cdp-sirsi-service-version"] + } +} \ No newline at end of file diff --git a/terragrunt/modules/orchestrator/ecr/iam.tf b/terragrunt/modules/orchestrator/ecr/iam.tf index 52f184aaa..24ef6d27e 100644 --- a/terragrunt/modules/orchestrator/ecr/iam.tf +++ b/terragrunt/modules/orchestrator/ecr/iam.tf @@ -1,7 +1,23 @@ resource "aws_ecr_repository_policy" "policy" { for_each = toset(local.repositories) + policy = data.aws_iam_policy_document.ecr_repo_policy_document.json repository = aws_ecr_repository.this[each.key].name +} + +resource "aws_iam_role" "orchestrator_read_service_version" { + assume_role_policy = data.aws_iam_policy_document.orchestrator_read_service_version_assume_role.json + name = "${local.name_prefix}-orchestrator-read-service-version" + tags = var.tags +} + +resource "aws_iam_policy" "orchestrator_read_service_version" { + description = "Policy to allow reading SSM parameters in the orchestrator account" + name = "${local.name_prefix}-orchestrator-read-service-version" + policy = data.aws_iam_policy_document.orchestrator_read_service_version.json +} - policy = data.aws_iam_policy_document.ecr_repo_policy_document.json +resource "aws_iam_role_policy_attachment" "orchestrator_read_service_version" { + policy_arn = aws_iam_policy.orchestrator_read_service_version.arn + role = aws_iam_role.orchestrator_read_service_version.name } diff --git a/terragrunt/modules/orchestrator/ecr/locals.tf b/terragrunt/modules/orchestrator/ecr/locals.tf index f7cf49712..e75bfbcb1 100644 --- a/terragrunt/modules/orchestrator/ecr/locals.tf +++ b/terragrunt/modules/orchestrator/ecr/locals.tf @@ -9,6 +9,6 @@ locals { for name, config in var.service_configs : config.name ], - ["cdp-grafana"]) + ["grafana"]) } diff --git a/terragrunt/modules/orchestrator/ecr/main.tf b/terragrunt/modules/orchestrator/ecr/main.tf index ede436c27..ea95c7ce2 100644 --- a/terragrunt/modules/orchestrator/ecr/main.tf +++ b/terragrunt/modules/orchestrator/ecr/main.tf @@ -2,7 +2,7 @@ resource "aws_ecr_repository" "this" { for_each = toset(local.repositories) name = "cdp-${each.value}" - image_tag_mutability = "IMMUTABLE" + image_tag_mutability = each.value != "grafana" ? "IMMUTABLE" : "MUTABLE" image_scanning_configuration { scan_on_push = true diff --git a/terragrunt/modules/orchestrator/iam/github.tf b/terragrunt/modules/orchestrator/iam/github.tf index 7eb8684c6..82e11943f 100644 --- a/terragrunt/modules/orchestrator/iam/github.tf +++ b/terragrunt/modules/orchestrator/iam/github.tf @@ -1,5 +1,5 @@ resource "aws_iam_user" "github_user" { - name = "github-user" + name = "${local.name_prefix}-github-user" tags = var.tags } diff --git a/terragrunt/modules/orchestrator/iam/locals.tf b/terragrunt/modules/orchestrator/iam/locals.tf deleted file mode 100644 index 879480b91..000000000 --- a/terragrunt/modules/orchestrator/iam/locals.tf +++ /dev/null @@ -1,3 +0,0 @@ -locals { - name_prefix = var.product.resource_name -} diff --git a/terragrunt/modules/orchestrator/iam/locals.tf b/terragrunt/modules/orchestrator/iam/locals.tf new file mode 120000 index 000000000..fcbbbebd4 --- /dev/null +++ b/terragrunt/modules/orchestrator/iam/locals.tf @@ -0,0 +1 @@ +../../core-iam/locals.tf \ No newline at end of file diff --git a/terragrunt/modules/orchestrator/iam/variables.tf b/terragrunt/modules/orchestrator/iam/variables.tf index d06372afe..9418f8366 100644 --- a/terragrunt/modules/orchestrator/iam/variables.tf +++ b/terragrunt/modules/orchestrator/iam/variables.tf @@ -1,3 +1,8 @@ +variable "account_ids" { + description = "Map of all accounts and their IDs" + type = map(string) +} + variable "environment" { description = "The environment we are provisioning" type = string From c36aea6277f4b856869bf0586d642b291e803668 Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Sun, 14 Jul 2024 12:49:14 +0100 Subject: [PATCH 03/18] DP-187 Point the workflow's logic to main branch --- .github/workflows/main-build-test-publish.yaml | 6 +++--- .github/workflows/main-pr-check.yml | 2 +- terragrunt/modules/orchestrator/ecr/cloudwatch.tf | 2 +- terragrunt/modules/orchestrator/iam/github.tf | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main-build-test-publish.yaml b/.github/workflows/main-build-test-publish.yaml index 6e752f64f..e290caba1 100644 --- a/.github/workflows/main-build-test-publish.yaml +++ b/.github/workflows/main-build-test-publish.yaml @@ -2,7 +2,7 @@ name: CI/CD Pipeline on: push: - branches: [DP-187] + branches: [main] jobs: build: @@ -75,7 +75,7 @@ jobs: publish: runs-on: ubuntu-latest needs: test - if: github.ref == 'refs/heads/DP-187' && github.repository_owner == 'cabinetoffice' + if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' steps: - uses: actions/checkout@v4 @@ -134,7 +134,7 @@ jobs: - name: Build run: cd docs && make build - name: Publish - if: github.ref == 'refs/heads/DP-187' && github.repository_owner == 'cabinetoffice' + if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' run: cd docs && make publish-docs-during-cd - name: Upload Documentation uses: actions/upload-artifact@v4 diff --git a/.github/workflows/main-pr-check.yml b/.github/workflows/main-pr-check.yml index a3d072438..6fd6786a6 100644 --- a/.github/workflows/main-pr-check.yml +++ b/.github/workflows/main-pr-check.yml @@ -2,7 +2,7 @@ name: Build on: pull_request: - branches: [DP-187] + branches: [main] jobs: test: diff --git a/terragrunt/modules/orchestrator/ecr/cloudwatch.tf b/terragrunt/modules/orchestrator/ecr/cloudwatch.tf index 2a76bcc10..2fd161b21 100644 --- a/terragrunt/modules/orchestrator/ecr/cloudwatch.tf +++ b/terragrunt/modules/orchestrator/ecr/cloudwatch.tf @@ -25,4 +25,4 @@ resource "aws_cloudwatch_event_rule" "ecr_push" { # rule = each.value.name # arn = each.key == "organisation-information-migrations" ? aws_sfn_state_machine.ecs_run_migration.arn : aws_sfn_state_machine.ecs_force_deploy[each.key].arn # role_arn = var.role_cloudwatch_events_arn -# } \ No newline at end of file +# } diff --git a/terragrunt/modules/orchestrator/iam/github.tf b/terragrunt/modules/orchestrator/iam/github.tf index 82e11943f..e153db123 100644 --- a/terragrunt/modules/orchestrator/iam/github.tf +++ b/terragrunt/modules/orchestrator/iam/github.tf @@ -17,4 +17,4 @@ resource "aws_iam_user_policy" "ssm_update_policy" { resource "aws_iam_access_key" "github_user_access_key" { user = aws_iam_user.github_user.name -} \ No newline at end of file +} From 83a87468c3f565c8f85740cffc43fc1e8a068181 Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Sun, 14 Jul 2024 13:25:38 +0100 Subject: [PATCH 04/18] DP-187 Move scripts, order variable and outputs --- terragrunt/modules/core-iam/outputs.tf | 16 ++++++++-------- terragrunt/modules/core-networking/outputs.tf | 10 +++++----- terragrunt/modules/database/variables.tf | 8 ++++---- terragrunt/modules/ecs/variables.tf | 8 ++++---- terragrunt/modules/orchestrator/iam/variables.tf | 10 +++++----- terragrunt/tools/scripts/delete_tf_cache.sh | 11 +++++++++++ terragrunt/tools/{ => scripts}/order.py | 0 7 files changed, 37 insertions(+), 26 deletions(-) create mode 100755 terragrunt/tools/scripts/delete_tf_cache.sh rename terragrunt/tools/{ => scripts}/order.py (100%) diff --git a/terragrunt/modules/core-iam/outputs.tf b/terragrunt/modules/core-iam/outputs.tf index d4a00087c..00d414e62 100644 --- a/terragrunt/modules/core-iam/outputs.tf +++ b/terragrunt/modules/core-iam/outputs.tf @@ -14,6 +14,14 @@ output "cloudwatch_events_name" { value = aws_iam_role.cloudwatch_events.name } +output "db_connection_step_function_arn" { + value = aws_iam_role.db_connection_step_function.arn +} + +output "db_connection_step_function_name" { + value = aws_iam_role.db_connection_step_function.name +} + output "ecs_task_arn" { value = aws_iam_role.ecs_task.arn } @@ -30,14 +38,6 @@ output "ecs_task_name" { value = aws_iam_role.ecs_task.name } -output "db_connection_step_function_arn" { - value = aws_iam_role.db_connection_step_function.arn -} - -output "db_connection_step_function_name" { - value = aws_iam_role.db_connection_step_function.name -} - output "service_deployer_step_function_arn" { value = aws_iam_role.service_deployer_step_function.arn } diff --git a/terragrunt/modules/core-networking/outputs.tf b/terragrunt/modules/core-networking/outputs.tf index ef090d72a..3b9fc1205 100644 --- a/terragrunt/modules/core-networking/outputs.tf +++ b/terragrunt/modules/core-networking/outputs.tf @@ -43,6 +43,11 @@ output "public_subnets_cidr_blocks" { value = aws_subnet.public.*.cidr_block } +output "vpc_cider" { + description = "ID of the VPC" + value = aws_vpc.this.cidr_block +} + output "vpc_cidr_block" { description = "VPC CIDR block" value = aws_vpc.this.cidr_block @@ -52,8 +57,3 @@ output "vpc_id" { description = "ID of the VPC" value = aws_vpc.this.id } - -output "vpc_cider" { - description = "ID of the VPC" - value = aws_vpc.this.cidr_block -} diff --git a/terragrunt/modules/database/variables.tf b/terragrunt/modules/database/variables.tf index a1d0a0a9a..a0f507cf6 100644 --- a/terragrunt/modules/database/variables.tf +++ b/terragrunt/modules/database/variables.tf @@ -42,13 +42,13 @@ variable "role_cloudwatch_events_name" { type = string } -variable "role_db_connection_step_function_name" { - description = "Name of the IAM role used by the Step Function in charge of updating DB connection secret" +variable "role_db_connection_step_function_arn" { + description = "ARN of the IAM role used by the Step Function in charge of updating DB connection secret" type = string } -variable "role_db_connection_step_function_arn" { - description = "ARN of the IAM role used by the Step Function in charge of updating DB connection secret" +variable "role_db_connection_step_function_name" { + description = "Name of the IAM role used by the Step Function in charge of updating DB connection secret" type = string } diff --git a/terragrunt/modules/ecs/variables.tf b/terragrunt/modules/ecs/variables.tf index 8088de13b..d5457d95e 100644 --- a/terragrunt/modules/ecs/variables.tf +++ b/terragrunt/modules/ecs/variables.tf @@ -123,13 +123,13 @@ variable "tags" { type = map(string) } -variable "vpc_id" { - description = "The ID of the VPC" +variable "vpc_cider" { + description = "VPC's IPv4 CIDR" type = string } -variable "vpc_cider" { - description = "VPC's IPv4 CIDR" +variable "vpc_id" { + description = "The ID of the VPC" type = string } diff --git a/terragrunt/modules/orchestrator/iam/variables.tf b/terragrunt/modules/orchestrator/iam/variables.tf index 9418f8366..44f0a81f2 100644 --- a/terragrunt/modules/orchestrator/iam/variables.tf +++ b/terragrunt/modules/orchestrator/iam/variables.tf @@ -17,12 +17,12 @@ variable "product" { }) } -variable "terraform_operators" { - description = "List of IAM user ARNs allowed to assume terraform roles" - type = list(string) -} - variable "tags" { description = "Tags to apply to all resources in this module" type = map(string) } + +variable "terraform_operators" { + description = "List of IAM user ARNs allowed to assume terraform roles" + type = list(string) +} diff --git a/terragrunt/tools/scripts/delete_tf_cache.sh b/terragrunt/tools/scripts/delete_tf_cache.sh new file mode 100755 index 000000000..b3c71d845 --- /dev/null +++ b/terragrunt/tools/scripts/delete_tf_cache.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +root_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" + +echo "🔎 Clearing Terraform and Terragrunt cache files..." +find "${root_dir}" -type d -name '.terragrunt-cache' -prune -exec echo "␡ Removing {}" \; -exec rm -rf '{}' + +find "${root_dir}" -type d -name '.terraform' -prune -exec echo "␡ Removing {}" \; -exec rm -rf '{}' + +find "${root_dir}" -type d -name '.terraform.d' -prune -exec echo "␡ Removing {}" \; -exec rm -rf '{}' + +find "${root_dir}" -type f -name '.terraform.lock.hcl' -delete +find "${root_dir}" -type f -name 'temp_providers.tf' -delete +echo "😎 Done." diff --git a/terragrunt/tools/order.py b/terragrunt/tools/scripts/order.py similarity index 100% rename from terragrunt/tools/order.py rename to terragrunt/tools/scripts/order.py From d11917846c00dad0d2ce467aa565a0b08d726748 Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Sun, 14 Jul 2024 13:49:44 +0100 Subject: [PATCH 05/18] DP-187 Update Makefile targets to distinguish between local/debug builds and release builds --- Makefile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index c372ed577..8c42ffcc8 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,11 @@ AWS_ACCOUNT_ID=$$(aws sts get-caller-identity | jq -r '.Account') REPO_URL := $(AWS_ACCOUNT_ID).dkr.ecr.eu-west-2.amazonaws.com IMAGES := cdp-organisation-information-migrations cdp-data-sharing cdp-entity-verification cdp-forms cdp-organisation-app cdp-organisation cdp-person cdp-tenant cdp-authority -TAGGED_IMAGES := $(addprefix cabinetoffice/,$(addsuffix :latest,$(IMAGES))) -TAGGED_REPO_IMAGES := $(addprefix $(REPO_URL)/,$(TAGGED_IMAGES)) +DATE := $(shell date +%Y%m%d) +TIME := $(shell date +%H%M) +COMMIT_REVISION := $(shell git rev-parse --short HEAD) +TAG := $(DATE)-localbuild-$(TIME)-$(COMMIT_REVISION) +TAGGED_IMAGES := $(addsuffix :$(TAG),$(IMAGES)) # Extracts targets and their comments help: ## List available commands @@ -156,8 +159,11 @@ aws-push-authority-private-key: ## Push Authority's private key to the target AW aws secretsmanager create-secret --name cdp-sirsi-authority-keys --secret-string "$$(jq -n --arg priv "$$(cat ./terragrunt/secrets/authority-private-key.pem)" '{PRIVATE: $$priv}')"; \ fi -aws-push-to-ecr: build-docker ## Build, tag and push Docker images to ECR - $(foreach image,$(TAGGED_IMAGES),docker tag $(image) $(REPO_URL)/$(notdir $(basename $(image)));) +aws-push-to-ecr: ## Tag latest built Docker images and push to ECR + $(foreach image,$(IMAGES),docker tag cabinetoffice/$(image):latest $(REPO_URL)/$(image):$(TAG);) aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin $(REPO_URL) - $(foreach image,$(IMAGES),docker push $(REPO_URL)/$(image);) + $(foreach image,$(IMAGES),docker push $(REPO_URL)/$(image):$(TAG);) .PHONY: aws-push-to-ecr + +aws-build-and-push-ecr: build-docker aws-push-to-ecr ## Build, tag and push Docker images to ECR +.PHONY: aws-build-and-push-ecr From 262a87840148eecb237118931687471c8709062b Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Sun, 14 Jul 2024 15:33:07 +0100 Subject: [PATCH 06/18] DP-187 Grafana's ECR, add codebuild repo --- terragrunt/components/service/telemetry/terragrunt.hcl | 1 + terragrunt/modules/orchestrator/ecr/locals.tf | 2 +- terragrunt/modules/telemetry/ecr.tf | 10 ---------- terragrunt/modules/telemetry/locals.tf | 2 ++ terragrunt/modules/telemetry/service-grafana.tf | 2 +- terragrunt/modules/telemetry/variables.tf | 5 +++++ 6 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 terragrunt/modules/telemetry/ecr.tf diff --git a/terragrunt/components/service/telemetry/terragrunt.hcl b/terragrunt/components/service/telemetry/terragrunt.hcl index d5bf583e6..8957807aa 100644 --- a/terragrunt/components/service/telemetry/terragrunt.hcl +++ b/terragrunt/components/service/telemetry/terragrunt.hcl @@ -58,6 +58,7 @@ dependency service_ecs { } inputs = { + account_ids = local.global_vars.locals.account_ids grafana_config = local.global_vars.locals.tools_configs.grafana service_configs = local.global_vars.locals.service_configs tags = local.tags diff --git a/terragrunt/modules/orchestrator/ecr/locals.tf b/terragrunt/modules/orchestrator/ecr/locals.tf index e75bfbcb1..598841512 100644 --- a/terragrunt/modules/orchestrator/ecr/locals.tf +++ b/terragrunt/modules/orchestrator/ecr/locals.tf @@ -9,6 +9,6 @@ locals { for name, config in var.service_configs : config.name ], - ["grafana"]) + ["grafana", "codebuild"]) } diff --git a/terragrunt/modules/telemetry/ecr.tf b/terragrunt/modules/telemetry/ecr.tf deleted file mode 100644 index 6e461e842..000000000 --- a/terragrunt/modules/telemetry/ecr.tf +++ /dev/null @@ -1,10 +0,0 @@ -resource "aws_ecr_repository" "grafana" { - name = "cdp-${var.grafana_config.name}" - image_tag_mutability = "MUTABLE" - - image_scanning_configuration { - scan_on_push = true - } - - tags = var.tags -} diff --git a/terragrunt/modules/telemetry/locals.tf b/terragrunt/modules/telemetry/locals.tf index 990be0047..a51481890 100644 --- a/terragrunt/modules/telemetry/locals.tf +++ b/terragrunt/modules/telemetry/locals.tf @@ -1,6 +1,8 @@ locals { name_prefix = var.product.resource_name + orchestrator_account_id = var.account_ids["orchestrator"] + service_widgets = [ for idx, service in values(var.service_configs) : [ { diff --git a/terragrunt/modules/telemetry/service-grafana.tf b/terragrunt/modules/telemetry/service-grafana.tf index 632c5e710..a9a1dd397 100644 --- a/terragrunt/modules/telemetry/service-grafana.tf +++ b/terragrunt/modules/telemetry/service-grafana.tf @@ -10,7 +10,7 @@ module "ecs_service_grafana" { gf_admin_password = "${aws_secretsmanager_secret.grafana_credentials.arn}:ADMIN_PASSWORD::" gf_admin_user = "${aws_secretsmanager_secret.grafana_credentials.arn}:ADMIN_USERNAME::" host_port = var.grafana_config.port - image = "${aws_ecr_repository.grafana.repository_url}:latest" + image = "${local.orchestrator_account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/cdp-grafana:latest" lg_name = aws_cloudwatch_log_group.grafana.name lg_prefix = "telemetry" lg_region = data.aws_region.current.name diff --git a/terragrunt/modules/telemetry/variables.tf b/terragrunt/modules/telemetry/variables.tf index 6d434ca74..7ce5bd9f9 100644 --- a/terragrunt/modules/telemetry/variables.tf +++ b/terragrunt/modules/telemetry/variables.tf @@ -1,3 +1,8 @@ +variable "account_ids" { + description = "Map of all accounts and their IDs" + type = map(string) +} + variable "ecs_alb_sg_id" { description = "Application load-balancer security group ID" type = string From 50c37ac8dea154466b1226ce631151005a8b7dca Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Sun, 14 Jul 2024 18:02:14 +0100 Subject: [PATCH 07/18] DP-187 Upgrade terraform and terragrunt - Add codebuild custom image configuration --- .mise.toml | 4 +-- terragrunt/modules/orchestrator/ecr/main.tf | 2 +- terragrunt/providers.tf | 2 +- terragrunt/tools/codebuild/Dockerfile | 34 ++++++++++++++++++ terragrunt/tools/codebuild/README.md | 38 +++++++++++++++++++++ 5 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 terragrunt/tools/codebuild/Dockerfile create mode 100644 terragrunt/tools/codebuild/README.md diff --git a/.mise.toml b/.mise.toml index 2c85749a9..57c59e7c6 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,4 +1,4 @@ [tools] dotnet = "8.0.300" -terraform = "1.8.2" -terragrunt = "0.58.2" +terraform = "1.9.2" +terragrunt = "0.62.0" diff --git a/terragrunt/modules/orchestrator/ecr/main.tf b/terragrunt/modules/orchestrator/ecr/main.tf index ea95c7ce2..ec37eabaa 100644 --- a/terragrunt/modules/orchestrator/ecr/main.tf +++ b/terragrunt/modules/orchestrator/ecr/main.tf @@ -2,7 +2,7 @@ resource "aws_ecr_repository" "this" { for_each = toset(local.repositories) name = "cdp-${each.value}" - image_tag_mutability = each.value != "grafana" ? "IMMUTABLE" : "MUTABLE" + image_tag_mutability = contains(["grafana", "codebuild"], each.value) ? "MUTABLE" : "IMMUTABLE" image_scanning_configuration { scan_on_push = true diff --git a/terragrunt/providers.tf b/terragrunt/providers.tf index c79044814..7cb48aa7b 100644 --- a/terragrunt/providers.tf +++ b/terragrunt/providers.tf @@ -1,5 +1,5 @@ terraform { - required_version = "= 1.8.2" + required_version = "= 1.9.2" required_providers { aws = { version = "~> 5.48.0" diff --git a/terragrunt/tools/codebuild/Dockerfile b/terragrunt/tools/codebuild/Dockerfile new file mode 100644 index 000000000..b54cfdedc --- /dev/null +++ b/terragrunt/tools/codebuild/Dockerfile @@ -0,0 +1,34 @@ +FROM amazonlinux:latest + +# Build arguments for Terraform and Terragrunt versions +ARG TERRAFORM_VERSION +ARG TERRAGRUNT_VERSION + +# Install yum-config-manager to manage your repositories +RUN yum install -y yum-utils + +# Use yum-config-manager to add the official HashiCorp Linux repository +RUN yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo + +# Install Terraform +RUN yum install -y terraform-${TERRAFORM_VERSION} + +# Install necessary tools +RUN yum install -y wget unzip + +# Download and install Terragrunt +RUN wget https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VERSION}/terragrunt_linux_amd64 +RUN mv terragrunt_linux_amd64 /usr/local/bin/terragrunt +RUN chmod +x /usr/local/bin/terragrunt + +# Verify Terraform and Terragrunt are installed +RUN terraform --version +RUN terragrunt --version + +# Install AWS CLI +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +RUN unzip awscliv2.zip +RUN ./aws/install + +# Verify AWS CLI is installed +RUN aws --version diff --git a/terragrunt/tools/codebuild/README.md b/terragrunt/tools/codebuild/README.md new file mode 100644 index 000000000..303cfbab1 --- /dev/null +++ b/terragrunt/tools/codebuild/README.md @@ -0,0 +1,38 @@ +# Coldbuild + +This configuration is to build custom CodeBuild image to be used by CodeBuild jobs in different accounts. + +> In the following examples ave is alias for `aws-vault exec` command. +Feel free to use any convenient AWS profiler instead. + +## build + +```shell +TERRAFORM_VERSION=$(grep -Po '(?<=terraform = ")[^"]*' ../../../.mise.toml) +TERRAGRUNT_VERSION=$(grep -Po '(?<=terragrunt = ")[^"]*' ../../../.mise.toml) + +if [ -z "$TERRAFORM_VERSION" ] || [ -z "$TERRAGRUNT_VERSION" ]; then + echo "Error: Could not find Terraform or Terragrunt versions in .mise.toml" + exit 1 +fi + +docker build --build-arg TERRAFORM_VERSION=$TERRAFORM_VERSION\ + --build-arg TERRAGRUNT_VERSION=$TERRAGRUNT_VERSION \ + -t cabinetoffice/cdp-codebuild . + +echo -e "Built completed, and the new image contains:\n $(docker run --rm cabinetoffice/cdp-codebuild terraform version)\n $(docker run --rm cabinetoffice/cdp-codebuild terragrunt --version)\n$(docker run --rm cabinetoffice/cdp-codebuild aws --version)" + +``` + +## Deploy + +### Push to ECR + +There are individual ECR repositories in each account. Using the following commands, we can push the built image to different accounts. + +```shell +ACCOUNT_ID=$(ave aws sts get-caller-identity | jq -r '.Account') +ave aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.eu-west-2.amazonaws.com +docker tag cabinetoffice/cdp-codebuild:latest ${ACCOUNT_ID}.dkr.ecr.eu-west-2.amazonaws.com/cdp-codebuild:latest +docker push ${ACCOUNT_ID}.dkr.ecr.eu-west-2.amazonaws.com/cdp-codebuild:latest +``` From 22f8e136f9cfbe55c86da70273560e12f783db43 Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Mon, 15 Jul 2024 09:03:17 +0100 Subject: [PATCH 08/18] DP-187 Add whitespace check during build before test and publish --- .github/workflows/main-build-test-publish.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main-build-test-publish.yaml b/.github/workflows/main-build-test-publish.yaml index e290caba1..0274929de 100644 --- a/.github/workflows/main-build-test-publish.yaml +++ b/.github/workflows/main-build-test-publish.yaml @@ -20,6 +20,7 @@ jobs: run: | dotnet tool restore dotnet restore + dotnet format whitespace --verbosity d dotnet build - name: Build Docker Images From a7a3d23dd026e6dacf22833bacbf1c170681cf87 Mon Sep 17 00:00:00 2001 From: Ali Bahman Date: Mon, 15 Jul 2024 10:49:34 +0100 Subject: [PATCH 09/18] DP-187 Revert Github workflows --- .../{main-pr-check.yml => build.yml} | 15 +- .../workflows/main-build-test-publish.yaml | 144 ------------------ 2 files changed, 12 insertions(+), 147 deletions(-) rename .github/workflows/{main-pr-check.yml => build.yml} (83%) delete mode 100644 .github/workflows/main-build-test-publish.yaml diff --git a/.github/workflows/main-pr-check.yml b/.github/workflows/build.yml similarity index 83% rename from .github/workflows/main-pr-check.yml rename to .github/workflows/build.yml index 6fd6786a6..02fbd511a 100644 --- a/.github/workflows/main-pr-check.yml +++ b/.github/workflows/build.yml @@ -1,8 +1,9 @@ name: Build on: - pull_request: + push: branches: [main] + pull_request: jobs: test: @@ -60,12 +61,20 @@ jobs: - name: Stop services run: make down - document: + docs: runs-on: ubuntu-latest - name: Publish documentation + name: Build documentation steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build run: cd docs && make build + - name: Publish + if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' + run: cd docs && make publish + - name: Upload Documentation + uses: actions/upload-artifact@v4 + with: + name: Documentation + path: docs/build/* diff --git a/.github/workflows/main-build-test-publish.yaml b/.github/workflows/main-build-test-publish.yaml deleted file mode 100644 index 0274929de..000000000 --- a/.github/workflows/main-build-test-publish.yaml +++ /dev/null @@ -1,144 +0,0 @@ -name: CI/CD Pipeline - -on: - push: - branches: [main] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '8.0.x' - - - name: Build .NET Project - run: | - dotnet tool restore - dotnet restore - dotnet format whitespace --verbosity d - dotnet build - - - name: Build Docker Images - run: make build-docker - - - name: Save Docker Images - run: | - docker save -o cdp-images.tar cabinetoffice/cdp-organisation-information-migrations:latest cabinetoffice/cdp-data-sharing:latest cabinetoffice/cdp-entity-verification:latest cabinetoffice/cdp-forms:latest cabinetoffice/cdp-organisation-app:latest cabinetoffice/cdp-organisation:latest cabinetoffice/cdp-person:latest cabinetoffice/cdp-tenant:latest cabinetoffice/cdp-authority:latest - - - name: Upload Docker Images as Artifacts - uses: actions/upload-artifact@v4 - with: - name: docker-images - path: cdp-images.tar - - test: - runs-on: ubuntu-latest - needs: build - env: - CDP_ORGANISATION_APP_PORT: 8888 - CDP_TENANT_PORT: 8811 - CDP_ORGANISATION_PORT: 8822 - CDP_PERSON_PORT: 8833 - CDP_FORMS_PORT: 8844 - CDP_DATA_SHARING_PORT: 8855 - - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '8.0.x' - - - name: Download Docker Images - uses: actions/download-artifact@v4 - with: - name: docker-images - - - name: Load Docker Images - run: docker load -i cdp-images.tar - - - name: Start services - run: make up - - - name: Run Tests - run: | - dotnet test --logger trx --results-directory TestResults - - - name: Stop services - run: make down - - publish: - runs-on: ubuntu-latest - needs: test - if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' - - steps: - - uses: actions/checkout@v4 - - - name: Download Docker Images - uses: actions/download-artifact@v4 - with: - name: docker-images - - - name: Load Docker Images - run: docker load -i cdp-images.tar - - - name: Set up AWS CLI - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: eu-west-2 - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 - - - name: Generate Image Version - id: image_version - run: | - IMAGE_VERSION=$(date +%Y%m%d)-$(git rev-parse --short HEAD) - echo "IMAGE_VERSION=$IMAGE_VERSION" >> $GITHUB_ENV - - - name: Tag and Push Docker Images - run: | - for image in cabinetoffice/cdp-organisation-information-migrations cabinetoffice/cdp-data-sharing cabinetoffice/cdp-entity-verification cabinetoffice/cdp-forms cabinetoffice/cdp-organisation-app cabinetoffice/cdp-organisation cabinetoffice/cdp-person cabinetoffice/cdp-tenant cabinetoffice/cdp-authority; do - CLEAN_IMAGE_NAME=$(echo $image | sed 's/^cabinetoffice\///') - docker tag $image:latest ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-west-2.amazonaws.com/$CLEAN_IMAGE_NAME:${{ env.IMAGE_VERSION }} - docker push ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-west-2.amazonaws.com/$CLEAN_IMAGE_NAME:${{ env.IMAGE_VERSION }} - done - - - name: Create Git Tag - run: | - git config --global user.name "github-actions" - git config --global user.email "github-actions@github.com" - git tag ${{ env.IMAGE_VERSION }} - git push origin ${{ env.IMAGE_VERSION }} - - - name: Store Version in SSM Parameter Store - run: | - aws ssm put-parameter --name "cdp-sirsi-service-version" --value "${{ env.IMAGE_VERSION }}" --type String --overwrite - - document: - runs-on: ubuntu-latest - name: Publish documentation - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Build - run: cd docs && make build - - name: Publish - if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' - run: cd docs && make publish-docs-during-cd - - name: Upload Documentation - uses: actions/upload-artifact@v4 - with: - name: Documentation - path: docs/build/* From ba23d4b902085bfbba621c7315cb8618abac316b Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 12:40:32 +0100 Subject: [PATCH 10/18] Expect the image version to be explicitly passed to the aws-push-to-ecr target --- Makefile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 9f507c0fc..46147935f 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,6 @@ AWS_ACCOUNT_ID=$$(aws sts get-caller-identity | jq -r '.Account') REPO_URL := $(AWS_ACCOUNT_ID).dkr.ecr.eu-west-2.amazonaws.com IMAGES := cdp-organisation-information-migrations cdp-data-sharing cdp-entity-verification cdp-forms cdp-organisation-app cdp-organisation cdp-person cdp-tenant cdp-authority -DATE := $(shell date +%Y%m%d) -TIME := $(shell date +%H%M) -COMMIT_REVISION := $(shell git rev-parse --short HEAD) -TAG := $(DATE)-localbuild-$(TIME)-$(COMMIT_REVISION) DOCKER_COMPOSE_CMD=IMAGE_VERSION=$(IMAGE_VERSION) docker compose # Extracts targets and their comments @@ -165,10 +161,11 @@ aws-push-authority-private-key: ## Push Authority's private key to the target AW aws secretsmanager create-secret --name cdp-sirsi-authority-keys --secret-string "$$(jq -n --arg priv "$$(cat ./terragrunt/secrets/authority-private-key.pem)" '{PRIVATE: $$priv}')"; \ fi +aws-push-to-ecr: IMAGE_VERSION ?= latest aws-push-to-ecr: ## Tag latest built Docker images and push to ECR - $(foreach image,$(IMAGES),docker tag cabinetoffice/$(image):latest $(REPO_URL)/$(image):$(TAG);) + $(foreach image,$(IMAGES),docker tag cabinetoffice/$(image):$(IMAGE_VERSION) $(REPO_URL)/$(image):$(IMAGE_VERSION);) aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin $(REPO_URL) - $(foreach image,$(IMAGES),docker push $(REPO_URL)/$(image):$(TAG);) + $(foreach image,$(IMAGES),docker push $(REPO_URL)/$(image):$(IMAGE_VERSION);) .PHONY: aws-push-to-ecr aws-build-and-push-ecr: build-docker aws-push-to-ecr ## Build, tag and push Docker images to ECR From b0789002ca0cbf4eb06865a9abe7db8e1ba7bacf Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 12:52:45 +0100 Subject: [PATCH 11/18] Remove a duplicate target --- docs/Makefile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 5744919b4..90b5d1970 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -15,14 +15,6 @@ publish: build/cdp.html git add index.html && git commit -m 'Update the documentation' && git push origin gh-pages .PHONY: publish -publish-docs-during-cd: build/cdp.html - git config --global user.name 'github-actions' - git config --global user.email 'github-actions@github.com' - git checkout gh-pages - cp build/cdp.html index.html - git add index.html && git commit -m 'Update the documentation' && git push origin gh-pages -.PHONY: publish-docs-during-cd - build-docker: docker build -t cabinetoffice/asciidoctor . .PHONY: build-docker From a4ef2ad80a56b777aed61dc8379bf04dbeb26032 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 13:51:49 +0100 Subject: [PATCH 12/18] Save docker images as build artifacts --- .github/workflows/build.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01aa82727..daee66e28 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,6 +78,17 @@ jobs: run: make down env: IMAGE_VERSION: ${{ steps.version.outputs.version }} + - name: Save Docker Images + run: | + IMAGES=$(docker images | awk '$1 ~ /cabinetoffice\/cdp-/ && $2 ~ /^'$IMAGE_VERSION'$/ { print $1":"$2}') + docker save -o cdp-images.tar $IMAGES + env: + IMAGE_VERSION: ${{ steps.version.outputs.version }} + - name: Upload Docker Images as Artifacts + uses: actions/upload-artifact@v4 + with: + name: docker-images + path: cdp-images.tar docs: runs-on: ubuntu-latest From 348306b8b6bed2243699edb68a39de57fd62d776 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 13:59:30 +0100 Subject: [PATCH 13/18] Debug saved images --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index daee66e28..cc70ad9dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,6 +81,7 @@ jobs: - name: Save Docker Images run: | IMAGES=$(docker images | awk '$1 ~ /cabinetoffice\/cdp-/ && $2 ~ /^'$IMAGE_VERSION'$/ { print $1":"$2}') + echo "Images to be saved: $IMAGES" docker save -o cdp-images.tar $IMAGES env: IMAGE_VERSION: ${{ steps.version.outputs.version }} From cb169670261e1838a7076d96926719b7219d5173 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 14:05:04 +0100 Subject: [PATCH 14/18] Extract docs to a separate build --- .github/workflows/build.yml | 18 ------------------ .github/workflows/docs.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cc70ad9dd..d27fe57e1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,21 +90,3 @@ jobs: with: name: docker-images path: cdp-images.tar - - docs: - runs-on: ubuntu-latest - name: Build documentation - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Build - run: cd docs && make build - - name: Publish - if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' - run: cd docs && make publish - - name: Upload Documentation - uses: actions/upload-artifact@v4 - with: - name: Documentation - path: docs/build/* diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..a154d9bf0 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,26 @@ +name: Docs + +on: + push: + branches: [main] + pull_request: + +jobs: + + docs: + runs-on: ubuntu-latest + name: Build documentation + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Build + run: cd docs && make build + - name: Publish + if: github.ref == 'refs/heads/main' && github.repository_owner == 'cabinetoffice' + run: cd docs && make publish + - name: Upload Documentation + uses: actions/upload-artifact@v4 + with: + name: Documentation + path: docs/build/* From 20ef77aabd97b1daab01ed76bcd96b07b1bc579d Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 14:06:58 +0100 Subject: [PATCH 15/18] Combine images list to a single line --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d27fe57e1..88aca5c51 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,7 +80,7 @@ jobs: IMAGE_VERSION: ${{ steps.version.outputs.version }} - name: Save Docker Images run: | - IMAGES=$(docker images | awk '$1 ~ /cabinetoffice\/cdp-/ && $2 ~ /^'$IMAGE_VERSION'$/ { print $1":"$2}') + IMAGES=$(docker images | awk '$1 ~ /cabinetoffice\/cdp-/ && $2 ~ /^'$IMAGE_VERSION'$/ { print $1":"$2}' | tr '\n' ' ') echo "Images to be saved: $IMAGES" docker save -o cdp-images.tar $IMAGES env: From d0409d97270eaa7e409980e6659384e45bb0b1c9 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 14:23:41 +0100 Subject: [PATCH 16/18] Prepare for publishing images to AWS ECR --- .github/workflows/build.yml | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 88aca5c51..980ca4860 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,7 @@ jobs: name: OpenAPI path: OpenAPI - docker: + package: runs-on: ubuntu-latest name: Build containers env: @@ -52,6 +52,8 @@ jobs: CDP_PERSON_PORT: 8833 CDP_FORMS_PORT: 8844 CDP_DATA_SHARING_PORT: 8855 + outputs: + version: ${{ steps.version.outputs.version }} steps: - uses: actions/checkout@v4 with: @@ -90,3 +92,36 @@ jobs: with: name: docker-images path: cdp-images.tar + + publish: + runs-on: ubuntu-latest + name: Publish containers + needs: [test, package] + + steps: + - uses: actions/checkout@v4 + + - name: Download Docker Images + uses: actions/download-artifact@v4 + with: + name: docker-images + + - name: Load Docker Images + run: docker load -i cdp-images.tar + + - name: Set up AWS CLI + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: eu-west-2 + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + + - name: Generate Image Version + id: image_version + run: | + IMAGE_VERSION=${{ needs.build.outputs.push }} + echo "IMAGE_VERSION=$IMAGE_VERSION" >> $GITHUB_ENV From 952d0c8ac464aef6a532ba1d071724a0825fce74 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 14:30:35 +0100 Subject: [PATCH 17/18] Fix a typo --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 980ca4860..e0f221f84 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -123,5 +123,5 @@ jobs: - name: Generate Image Version id: image_version run: | - IMAGE_VERSION=${{ needs.build.outputs.push }} + IMAGE_VERSION=${{ needs.package.outputs.push }} echo "IMAGE_VERSION=$IMAGE_VERSION" >> $GITHUB_ENV From f25760a59682417cf47ce2e10617fb2699c81281 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 15 Jul 2024 14:38:08 +0100 Subject: [PATCH 18/18] Fix a typo --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e0f221f84..4680b0d8a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -123,5 +123,5 @@ jobs: - name: Generate Image Version id: image_version run: | - IMAGE_VERSION=${{ needs.package.outputs.push }} + IMAGE_VERSION=${{ needs.package.outputs.version }} echo "IMAGE_VERSION=$IMAGE_VERSION" >> $GITHUB_ENV