diff --git a/infra/deployments/deploy/engineer-access/roles.tf b/infra/deployments/deploy/engineer-access/roles.tf index de2cf8b01..dd720cd55 100644 --- a/infra/deployments/deploy/engineer-access/roles.tf +++ b/infra/deployments/deploy/engineer-access/roles.tf @@ -12,6 +12,7 @@ module "engineer_access" { codestar_connection_arn = var.codestar_connection_arn allow_ecs_task_usage = false allow_rds_data_api_access = false + state_file_bucket_name = "gds-forms-deploy-tfstate" # Pentesters may not have GDS domains so our pattern using the 'users' module # doesn't necessarily work. diff --git a/infra/deployments/forms/account/.terraform.lock.hcl b/infra/deployments/forms/account/.terraform.lock.hcl index 4c2d79956..1d874b395 100644 --- a/infra/deployments/forms/account/.terraform.lock.hcl +++ b/infra/deployments/forms/account/.terraform.lock.hcl @@ -77,3 +77,23 @@ provider "registry.terraform.io/hashicorp/aws" { "zh:e0c542950f96c93e761d50602e449fef8447f1389a6d5242a0a7dc9b06826d0b", ] } + +provider "registry.terraform.io/hashicorp/random" { + version = "3.7.2" + constraints = "~> 3.7.0" + hashes = [ + "h1:KG4NuIBl1mRWU0KD/BGfCi1YN/j3F7H4YgeeM7iSdNs=", + "zh:14829603a32e4bc4d05062f059e545a91e27ff033756b48afbae6b3c835f508f", + "zh:1527fb07d9fea400d70e9e6eb4a2b918d5060d604749b6f1c361518e7da546dc", + "zh:1e86bcd7ebec85ba336b423ba1db046aeaa3c0e5f921039b3f1a6fc2f978feab", + "zh:24536dec8bde66753f4b4030b8f3ef43c196d69cccbea1c382d01b222478c7a3", + "zh:29f1786486759fad9b0ce4fdfbbfece9343ad47cd50119045075e05afe49d212", + "zh:4d701e978c2dd8604ba1ce962b047607701e65c078cb22e97171513e9e57491f", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7b8434212eef0f8c83f5a90c6d76feaf850f6502b61b53c329e85b3b281cba34", + "zh:ac8a23c212258b7976e1621275e3af7099e7e4a3d4478cf8d5d2a27f3bc3e967", + "zh:b516ca74431f3df4c6cf90ddcdb4042c626e026317a33c53f0b445a3d93b720d", + "zh:dc76e4326aec2490c1600d6871a95e78f9050f9ce427c71707ea412a2f2f1a62", + "zh:eac7b63e86c749c7d48f527671c7aee5b4e26c10be6ad7232d6860167f99dbb0", + ] +} diff --git a/infra/deployments/forms/account/engineer-access.tf b/infra/deployments/forms/account/engineer-access.tf index d86c5cfdd..8a9c22153 100644 --- a/infra/deployments/forms/account/engineer-access.tf +++ b/infra/deployments/forms/account/engineer-access.tf @@ -15,4 +15,5 @@ module "engineer_access" { codestar_connection_arn = var.codestar_connection_arn allow_rds_data_api_access = true allow_ecs_task_usage = true + state_file_bucket_name = var.bucket } diff --git a/infra/deployments/integration/account/engineer-access.tf b/infra/deployments/integration/account/engineer-access.tf index abdc8c8a7..4bc5c0edf 100644 --- a/infra/deployments/integration/account/engineer-access.tf +++ b/infra/deployments/integration/account/engineer-access.tf @@ -33,6 +33,31 @@ resource "aws_iam_policy" "deny_parameter_store" { }) } +resource "aws_iam_policy" "lock_state_files" { + name = "release-lock-on-state-files" + path = "/" + + description = "Allow locking state files" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject" + ] + Effect = "Allow" + Resource = [ + "arn:aws:s3:::${var.bucket}/*.tflock" + ] + } + ] + }) +} + + module "admin_role" { for_each = toset(local.admin_users) @@ -51,6 +76,7 @@ module "support_role" { email = "${each.value}@digital.cabinet-office.gov.uk" role_suffix = "support" iam_policy_arns = [ + aws_iam_policy.lock_state_files.arn ] ip_restrictions = local.ip_restrictions } @@ -63,6 +89,7 @@ module "readonly_role" { role_suffix = "readonly" iam_policy_arns = [ "arn:aws:iam::aws:policy/ReadOnlyAccess", + aws_iam_policy.lock_state_files.arn ] ip_restrictions = local.ip_restrictions } diff --git a/infra/modules/engineer-access/policies.tf b/infra/modules/engineer-access/policies.tf index b5bfc0b1b..687ef2bbf 100644 --- a/infra/modules/engineer-access/policies.tf +++ b/infra/modules/engineer-access/policies.tf @@ -289,24 +289,26 @@ resource "aws_iam_policy" "deny_parameter_store" { }) } -resource "aws_iam_policy" "release_lock_on_state_files" { +resource "aws_iam_policy" "lock_state_files" { name = "release-lock-on-state-files" path = "/" - description = "Allow releasing the lock on state files" + description = "Allow locking state files" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ + "s3:GetObject", + "s3:PutObject", "s3:DeleteObject" ] Effect = "Allow" Resource = [ - "arn:aws:s3:::gds-forms-${var.environment_type}-tfstate/*.tflock" + "arn:aws:s3:::${var.state_file_bucket_name}/*.tflock" ] } ] }) -} \ No newline at end of file +} diff --git a/infra/modules/engineer-access/roles.tf b/infra/modules/engineer-access/roles.tf index ad15e8f1f..685955901 100644 --- a/infra/modules/engineer-access/roles.tf +++ b/infra/modules/engineer-access/roles.tf @@ -28,7 +28,7 @@ module "support_role" { aws_iam_policy.manage_dashboards.arn, aws_iam_policy.manage_deployments.arn, aws_iam_policy.manage_maintenance_page.arn, - aws_iam_policy.release_lock_on_state_files.arn, + aws_iam_policy.lock_state_files.arn, var.allow_rds_data_api_access ? [aws_iam_policy.query_rds_with_data_api[0].arn] : [], var.allow_ecs_task_usage ? [aws_iam_policy.run_task[0].arn, aws_iam_policy.stop_task[0].arn] : [] ]) @@ -43,6 +43,7 @@ module "readonly_role" { role_suffix = "readonly" iam_policy_arns = [ "arn:aws:iam::aws:policy/ReadOnlyAccess", + aws_iam_policy.lock_state_files.arn, ] ip_restrictions = local.vpn_ip_restrictions } diff --git a/infra/modules/engineer-access/variables.tf b/infra/modules/engineer-access/variables.tf index 050be4d93..a9fbfa843 100644 --- a/infra/modules/engineer-access/variables.tf +++ b/infra/modules/engineer-access/variables.tf @@ -57,4 +57,9 @@ variable "allow_rds_data_api_access" { variable "allow_ecs_task_usage" { type = bool description = "Whether appropriate engineer roles should be able to run tasks in AWS ECS" -} \ No newline at end of file +} + +variable "state_file_bucket_name" { + type = string + description = "The name of the S3 bucket in which Terraform state files are stored" +}