Skip to content

Commit 5e44d4e

Browse files
committed
rollback
1 parent 3e7c588 commit 5e44d4e

File tree

1 file changed

+272
-38
lines changed

1 file changed

+272
-38
lines changed

terraform/lambda.tf

Lines changed: 272 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
1+
# Define the directory containing the Docker image and calculate its SHA-256 hash for triggering redeployments
12
locals {
2-
lambda_dir = abspath("${path.root}/../backend")
3-
source_path = local.lambda_dir
4-
path_include = ["**"]
5-
path_exclude = ["**/__pycache__/**"]
6-
files_include = setunion([for f in local.path_include : fileset(local.source_path, f)]...)
7-
files_exclude = setunion([for f in local.path_exclude : fileset(local.source_path, f)]...)
8-
files = sort(setsubtract(local.files_include, local.files_exclude))
9-
10-
dir_sha = sha1(join("", [for f in local.files : filesha1("${local.source_path}/${f}")]))
3+
shared_dir = abspath("${path.root}/../shared")
4+
id_sync_lambda_dir = abspath("${path.root}/../id_sync")
5+
6+
# Get files from both directories
7+
shared_files = fileset(local.shared_dir, "**")
8+
id_sync_lambda_files = fileset(local.id_sync_lambda_dir, "**")
9+
10+
# Calculate SHA for both directories
11+
shared_dir_sha = sha1(join("", [for f in local.shared_files : filesha1("${local.shared_dir}/${f}")]))
12+
id_sync_lambda_dir_sha = sha1(join("", [for f in local.id_sync_lambda_files : filesha1("${local.id_sync_lambda_dir}/${f}")]))
13+
1114
}
1215

13-
resource "aws_ecr_repository" "operation_lambda_repository" {
16+
resource "aws_ecr_repository" "id_sync_lambda_repository" {
1417
image_scanning_configuration {
1518
scan_on_push = true
1619
}
17-
name = "${local.prefix}-operation-lambda-repo"
20+
name = "${local.short_prefix}-id-sync-repo"
1821
force_delete = local.is_temp
1922
}
2023

21-
#resource "docker_image" "lambda_function_docker" {
22-
module "docker_image" {
23-
source = "terraform-aws-modules/lambda/aws//modules/docker-build"
24-
version = "8.0.1"
25-
24+
# Module for building and pushing Docker image to ECR
25+
module "id_sync_docker_image" {
26+
source = "terraform-aws-modules/lambda/aws//modules/docker-build"
27+
version = "8.0.1"
28+
docker_file_path = "./id_sync/Dockerfile"
2629
create_ecr_repo = false
27-
ecr_repo = "${local.prefix}-operation-lambda-repo"
28-
docker_file_path = "lambda.Dockerfile"
30+
ecr_repo = aws_ecr_repository.id_sync_lambda_repository.name
2931
ecr_repo_lifecycle_policy = jsonencode({
3032
"rules" : [
3133
{
@@ -45,46 +47,278 @@ module "docker_image" {
4547

4648
platform = "linux/amd64"
4749
use_image_tag = false
48-
source_path = local.lambda_dir
50+
source_path = abspath("${path.root}/..")
4951
triggers = {
50-
dir_sha = local.dir_sha
52+
dir_sha = local.id_sync_lambda_dir_sha
5153
}
5254
}
5355

5456
# Define the lambdaECRImageRetreival policy
55-
resource "aws_ecr_repository_policy" "operation_lambda_ECRImageRetreival_policy" {
56-
repository = aws_ecr_repository.operation_lambda_repository.name
57+
resource "aws_ecr_repository_policy" "id_sync_lambda_ECRImageRetreival_policy" {
58+
repository = aws_ecr_repository.id_sync_lambda_repository.name
5759

5860
policy = jsonencode({
5961
Version = "2012-10-17"
6062
Statement = [
6163
{
62-
"Sid" : "LambdaECRImageRetrievalPolicy",
63-
"Effect" : "Allow",
64-
"Principal" : {
65-
"Service" : "lambda.amazonaws.com"
64+
Sid : "LambdaECRImageRetrievalPolicy",
65+
Effect : "Allow",
66+
Principal : {
67+
Service : "lambda.amazonaws.com"
6668
},
67-
"Action" : [
69+
Action : [
6870
"ecr:BatchGetImage",
6971
"ecr:DeleteRepositoryPolicy",
7072
"ecr:GetDownloadUrlForLayer",
7173
"ecr:GetRepositoryPolicy",
7274
"ecr:SetRepositoryPolicy"
7375
],
74-
"Condition" : {
75-
"StringLike" : {
76-
"aws:sourceArn" : [
77-
"arn:aws:lambda:eu-west-2:${var.immunisation_account_id}:function:${local.short_prefix}_get_status",
78-
"arn:aws:lambda:eu-west-2:${var.immunisation_account_id}:function:${local.short_prefix}_not_found",
79-
"arn:aws:lambda:eu-west-2:${var.immunisation_account_id}:function:${local.short_prefix}_search_imms",
80-
"arn:aws:lambda:eu-west-2:${var.immunisation_account_id}:function:${local.short_prefix}_get_imms",
81-
"arn:aws:lambda:eu-west-2:${var.immunisation_account_id}:function:${local.short_prefix}_delete_imms",
82-
"arn:aws:lambda:eu-west-2:${var.immunisation_account_id}:function:${local.short_prefix}_create_imms",
83-
"arn:aws:lambda:eu-west-2:${var.immunisation_account_id}:function:${local.short_prefix}_update_imms"
84-
]
76+
Condition : {
77+
StringLike : {
78+
"aws:sourceArn" : aws_lambda_function.id_sync_lambda.arn
8579
}
8680
}
8781
}
8882
]
8983
})
9084
}
85+
86+
# IAM Role for Lambda
87+
resource "aws_iam_role" "id_sync_lambda_exec_role" {
88+
name = "${local.short_prefix}-id-sync-lambda-exec-role"
89+
assume_role_policy = jsonencode({
90+
Version = "2012-10-17",
91+
Statement = [{
92+
Effect = "Allow",
93+
Sid = "",
94+
Principal = {
95+
Service = "lambda.amazonaws.com"
96+
},
97+
Action = "sts:AssumeRole"
98+
}]
99+
})
100+
}
101+
102+
# Policy for Lambda execution role
103+
resource "aws_iam_policy" "id_sync_lambda_exec_policy" {
104+
name = "${local.short_prefix}-id-sync-lambda-exec-policy"
105+
policy = jsonencode({
106+
Version = "2012-10-17",
107+
Statement = [
108+
{
109+
Effect = "Allow"
110+
Action = [
111+
"logs:CreateLogGroup",
112+
"logs:CreateLogStream",
113+
"logs:PutLogEvents"
114+
]
115+
Resource = "arn:aws:logs:${var.aws_region}:${var.immunisation_account_id}:log-group:/aws/lambda/${local.short_prefix}-id_sync_lambda:*"
116+
},
117+
{
118+
Effect = "Allow"
119+
Action = [
120+
"s3:GetObject",
121+
"s3:ListBucket",
122+
"s3:PutObject",
123+
"s3:CopyObject",
124+
"s3:DeleteObject"
125+
]
126+
Resource = [
127+
aws_s3_bucket.batch_data_source_bucket.arn,
128+
"${aws_s3_bucket.batch_data_source_bucket.arn}/*"
129+
]
130+
},
131+
{
132+
Effect = "Allow"
133+
Action = [
134+
"s3:GetObject",
135+
"s3:PutObject",
136+
"s3:ListBucket"
137+
]
138+
Resource = [
139+
aws_s3_bucket.batch_data_destination_bucket.arn,
140+
"${aws_s3_bucket.batch_data_destination_bucket.arn}/*"
141+
]
142+
},
143+
{
144+
Effect = "Allow",
145+
Action = [
146+
"ec2:CreateNetworkInterface",
147+
"ec2:DescribeNetworkInterfaces",
148+
"ec2:DeleteNetworkInterface"
149+
],
150+
Resource = "*"
151+
},
152+
{
153+
Effect = "Allow"
154+
Action = [
155+
"s3:GetObject",
156+
"s3:PutObject",
157+
"s3:ListBucket"
158+
]
159+
Resource = [
160+
local.config_bucket_arn,
161+
"${local.config_bucket_arn}/*"
162+
]
163+
},
164+
{
165+
Effect = "Allow",
166+
Action = [
167+
"firehose:PutRecord",
168+
"firehose:PutRecordBatch"
169+
],
170+
Resource = "arn:aws:firehose:*:*:deliverystream/${module.splunk.firehose_stream_name}"
171+
},
172+
{
173+
Effect = "Allow"
174+
Action = "lambda:InvokeFunction"
175+
Resource = [
176+
"arn:aws:lambda:${var.aws_region}:${var.immunisation_account_id}:function:imms-${var.sub_environment}-id_sync_lambda",
177+
]
178+
},
179+
# NEW
180+
# NB anomaly: do we want this in "id_sync_lambda_sqs_access_policy"?
181+
{
182+
Effect = "Allow",
183+
Action = [
184+
"sqs:ReceiveMessage",
185+
"sqs:DeleteMessage",
186+
"sqs:GetQueueAttributes"
187+
],
188+
Resource = "arn:aws:sqs:eu-west-2:${var.immunisation_account_id}:${local.short_prefix}-id-sync-queue"
189+
},
190+
# NB anomaly: in redis_sync this appears in "redis_sync_lambda_kms_access_policy"
191+
{
192+
Effect = "Allow",
193+
Action = [
194+
"kms:Decrypt",
195+
"kms:GenerateDataKey"
196+
],
197+
Resource = data.aws_kms_key.existing_id_sync_sqs_encryption_key.arn
198+
}
199+
]
200+
})
201+
}
202+
203+
resource "aws_iam_policy" "id_sync_lambda_kms_access_policy" {
204+
name = "${local.short_prefix}-id-sync-lambda-kms-policy"
205+
description = "Allow Lambda to decrypt environment variables"
206+
207+
policy = jsonencode({
208+
Version = "2012-10-17"
209+
Statement = [
210+
{
211+
Effect = "Allow"
212+
Action = [
213+
"kms:Decrypt"
214+
]
215+
Resource = data.aws_kms_key.existing_lambda_encryption_key.arn
216+
},
217+
{
218+
Effect = "Allow"
219+
Action = [
220+
"kms:Encrypt",
221+
"kms:Decrypt",
222+
"kms:GenerateDataKey*"
223+
]
224+
Resource = [
225+
data.aws_kms_key.existing_s3_encryption_key.arn,
226+
]
227+
}
228+
]
229+
})
230+
}
231+
232+
# Attach the execution policy to the Lambda role
233+
resource "aws_iam_role_policy_attachment" "id_sync_lambda_exec_policy_attachment" {
234+
role = aws_iam_role.id_sync_lambda_exec_role.name
235+
policy_arn = aws_iam_policy.id_sync_lambda_exec_policy.arn
236+
}
237+
238+
# Attach the kms policy to the Lambda role
239+
resource "aws_iam_role_policy_attachment" "id_sync_lambda_kms_policy_attachment" {
240+
role = aws_iam_role.id_sync_lambda_exec_role.name
241+
policy_arn = aws_iam_policy.id_sync_lambda_kms_access_policy.arn
242+
}
243+
244+
data "aws_iam_policy_document" "id_sync_policy_document" {
245+
source_policy_documents = [
246+
templatefile("${local.policy_path}/dynamodb.json", {
247+
"dynamodb_table_name" : aws_dynamodb_table.delta-dynamodb-table.name
248+
}),
249+
templatefile("${local.policy_path}/dynamodb_stream.json", {
250+
"dynamodb_table_name" : aws_dynamodb_table.events-dynamodb-table.name
251+
}),
252+
templatefile("${local.policy_path}/secret_manager.json", {
253+
"account_id" : data.aws_caller_identity.current.account_id,
254+
"pds_environment" : var.pds_environment
255+
})
256+
]
257+
}
258+
259+
resource "aws_iam_policy" "id_sync_lambda_dynamodb_access_policy" {
260+
name = "${local.short_prefix}-id-sync-lambda-dynamodb-access-policy"
261+
description = "Allow Lambda to access DynamoDB"
262+
policy = data.aws_iam_policy_document.id_sync_policy_document.json
263+
}
264+
265+
# Attach the dynamodb policy to the Lambda role
266+
resource "aws_iam_role_policy_attachment" "id_sync_lambda_dynamodb_policy_attachment" {
267+
role = aws_iam_role.id_sync_lambda_exec_role.name
268+
policy_arn = aws_iam_policy.id_sync_lambda_dynamodb_access_policy.arn
269+
}
270+
271+
# Lambda Function with Security Group and VPC.
272+
resource "aws_lambda_function" "id_sync_lambda" {
273+
function_name = "${local.short_prefix}-id_sync_lambda"
274+
role = aws_iam_role.id_sync_lambda_exec_role.arn
275+
package_type = "Image"
276+
image_uri = module.id_sync_docker_image.image_uri
277+
architectures = ["x86_64"]
278+
timeout = 360
279+
280+
vpc_config {
281+
subnet_ids = local.private_subnet_ids
282+
security_group_ids = [data.aws_security_group.existing_securitygroup.id]
283+
}
284+
285+
environment {
286+
variables = {
287+
CONFIG_BUCKET_NAME = local.config_bucket_name
288+
REDIS_HOST = data.aws_elasticache_cluster.existing_redis.cache_nodes[0].address
289+
REDIS_PORT = data.aws_elasticache_cluster.existing_redis.cache_nodes[0].port
290+
ID_SYNC_PROC_LAMBDA_NAME = "imms-${var.sub_environment}-id_sync_lambda"
291+
# NEW
292+
DELTA_TABLE_NAME = aws_dynamodb_table.delta-dynamodb-table.name
293+
IEDS_TABLE_NAME = aws_dynamodb_table.events-dynamodb-table.name
294+
PDS_ENV = var.pds_environment
295+
SPLUNK_FIREHOSE_NAME = module.splunk.firehose_stream_name
296+
}
297+
}
298+
kms_key_arn = data.aws_kms_key.existing_lambda_encryption_key.arn
299+
300+
depends_on = [
301+
aws_cloudwatch_log_group.id_sync_log_group,
302+
aws_iam_policy.id_sync_lambda_exec_policy
303+
]
304+
}
305+
306+
resource "aws_cloudwatch_log_group" "id_sync_log_group" {
307+
name = "/aws/lambda/${local.short_prefix}-id_sync_lambda"
308+
retention_in_days = 30
309+
}
310+
311+
# delete config_lambda_notification / new_s3_invoke_permission - not required; duplicate
312+
313+
# NEW
314+
resource "aws_lambda_event_source_mapping" "id_sync_sqs_trigger" {
315+
event_source_arn = "arn:aws:sqs:eu-west-2:${var.immunisation_account_id}:${local.short_prefix}-id-sync-queue"
316+
function_name = aws_lambda_function.id_sync_lambda.arn # TODO
317+
318+
# Optional: Configure batch size and other settings
319+
batch_size = 10
320+
maximum_batching_window_in_seconds = 5
321+
322+
# Optional: Configure error handling
323+
function_response_types = ["ReportBatchItemFailures"]
324+
}

0 commit comments

Comments
 (0)