Skip to content

Commit e4c0cfc

Browse files
committed
fix tf format
2 parents 66ddac9 + d05675b commit e4c0cfc

File tree

17 files changed

+231
-129
lines changed

17 files changed

+231
-129
lines changed

.release-manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "5.11.0"
2+
".": "5.12.1"
33
}

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## [5.12.1](https://github.com/uktrade/terraform-platform-modules/compare/5.12.0...5.12.1) (2024-12-04)
4+
5+
6+
### Bug Fixes
7+
8+
* Environment pipeline permissions ([#299](https://github.com/uktrade/terraform-platform-modules/issues/299)) ([7eb1a63](https://github.com/uktrade/terraform-platform-modules/commit/7eb1a63c5ffde9767ed9a71fd9739378fd56976d))
9+
10+
## [5.12.0](https://github.com/uktrade/terraform-platform-modules/compare/5.11.0...5.12.0) (2024-12-03)
11+
12+
13+
### Features
14+
15+
* DBTP-1299 - Cross account database copy ([#294](https://github.com/uktrade/terraform-platform-modules/issues/294)) ([ac84ca8](https://github.com/uktrade/terraform-platform-modules/commit/ac84ca8690ab530e74efadabf179fa8b38059c70))
16+
317
## [5.11.0](https://github.com/uktrade/terraform-platform-modules/compare/5.10.0...5.11.0) (2024-11-29)
418

519

application-load-balancer/lambda_function/rotate_secret_lambda.py

-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# import os
2-
# import json
31
import boto3
42
import logging
53

@@ -10,9 +8,6 @@
108

119
service_client = boto3.client('secretsmanager')
1210

13-
AWSPENDING = "AWSPENDING"
14-
AWSCURRENT = "AWSCURRENT"
15-
1611

1712
def lambda_handler(event, context):
1813
secret_id = event.get('SecretId')

application-load-balancer/lambda_function/secret_rotator.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import logging
55
import requests
66
import time
7-
#import uuid
87
from typing import Tuple, Dict, Any, List, Optional
98
from slack_service import SlackNotificationService
109
from requests.exceptions import RequestException
@@ -246,6 +245,9 @@ def process_cf_distributions_and_WAF_rules(self, matching_distributions, pending
246245
"""
247246
Process CloudFront distributions based on whether the custom header is already present.
248247
If the custom header is missing, it will be added to the distribution.
248+
Updates the WAF ACL & the CloudFront distributions with the AWSPENDING & AWSCURRENT secret values.
249+
This method should set the AWSPENDING secret in the service that the secret belongs to.
250+
Sleep 75 seconds to allow resources to update
249251
"""
250252
all_have_header = True # Assume all distributions have the header initially
251253

application-load-balancer/secret_manager.tf

+6-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ data "aws_iam_policy_document" "secret_manager_policy" {
1313
effect = "Allow"
1414

1515
principals {
16-
type = "AWS"
17-
identifiers = ["arn:aws:iam::${var.dns_account_id}:role/environment-pipeline-assumed-role"]
16+
type = "AWS"
17+
identifiers = [
18+
"arn:aws:iam::${var.dns_account_id}:role/environment-pipeline-assumed-role"
19+
]
1820
}
1921

20-
actions = ["secretsmanager:GetSecretValue",
22+
actions = [
23+
"secretsmanager:GetSecretValue",
2124
"secretsmanager:DescribeSecret"]
2225
resources = [aws_secretsmanager_secret.origin-verify-secret.arn]
2326
}

cdn/main.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ resource "aws_cloudfront_distribution" "standard" {
164164
}
165165

166166
lifecycle {
167-
# Use `ignore_changes` to allow rotation without Terraform overwriting the value
167+
# Use `ignore_changes` to allow custom_header secret rotation without Terraform overwriting the value
168168
ignore_changes = [origin]
169169
}
170170

environment-pipelines/iam.tf

+12-3
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ data "aws_iam_policy_document" "kms_key" {
503503
"kms:DeleteAlias"
504504
]
505505
resources = [
506-
"arn:aws:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:alias/${var.application}-${statement.value.name}-*-key"
506+
"arn:aws:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:alias/${var.application}-${statement.value.name}-*",
507507
]
508508
}
509509
}
@@ -746,16 +746,25 @@ data "aws_iam_policy_document" "ecs" {
746746
}
747747

748748
statement {
749-
sid = "AllowRegisterAndDeregister"
749+
sid = "AllowRegister"
750750
actions = [
751-
"ecs:DeregisterTaskDefinition",
752751
"ecs:RegisterTaskDefinition",
753752
]
754753
resources = [
755754
"arn:aws:ecs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:task-definition/*",
756755
"arn:aws:ecs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:task-definition/"
757756
]
758757
}
758+
759+
statement {
760+
sid = "AllowDeregister"
761+
actions = [
762+
"ecs:DeregisterTaskDefinition"
763+
]
764+
resources = [
765+
"*"
766+
]
767+
}
759768
}
760769

761770
resource "aws_iam_policy" "ecs" {

postgres/database-copy.tf

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
module "database-dump" {
2-
count = length(local.data_dump_tasks)
2+
count = length(local.data_dump_tasks) > 0 ? 1 : 0
33
source = "./database-dump"
44

55
application = var.application
66
environment = var.environment
77
database_name = var.name
8+
tasks = local.data_dump_tasks
89
}
910

1011

@@ -16,4 +17,4 @@ module "database-load" {
1617
environment = var.environment
1718
database_name = var.name
1819
task = local.data_load_tasks[count.index]
19-
}
20+
}

postgres/database-dump/locals.tf

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,4 @@ locals {
1212
dump_bucket_name = local.task_name
1313

1414
ecr_repository_arn = "arn:aws:ecr-public::763451185160:repository/database-copy"
15-
16-
}
15+
}

postgres/database-dump/main.tf

+28-8
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ resource "aws_iam_role_policy" "allow_task_creation" {
5656
policy = data.aws_iam_policy_document.allow_task_creation.json
5757
}
5858

59-
6059
data "aws_iam_policy_document" "data_dump" {
6160
policy_id = "data_dump"
6261
statement {
@@ -163,7 +162,6 @@ resource "aws_ecs_task_definition" "service" {
163162
}
164163
}
165164

166-
167165
resource "aws_s3_bucket" "data_dump_bucket" {
168166
# checkov:skip=CKV_AWS_144: Cross Region Replication not Required
169167
# checkov:skip=CKV2_AWS_62: Requires wider discussion around log/event ingestion before implementing. To be picked up on conclusion of DBTP-974
@@ -182,22 +180,40 @@ data "aws_iam_policy_document" "data_dump_bucket_policy" {
182180
type = "*"
183181
identifiers = ["*"]
184182
}
185-
186183
actions = [
187184
"s3:*",
188185
]
189-
190186
effect = "Deny"
191-
192187
condition {
193188
test = "Bool"
194189
variable = "aws:SecureTransport"
195-
196190
values = [
197191
"false",
198192
]
199193
}
194+
resources = [
195+
aws_s3_bucket.data_dump_bucket.arn,
196+
"${aws_s3_bucket.data_dump_bucket.arn}/*",
197+
]
198+
}
200199

200+
statement {
201+
effect = "Allow"
202+
principals {
203+
type = "AWS"
204+
identifiers = [
205+
for el in var.tasks :
206+
"arn:aws:iam::${coalesce(el.to_account, data.aws_caller_identity.current.account_id)}:role/${var.application}-${el.to}-${var.database_name}-load-task"
207+
]
208+
}
209+
actions = [
210+
"s3:ListBucket",
211+
"s3:GetObject",
212+
"s3:GetObjectTagging",
213+
"s3:GetObjectVersion",
214+
"s3:GetObjectVersionTagging",
215+
"s3:DeleteObject"
216+
]
201217
resources = [
202218
aws_s3_bucket.data_dump_bucket.arn,
203219
"${aws_s3_bucket.data_dump_bucket.arn}/*",
@@ -216,13 +232,17 @@ resource "aws_kms_key" "data_dump_kms_key" {
216232
tags = local.tags
217233

218234
policy = jsonencode({
219-
Id = "key-default-1"
220235
Statement = [
221236
{
222237
"Sid" : "Enable IAM User Permissions",
223238
"Effect" : "Allow",
224239
"Principal" : {
225-
"AWS" : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
240+
"AWS" : flatten([
241+
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:root",
242+
[for el in var.tasks :
243+
"arn:aws:iam::${coalesce(el.to_account, data.aws_caller_identity.current.account_id)}:role/${var.application}-${el.to}-${var.database_name}-load-task"
244+
]
245+
])
226246
},
227247
"Action" : "kms:*",
228248
"Resource" : "*"

postgres/database-dump/tests/unit.tftest.hcl

+81-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ variables {
22
application = "test-app"
33
environment = "test-env"
44
database_name = "test-db"
5+
tasks = [
6+
{
7+
from : "prod"
8+
to : "dev"
9+
}
10+
]
511
}
612

713
mock_provider "aws" {}
@@ -68,8 +74,12 @@ run "data_dump_unit_test" {
6874
for el in data.aws_iam_policy_document.assume_ecs_task_role.statement[0].principals :
6975
true if el.type == "Service" && [
7076
for identifier in el.identifiers : true if identifier == "ecs-tasks.amazonaws.com"
71-
][0] == true
72-
][0] == true
77+
][
78+
0
79+
] == true
80+
][
81+
0
82+
] == true
7383
error_message = "Principal identifier should be: 'ecs-tasks.amazonaws.com'"
7484
}
7585

@@ -142,7 +152,7 @@ run "data_dump_unit_test" {
142152

143153
assert {
144154
condition = contains(data.aws_iam_policy_document.data_dump.statement[1].actions, "kms:Decrypt")
145-
error_message = "Permission not found: kms:Encrypt"
155+
error_message = "Permission not found: kms:Decrypt"
146156
}
147157

148158
assert {
@@ -262,13 +272,37 @@ run "data_dump_unit_test" {
262272
}
263273

264274
assert {
265-
condition = [for el in data.aws_iam_policy_document.data_dump_bucket_policy.statement[0].condition : true if(el.variable == "aws:SecureTransport" && contains(el.values, "false"))] == [true]
275+
condition = [
276+
for el in data.aws_iam_policy_document.data_dump_bucket_policy.statement[0].condition : true
277+
if(el.variable == "aws:SecureTransport" && contains(el.values, "false"))
278+
] == [true]
266279
error_message = "Should be denied if not aws:SecureTransport"
267280
}
268281

269-
# aws_s3_bucket_policy.data_dump_bucket_policy.policy cannot be tested with plan
282+
assert {
283+
condition = [for el in data.aws_iam_policy_document.data_dump_bucket_policy.statement[1].principals : el.type][0] == "AWS"
284+
error_message = "Should be: AWS"
285+
}
286+
287+
assert {
288+
condition = flatten([for el in data.aws_iam_policy_document.data_dump_bucket_policy.statement[1].principals : el.identifiers]) == ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/test-app-dev-test-db-load-task"]
289+
error_message = "Bucket policy principals incorrect"
290+
}
291+
292+
assert {
293+
condition = data.aws_iam_policy_document.data_dump_bucket_policy.statement[1].actions == toset(["s3:ListBucket",
294+
"s3:GetObject",
295+
"s3:GetObjectTagging",
296+
"s3:GetObjectVersion",
297+
"s3:GetObjectVersionTagging",
298+
"s3:DeleteObject"])
299+
error_message = "Unexpected actions"
300+
}
270301

271-
# aws_kms_key.data_dump_kms_key policy cannot be tested with plan
302+
assert {
303+
condition = strcontains(aws_kms_key.data_dump_kms_key.policy, "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root") && !strcontains(aws_kms_key.data_dump_kms_key.policy, "arn:aws:iam::000123456789:role/test-app-dev-test-db-load-task")
304+
error_message = "Unexpected KMS key policy principal"
305+
}
272306

273307
assert {
274308
condition = aws_kms_alias.data_dump_kms_alias.name == "alias/test-app-test-env-test-db-dump"
@@ -281,7 +315,10 @@ run "data_dump_unit_test" {
281315
}
282316

283317
assert {
284-
condition = [for el in aws_s3_bucket_server_side_encryption_configuration.encryption-config.rule : el.apply_server_side_encryption_by_default[0].sse_algorithm] == ["aws:kms"]
318+
condition = [
319+
for el in aws_s3_bucket_server_side_encryption_configuration.encryption-config.rule :
320+
el.apply_server_side_encryption_by_default[0].sse_algorithm
321+
] == ["aws:kms"]
285322
error_message = "Server side encryption algorithm should be: aws:kms"
286323
}
287324

@@ -295,3 +332,40 @@ run "data_dump_unit_test" {
295332
error_message = "Public access block has expected conditions"
296333
}
297334
}
335+
336+
run "cross_account_data_dump_unit_test" {
337+
command = plan
338+
339+
variables {
340+
tasks = [
341+
{
342+
from : "prod"
343+
from_account : "123456789000"
344+
to : "dev"
345+
to_account : "000123456789"
346+
}
347+
]
348+
}
349+
350+
assert {
351+
condition = [for el in data.aws_iam_policy_document.data_dump_bucket_policy.statement[1].principals : el.type][0] == "AWS"
352+
error_message = "Should be: AWS"
353+
}
354+
assert {
355+
condition = flatten([for el in data.aws_iam_policy_document.data_dump_bucket_policy.statement[1].principals : el.identifiers]) == ["arn:aws:iam::000123456789:role/test-app-dev-test-db-load-task"]
356+
error_message = "Bucket policy principals incorrect"
357+
}
358+
assert {
359+
condition = data.aws_iam_policy_document.data_dump_bucket_policy.statement[1].actions == toset(["s3:ListBucket",
360+
"s3:GetObject",
361+
"s3:GetObjectTagging",
362+
"s3:GetObjectVersion",
363+
"s3:GetObjectVersionTagging",
364+
"s3:DeleteObject"])
365+
error_message = "Unexpected actions"
366+
}
367+
assert {
368+
condition = strcontains(aws_kms_key.data_dump_kms_key.policy, "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root") && strcontains(aws_kms_key.data_dump_kms_key.policy, "arn:aws:iam::000123456789:role/test-app-dev-test-db-load-task")
369+
error_message = "Unexpected KMS key policy principal"
370+
}
371+
}

postgres/database-dump/variables.tf

+9
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,12 @@ variable "environment" {
99
variable "database_name" {
1010
type = string
1111
}
12+
13+
variable "tasks" {
14+
type = list(object({
15+
from = string
16+
to = string
17+
from_account = optional(string)
18+
to_account = optional(string)
19+
}))
20+
}

postgres/database-load/locals.tf

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ locals {
99

1010
task_name = "${var.application}-${var.environment}-${var.database_name}-load"
1111

12-
dump_task_name = "${var.application}-${var.task.from}-${var.database_name}-dump"
12+
dump_task_name = "${var.application}-${var.task.from}-${var.database_name}-dump"
13+
# tflint-ignore: terraform_unused_declarations
1314
dump_kms_key_alias = "alias/${local.dump_task_name}"
1415
dump_bucket_name = local.dump_task_name
1516

1617
ecr_repository_arn = "arn:aws:ecr-public::763451185160:repository/database-copy"
17-
1818
}

0 commit comments

Comments
 (0)