Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NRL-793] Add github action to update deployed permissions #708

Merged
merged 5 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/persistent-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,7 @@ jobs:

- name: Update environment config version
run: |
short_commit_ref="$(echo ${{ github.sha }} | cut -c1-8)"
deployed_version="${{ inputs.branch_name }}@${short_commit_ref}"
deployed_version=$(terraform -chdir=terraform/infrastructure output --raw version)
poetry run python ./scripts/set_env_config.py inactive-version ${deployed_version} ${{ inputs.environment }}

- name: Smoke Test
Expand Down
270 changes: 270 additions & 0 deletions .github/workflows/update-lambda-permissions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
name: Update Lambda Permissions
run-name: Updating permissions on ${{ inputs.environment }} using ${{ inputs.branch_name }} by ${{ github.actor }}

on:
workflow_dispatch:
inputs:
environment:
description: Environment to deploy to
required: true
default: "dev"
type: environment

stack_name:
description: Name of stack to apply permissions to
required: true
type: string

branch_name:
description: Branch to deploy
required: true

permissions:
id-token: write
contents: read
actions: write

jobs:
check-versions:
name: Check versions
runs-on: [self-hosted, ci]

steps:
- name: Git clone - ${{ github.ref }}
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Setup asdf cache
uses: actions/cache@v4
with:
path: ~/.asdf
key: ${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}
restore-keys: |
${{ runner.os }}-asdf-

- name: Install asdf
uses: asdf-vm/actions/[email protected]

- name: Install zip
run: sudo apt-get install zip

- name: Setup Python environment
run: |
poetry install --no-root
source $(poetry env info --path)/bin/activate

- name: Configure Management Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-to-assume: ${{ secrets.MGMT_ROLE_ARN }}
role-session-name: github-actions-ci-${{ inputs.environment }}-${{ github.run_id }}

- name: Terraform Init
run: |
terraform -chdir=terraform/infrastructure init
terraform -chdir=terraform/infrastructure workspace new ${{ inputs.stack_name }} || \
terraform -chdir=terraform/infrastructure workspace select ${{ inputs.stack_name }}

- name: Check deployed version matches build version
run: |
this_version="$(./scripts/get-current-info.sh) | jq -r .version)"
deployed_version="$(terraform -chdir=terraform/infrastructure output --raw version)"

if [ "${deployed_version}" != "${this_version}" ]; then
echo "Deployed version is ${deployed_version}, not ${this_version}"
exit 1
fi

echo "Deployed version matches this version: ${deployed_version}"

build-permissions:
name: Build permissions for ${{ inputs.environment }}
runs-on: [self-hosted, ci]
environment: ${{ inputs.environment }}

needs: [check-versions]

steps:
- name: Git clone - ${{ github.ref }}
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Setup asdf cache
uses: actions/cache@v4
with:
path: ~/.asdf
key: ${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}
restore-keys: |
${{ runner.os }}-asdf-

- name: Install asdf
uses: asdf-vm/actions/[email protected]

- name: Install zip
run: sudo apt-get install zip

- name: Setup Python environment
run: |
poetry install --no-root
source $(poetry env info --path)/bin/activate

- name: Configure Management Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-to-assume: ${{ secrets.MGMT_ROLE_ARN }}
role-session-name: github-actions-ci-${{ inputs.environment }}-${{ github.run_id }}

- name: Create lambda permissions layer
run: |
account=$(echo '${{ inputs.environment }}' | cut -d '-' -f1)
make get-s3-perms ENV=${account} TF_WORKSPACE_NAME=${{ inputs.stack_name }}

- name: Save NRLF permissions in cache
uses: actions/cache/save@v4
with:
key: ${{ github.run_id }}-nrlf-permissions
path: dist/nrlf_permissions.zip

pull-deployed-lambdas:
name: Pull deployed lambdas from ${{ inputs.stack_name }}
runs-on: [self-hosted, ci]
environment: ${{ inputs.environment }}

needs: [check-versions]

steps:
- name: Git clone - ${{ github.ref }}
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Configure Management Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-to-assume: ${{ secrets.MGMT_ROLE_ARN }}
role-session-name: github-actions-ci-${{ inputs.environment }}-${{ github.run_id }}

- name: Configure Account Role
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-chaining: true
role-to-assume: ${{ secrets.DEPLOY_ROLE_ARN }}
role-session-name: github-actions-ci-acc-${{ inputs.environment }}-${{ github.run_id }}

- name: Pull deployed lambda artifacts
run: |
account=$(echo '${{ inputs.environment }}' | cut -d '-' -f1)
./scripts/pull-lambda-code-for-stack.sh ${{ inputs.stack_name }}

- name: Save lambda artifacts in cache
uses: actions/cache/save@v4
with:
key: ${{ github.run_id }}-pulled-lambda-artifacts
path: dist/*.zip

terraform-plan:
name: Plan changes to ${{ inputs.stack_name }} for ${{ inputs.environment }}
runs-on: [self-hosted, ci]
environment: ${{ inputs.environment }}

needs: [build-permissions, pull-deployed-lambdas]

steps:
- name: Git clone - ${{ github.ref }}
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Restore pulled lambda artifacts
uses: actions/cache/restore@v4
with:
key: ${{ github.run_id }}-pulled-lambda-artifacts
path: ./dist
fail-on-cache-miss: true

- name: Restore NRLF permissions cache
uses: actions/cache/restore@v4
with:
key: ${{ github.run_id }}-nrlf-permissions
path: dist/nrlf_permissions.zip
fail-on-cache-miss: true

- name: Configure Management Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-to-assume: ${{ secrets.MGMT_ROLE_ARN }}
role-session-name: github-actions-ci-${{ inputs.environment }}-${{ github.run_id }}

- name: Terraform Init
run: |
terraform -chdir=terraform/infrastructure init
terraform -chdir=terraform/infrastructure workspace new ${{ inputs.stack_name }} || \
terraform -chdir=terraform/infrastructure workspace select ${{ inputs.stack_name }}

- name: Terraform Plan
run: |
terraform -chdir=terraform/infrastructure plan \
--var-file=etc/${{ vars.ACCOUNT_NAME }}.tfvars \
--var assume_role_arn=${{ secrets.DEPLOY_ROLE_ARN }} \
--var use_shared_resources=$(poetry run python scripts/are_resources_shared_for_stack.py ${{ inputs.stack_name }}) \
--out tfplan

- name: Save Terraform Plan
run: |
terraform -chdir=terraform/infrastructure show -no-color tfplan > terraform/infrastructure/tfplan.txt
aws s3 cp terraform/infrastructure/tfplan s3://nhsd-nrlf--mgmt--github-ci-logging/${{ inputs.environment }}/${{ github.run_id }}/tfplan
aws s3 cp terraform/infrastructure/tfplan.txt s3://nhsd-nrlf--mgmt--github-ci-logging/${{ inputs.environment }}/${{ github.run_id }}/tfplan.txt

terraform-apply:
name: Apply permissions to ${{ inputs.stack_name }} for ${{ inputs.environment }}
runs-on: [self-hosted, ci]
environment: ${{ inputs.environment }}

needs: terraform-plan

steps:
- name: Git clone - ${{ github.ref }}
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Restore pulled lambda artifacts
uses: actions/cache/restore@v4
with:
key: ${{ github.run_id }}-pulled-lambda-artifacts
path: ./dist
fail-on-cache-miss: true

- name: Restore NRLF permissions cache
uses: actions/cache/restore@v4
with:
key: ${{ github.run_id }}-nrlf-permissions
path: dist/nrlf_permissions.zip
fail-on-cache-miss: true

- name: Configure Management Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-to-assume: ${{ secrets.MGMT_ROLE_ARN }}
role-session-name: github-actions-ci-${{ inputs.environment }}-${{ github.run_id }}

- name: Download Terraform Plan artifact
run: aws s3 cp s3://nhsd-nrlf--mgmt--github-ci-logging/${{ inputs.environment }}/${{ github.run_id }}/tfplan terraform/infrastructure/tfplan

- name: Terraform Init
run: |
terraform -chdir=terraform/infrastructure init
terraform -chdir=terraform/infrastructure workspace new ${{ inputs.stack_name }} || \
terraform -chdir=terraform/infrastructure workspace select ${{ inputs.stack_name }}

- name: Terraform Apply
run: |
terraform -chdir=terraform/infrastructure apply tfplan
8 changes: 8 additions & 0 deletions scripts/get_current_info.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
# Get the current info about the codebase
set -o errexit -o nounset -o pipefail

BRANCH_NAME="$(git rev-parse --abbrev-ref HEAD)"
SHORT_COMMIT_HASH="$(git rev-parse --short=8 HEAD)"

echo "{ \"version\": \"${BRANCH_NAME}@${SHORT_COMMIT_HASH}\" }"
78 changes: 78 additions & 0 deletions scripts/pull-lambda-code-for-stack.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash
# Pull down all the lambda code for the named stack
set -o errexit -o nounset -o pipefail

: "${DIST_DIR:="./dist"}"

if [ $# -ne 1 ]
then
echo "Error: stack-name argument is missing" 1>&2
echo "Usage: $0 <stack-name>" 1>&2
exit 1
fi

stack_name="$1"

function pull_lambda_code(){
local api_name="$1"
local endpoint_name="$2"

lambda_name="nhsd-nrlf--${stack_name}--api--${api_name}--${endpoint_name}"

echo -n "- Downloading code for lambda ${lambda_name}.... "
code_url="$(aws lambda get-function --function-name "${lambda_name}" | jq -r .Code.Location)"
curl "${code_url}" 2>/dev/null > "${DIST_DIR}/${api_name}-${endpoint_name}.zip"
echo "✅"
}

function pull_layer_code(){
local name="$1"

layer_name="nhsd-nrlf--${stack_name}--${name}"
layer_pkg_name="$(echo "${name}" | tr '-' '_').zip"
layer_version="$(aws lambda list-layer-versions --layer-name "${layer_name}" | jq -r '.LayerVersions[0].Version')"

echo -n "- Downloading code for layer ${layer_name} version ${layer_version}.... "
code_url="$(aws lambda get-layer-version --layer-name "${layer_name}" --version-number "${layer_version}" | jq -r .Content.Location)"
curl "${code_url}" 2>/dev/null > "${DIST_DIR}/${layer_pkg_name}"
echo "✅"
}

mkdir -p "${DIST_DIR}"

echo
echo "Pulling code for consumer API lambdas...."
for endpoint_path in api/consumer/*
do
if [ ! -d "${endpoint_path}" ]
then
continue
fi

endpoint_name="$(basename "${endpoint_path}")"
pull_lambda_code "consumer" "${endpoint_name}"
done

echo
echo "Pulling code for producer API lambdas...."
for endpoint_path in api/producer/*
do
if [ ! -d "${endpoint_path}" ]
then
continue
fi

endpoint_name="$(basename "${endpoint_path}")"
pull_lambda_code "producer" "${endpoint_name}"
done

echo
echo "Pulling code for layers...."
for layer_name in nrlf dependency-layer nrlf-permissions
do
pull_layer_code "${layer_name}"
done

echo
echo "✅ Done. Code is in ${DIST_DIR}"
echo
7 changes: 7 additions & 0 deletions terraform/infrastructure/data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,10 @@ data "aws_iam_policy" "pointers-kms-read-write" {
count = var.use_shared_resources ? 1 : 0
name = "${local.shared_prefix}-pointers-kms-read-write"
}

data "external" "current-info" {
program = [
"bash",
"../../scripts/get_current_info.sh",
]
}
4 changes: 4 additions & 0 deletions terraform/infrastructure/output.tf
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ output "certificate_domain_name" {
output "auth_store" {
value = local.auth_store_id
}

output "version" {
value = data.external.current-info.result.version
}