Skip to content

Commit

Permalink
FDOS_142 Add bootstrapper stacks
Browse files Browse the repository at this point in the history
  • Loading branch information
timrickwood committed Feb 6, 2025
1 parent 733ed34 commit 2bad940
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
!project.code-workspace

# Please, add your custom content below!
*terraform.lock.hcl
60 changes: 60 additions & 0 deletions infrastructure/common/common-variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
variable "project" {
description = "The project code, typically reflecting a sub-project of the project owner"
}

variable "project_owner" {
description = "The owner of the project, based on organisation and department codes"
}

variable "environment" {
description = "The deployment environment e.g. dev, test, pre-prod, or prod"
}

variable "repo_name" {
description = "The name of the GitHub repository associated with this project"
}

variable "tag_version" {
description = "The version of the tagging policy in use, enabling evolution of the tagging strategy and supporting automation"
type = string
}

variable "service" {
description = "The service or program that this project is associated with"
type = string
}

variable "cost_centre" {
description = "The cost center used for consolidated billing and cost attribution to programs"
type = string
}

variable "data_classification" {
description = "The data classification according to the Cloud Risk Model, enabling quick searches e.g. Low, Medium, High"
type = string
}

variable "data_type" {
description = "The type of data handled by this project e.g. None, PCD, PII, Anonymized, UserAccount, Audit"
type = string
}

variable "project_type" {
description = "The purpose of the resources e.g PoC, Pilot, Production"
type = string
}

variable "public_facing" {
description = "Indicates if the project is accessible publicly via the internet"
type = string
}

variable "service_category" {
description = "Identifies the service category to prioritize responses"
type = string
}

variable "on_off_pattern" {
description = "Defines the automated schedule for turning resources on/off, applicable for non-production environments"
type = string
}
7 changes: 7 additions & 0 deletions infrastructure/common/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
locals {
account_id = data.aws_caller_identity.current.id
workspace_suffix = "${terraform.workspace}" == "default" ? "" : "-${terraform.workspace}"
prefix = "${var.project}-${var.environment}"

deploy_databases = var.environment == terraform.workspace
}
34 changes: 34 additions & 0 deletions infrastructure/common/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
variable "aws_region" {
type = string
default = "eu-west-2"
}

data "aws_caller_identity" "current" {}

provider "aws" {
region = var.aws_region

skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = false

default_tags {
tags = {
owner = var.project_owner
project = var.project
environment = "${var.environment}${local.workspace_suffix}"
workspace = terraform.workspace
terraform-base-path = replace(path.cwd, "/^.*?(${var.repo_name}\\/)/", "$1")
TagVersion = var.tag_version
service = var.service
CostCentre = var.cost_centre
data_classification = var.data_classification
DataType = var.data_type
ProjectType = var.project_type
PublicFacing = var.public_facing
ServiceCategory = var.service_category
OnOffPattern = var.on_off_pattern
}
}
}
13 changes: 13 additions & 0 deletions infrastructure/common/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
required_version = ">= 1.5.0, < 1.7.2"

backend "s3" {
}

required_providers {
aws = {
source = "hashicorp/aws"
version = "5.70.0"
}
}
}
13 changes: 13 additions & 0 deletions infrastructure/local/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
required_version = ">= 1.5.0, < 1.7.2"

backend "local" {
}

required_providers {
aws = {
source = "hashicorp/aws"
version = "5.70.0"
}
}
}
9 changes: 9 additions & 0 deletions infrastructure/stacks/account_wide/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Account-Wide Infrastructure

This is infrastructure that should only be deployed once per account.

> **Note**: This should be deployed using the `default` workspace.
Currently, the following resources are deployed:

1. IAM role for GitHub Actions (via OIDC)
79 changes: 79 additions & 0 deletions infrastructure/stacks/account_wide/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
data "aws_iam_policy" "power_user_iam_policy" {
name = "PowerUserAccess"
}

resource "aws_iam_role_policy_attachment" "power_user_iam_role_policy_attachment" {
role = aws_iam_role.github_runner_iam_role.name
policy_arn = data.aws_iam_policy.power_user_iam_policy.arn
}

resource "aws_iam_policy" "read_only_user_iam_policy" {
name = "${var.repo_name}-github-runner-iam-services"
description = "Read-only policy for IAM permissions required by GitHub runner"
policy = <<-EOF
{
"Version":"2012-10-17",
"Statement": [
{
"Action": [
"iam:GenerateCredentialReport",
"iam:List*",
"iam:GenerateServiceLastAccessedDetails",
"iam:TagRole",
"iam:DeletePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:AttachRolePolicy",
"iam:TagPolicy",
"iam:CreatePolicy",
"iam:PassRole",
"iam:Get*",
"iam:DetachRolePolicy",
"iam:SimulatePrincipalPolicy",
"iam:SimulateCustomPolicy",
"iam:CreatePolicyVersion",
"iam:DeletePolicyVersion",
"iam:TagOpenIDConnectProvider",
"iam:DeleteRolePolicy",
"iam:PutRolePolicy",
"iam:UpdateOpenIDConnectProviderThumbprint",
"iam:UntagPolicy",
"iam:UntagRole"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "ReadOnlyIAM"
}
]
}
EOF
}

resource "aws_iam_role_policy_attachment" "read_only_user_iam_role_policy_attachment" {
role = aws_iam_role.github_runner_iam_role.name
policy_arn = aws_iam_policy.read_only_user_iam_policy.arn
}

resource "aws_iam_role" "github_runner_iam_role" {
name = "${var.repo_name}-github-runner"
assume_role_policy = <<EOF
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal":{
"Federated":"arn:aws:iam::${local.account_id}:oidc-provider/token.actions.githubusercontent.com"
},
"Action":"sts:AssumeRoleWithWebIdentity",
"Condition":{
"ForAllValues:StringLike":{
"token.actions.githubusercontent.com:sub":"repo:${var.github_org}/${var.repo_name}:*",
"token.actions.githubusercontent.com:aud":"sts.amazonaws.com"
}
}
}
]
}
EOF
}
3 changes: 3 additions & 0 deletions infrastructure/stacks/account_wide/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
variable "github_org" {
description = "The name of the GitHub organization e.g. NHSDigital"
}
10 changes: 10 additions & 0 deletions infrastructure/stacks/terraform_management/dynamodb.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module "terraform_lock_dynamodb" {
source = "../../modules/dynamodb"
table_name = var.terraform_lock_table_name

hash_key = "LockID"
attributes = [{
name = "LockID"
type = "S"
}]
}
4 changes: 4 additions & 0 deletions infrastructure/stacks/terraform_management/s3.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module "terraform_state_bucket" {
source = "../../modules/s3"
bucket_name = var.terraform_state_bucket_name
}
12 changes: 12 additions & 0 deletions infrastructure/stacks/terraform_management/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
variable "terraform_lock_table_name" {
description = "Name of dynamodb table that holds terraformn state locks"
}

variable "terraform_state_bucket_name" {
description = "Name of s3 bucket that holds terraform state"
}

variable "s3_versioning" {
description = "Whether versioning is enabled for the S3 bucket that holds the Terraform state"
type = bool
}
2 changes: 1 addition & 1 deletion scripts/docker/docker.lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ function docker-get-image-version-and-pull() {
local digest="$(echo "$version" | sed 's/^.*@//')"

# Check if the image exists locally already
if ! docker images | awk '{ print $1 ":" $2 }' | grep -q "^${name}:${tag}$"; then
if ! $DOCKER_CMD images | awk '{ print $1 ":" $2 }' | grep -q "^${name}:${tag}$"; then
if [ "$digest" != "latest" ]; then
# Pull image by the digest sha256 and tag it
$DOCKER_CMD pull \
Expand Down
36 changes: 18 additions & 18 deletions scripts/workflow/bootstrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ function terraform-initialise {
}

function github_runner_stack {
# now do github runner stack
export STACK=github-runner
# now do account_wide stack for github runner and for oidc provider
export STACK=account_wide
# specific to stack
STACK_TF_VARS_FILE="$STACK.tfvars"
# the directory that holds the stack to terraform
Expand Down Expand Up @@ -156,17 +156,17 @@ function github_runner_stack {

if [ -n "$ACTION" ] && [ "$ACTION" = 'plan' ] ; then
terraform plan \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$COMMON_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$STACK_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$PROJECT_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$COMMON_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$STACK_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$PROJECT_TF_VARS_FILE \
-var-file "$ENVIRONMENTS_DIR/$ENV_TF_VARS_FILE"
fi

if [ -n "$ACTION" ] && [ "$ACTION" = 'apply' ] ; then
terraform apply -auto-approve \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$COMMON_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$STACK_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$PROJECT_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$COMMON_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$STACK_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$PROJECT_TF_VARS_FILE \
-var-file "$ENVIRONMENTS_DIR/$ENV_TF_VARS_FILE"
fi
# cleardown temp files
Expand All @@ -187,7 +187,7 @@ PROJECT_TF_VARS_FILE="project.tfvars"
ENV_TF_VARS_FILE="$ENVIRONMENT.tfvars"
ENVIRONMENTS_DIR="$ROOT_DIR/$INFRASTRUCTURE_DIR"

[ -d "$ROOT_DIR/$INFRASTRUCTURE_DIR/$ENVIRONMENTS_SUB_DIR" ] && ENVIRONMENTS_DIR="$ENVIRONMENTS_DIR/$ENVIRONMENTS_SUB_DIR"
[ -d "$ROOT_DIR/$INFRASTRUCTURE_DIR/$ENVIRONMENTS_SUB_DIR/$ENVIRONMENT" ] && ENVIRONMENTS_DIR="$ENVIRONMENTS_DIR/$ENVIRONMENTS_SUB_DIR/$ENVIRONMENT"
echo "Pulling environment variables from $ENVIRONMENTS_DIR"


Expand Down Expand Up @@ -228,23 +228,23 @@ terraform-initialise

if [ -n "$ACTION" ] && [ "$ACTION" = 'plan' ] ; then
terraform plan \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$COMMON_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$STACK_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$PROJECT_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$COMMON_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$STACK_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$PROJECT_TF_VARS_FILE \
-var-file "$ENVIRONMENTS_DIR/$ENV_TF_VARS_FILE"
fi
if [ -n "$ACTION" ] && [ "$ACTION" = 'apply' ] ; then
terraform apply -auto-approve \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$COMMON_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$STACK_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$PROJECT_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$COMMON_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$STACK_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$PROJECT_TF_VARS_FILE \
-var-file "$ENVIRONMENTS_DIR/$ENV_TF_VARS_FILE"
fi
if [ -n "$ACTION" ] && [ "$ACTION" = 'destroy' ] ; then
terraform destroy -auto-approve \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$COMMON_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$STACK_TF_VARS_FILE \
-var-file $ROOT_DIR/$INFRASTRUCTURE_DIR/$PROJECT_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$COMMON_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$STACK_TF_VARS_FILE \
-var-file "$ROOT_DIR"/"$INFRASTRUCTURE_DIR"/$PROJECT_TF_VARS_FILE \
-var-file "$ENVIRONMENTS_DIR/$ENV_TF_VARS_FILE"
fi
# cleardown temp files
Expand Down

0 comments on commit 2bad940

Please sign in to comment.