ministryofjustice / modernisation-platform-ami-builds

Modernisation platform AMI builds • This repository is defined and managed in Terraform

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Modernisation Platform AMI builds

repo standards badge

Introduction

This repository contains the Modernisation Platform AMI build code and workflows.

Contents

AWS EC2 Image Builder

Infrastructure-as-code (Terraform) is used in this repository to define AMIs and uses AWS EC2 Image Builder - a managed service for building, testing and deploying Amazon Machine Images. See https://docs.aws.amazon.com/imagebuilder/latest/userguide/what-is-image-builder.html for information.

AWS Image Builder introduces concepts such as pipelines, recipes and components to define an AMI. These concepts are backed by equivalent Terraform resources. Recipes and Components natively enforce versioning, allowing changes to be tracked and identified. This raises an interesting consideration around the declarative nature of Terraform in combination with inherent versioning within Git repositories - a consideration which has led to a recommended approach in the use of AWS Image Builder within this repository.

Building and testing of AMIs target the core-shared-services account

All Image Builder resources are deployed to, and execute within, the core-shared-services account within the Modernisation Platform. Therefore, Image Builder resources other than your own will exist in this account. However, all resources are prefixed with a team name to allow your resources to be easily identified and separated from others.

Structure

In terms of defining AMIs, three important directories exist in this repository.

  • ./modernisation-platform
    • This directory will contain pipelines that will define AMIs acting as parent images for more customised AMIs required by Modernisation Platform consumers. Types of AMIs produced could be
      • AMIs for hardened OSs
      • AMIs for vanilla server applications, installed onto hardened OSs
  • ./teams
    • This directory is designed to hold additional directories for each team that is a Modernisation Platform consumer (AKA environment or member)
    • Teams therefore define their AMIs within their own directory, referencing parent images defined and generated within the Modernisation Platform directory
    • The example directory is a template for each new team
  • ./ansible
    • This directory will contain common ansible resources, such as ansible roles, that can be used in AMI builds.

The modernisation-platform and teams directories also contain a components directory, holding components relevant to Linux or Windows (within the respective OS folder)

How to guides

How to add a new team

To add a new team

  • copy the files under the teams/example directory into e.g. teams/your_team
  • change the team_name variable in locals.tf, which will subsequently be interpolated and used in all Image Builder resource names.
  • Each team directory will use a different terraform remote state file defined in backend.tf - so also rename the state file name by renaming the key attribute value, updating the team name to be consistent to that used in the previous step.
  key = "imagebuilder-[team name].tfstate"

To ensure you can review any PRs you generate add the team to the .github/CODEOWNERS. Check the contents of the file to see what is needed. Generally it is /teams/ @ministryofjustice/. Ones that are currently in place can be seen in CODEOWNERS.

How to define an AMI (and associated Image Builder resources)

Using the linux_pipeline.tf and linux_pipeline_vars.tf files as example files

  • Replace linux_pipeline with your desired name for both files
  • Update components and aws_components lists with the sequenced components you want included in the image (components being your custom yml files under the components directory, aws_components being the names of the components supplied by Amazon which are [not in this repo])
  • Update any other variables you wish to change, such as cron schedule, instance size etc.

How to add your own team kms key

Under your team directory:

  • In data.tf, edit the data block changing the key_id to match the new key to be used in the pipeline.
    default key: key_id = "arn:aws:kms:eu-west-2:${data.aws_caller_identity.current.account_id}:alias/ebs-encryption-key"
    team key: key_id = "arn:aws:kms:eu-west-2:${local.environment_management.account_ids["<team environemnt>"]}:alias/<team kms key alias name>"\

example of team key: key_id = "arn:aws:kms:eu-west-2:${local.environment_management.account_ids["sprinkler-development"]}:alias/sprinkler_ebs-encryption-key"

The requirements, as an example, for sprinkler are shown below.

Under data.tf

data "aws_kms_key" "sprinkler_ebs_encryption_key" {
  key_id = "arn:aws:kms:eu-west-2:${local.environment_management.account_ids["sprinkler-development"]}:alias/sprinkler_ebs-encryption-key"
}

At the end of locals.tf include

ami_share_accounts = [
  "${local.environment_management.account_ids["sprinkler-development"]}"
]

The above can be seen in the pull request https://github.com/ministryofjustice/modernisation-platform-ami-builds/pull/18/files/6a589a6d3d0dc70f2bc28cb8cbb84075cad9d73c# but this includes far more detail than is required here.

Example code on how to create a team KMS key, and the permissions needed can be found in https://github.com/ministryofjustice/modernisation-platform-environments/blob/b73bba2e9d708efbc0db4492582829f52f00cb60/terraform/environments/sprinkler/kms.tf

How to use the per business unit shared kms key

There are keys created per business unit which have permissions to be used by all the member accounts in that business unit. Using these keys means you do not have to create your own key, and you can easily share your AMIs between other accounts in your business unit. A full list of the shared keys available can be found in the core-shared-services account. To be used as shown below.

data "aws_kms_key" "ebs_encryption_cmk" {key_id = "arn:aws:kms:eu-west-2:${data.aws_caller_identity.current.account_id}:alias/ebs-<business-unit>"}

For example:

data "aws_kms_key" "ebs_encryption_cmk" {key_id = "arn:aws:kms:eu-west-2:${data.aws_caller_identity.current.account_id}:alias/ebs-hmpps"}

How to edit ami account share

This is a optional task and doesn't have to be done, this should only be changed if you want to share images with particular accounts.
Under your team directory:

  • In locals.tf edit the ami_share_accounts section, changing the account from the default core-shared-services to your account of choice.
    default: "${local.environment_management.account_ids["core-shared-services-production"]}"
    member account: "${local.environment_management.account_ids["<member account>"]}"\

example member account: "${local.environment_management.account_ids["sprinkler-development"]}"

How to add new components and manage versions

To add a new component or make changes to an existing component:

  • Make the change to the file in the corresponding components directory (modernisation-platform or team)
  • Increment the component version in the parameters section of the component file
  • Increment the recipe version in the recipe block in the pipeline vars file

Both the component version(s) and recipe version will need to be updated for a successful Terraform run. No further change will need to be made to the component block of the pipeline terraform file to add / edit a component (there is logic to ingest the list defined in the pipeline vars and create terraform resources from them).

How to add a new GitHub workflow

GitHub workflow files are used to invoke Terraform and an example workflow is defined at ./.github/workflows/example.yml. To create a workflow for your team, simply copy example.yml and add a new file named [your_team_name].yml. The workflow within the example workflow has no branch condition that might restrict when Terraform is applied. Please change as appropriate for your team's processes.

How to view and start EC2 Image Builder pipelines

You can view and start EC2 Image Builder pipelines by assuming a role in the core-shared-services account.

  • Log in to the AWS console via SSO as a modernisation-platform-developer
  • Click your SSO username in the top right of the AWS Console and choose "Switch Role"
  • Enter the core-shared-services account number (see Slack message)
  • Enter role as member-shared-services
  • Navigate to EC2 Image Builder and click on “Image pipelines”
  • Choose your pipeline, you can view details and run the pipeline via “Actions”

Future additions and improvements

  • Investigate and implement a design around access to S3 buckets for purposes of analysing Image Builder logs and hosting of external software packages and installers
  • Implement AMI lifecycle management (including EBS volume snapshots)
  • Pipeline name could be variabilised further (e.g. with operating system)
  • Investigate and consider potential to integrate Image Distribution with AWS Organisation OUs (new feature at the time of writing introduced Oct 2021)
  • Consider separate environment for deploying / testing branches against
  • Consider implementation of OPA tests to safeguard changes to files that should remain static

About

Modernisation platform AMI builds • This repository is defined and managed in Terraform

License:MIT License


Languages

Language:HCL 92.4%Language:Shell 5.6%Language:Go 1.8%Language:PowerShell 0.2%Language:Batchfile 0.0%