diff --git a/services/terraform/modules/shared/outputs.tf b/services/terraform/modules/shared/outputs.tf --- a/services/terraform/modules/shared/outputs.tf +++ b/services/terraform/modules/shared/outputs.tf @@ -4,6 +4,7 @@ aws_dynamodb_table.backup-service-backup, aws_dynamodb_table.reports-service-reports, aws_dynamodb_table.tunnelbroker-undelivered-messages, + aws_dynamodb_table.identity-users, ] } diff --git a/services/terraform/modules/shared/search_index_lambda.tf b/services/terraform/modules/shared/search_index_lambda.tf new file mode 100644 --- /dev/null +++ b/services/terraform/modules/shared/search_index_lambda.tf @@ -0,0 +1,36 @@ +variable iam_role_arn { + default = "arn:aws:iam::000000000000:role/lambda-role" +} + +variable lambda_zip_dir { + type = string + default = "../../search-index-lambda/target/lambda/search-index-lambda" +} + +resource "aws_lambda_function" "search_index_lambda" { + function_name = "search-index-lambda-function" + filename = "${var.lambda_zip_dir}/bootstrap.zip" + source_code_hash = filebase64sha256("${var.lambda_zip_dir}/bootstrap.zip") + handler = "bootstrap" + role = var.iam_role_arn + runtime = "provided.al2" + architectures = ["arm64"] + timeout = 300 + + environment { + variables = { + RUST_BACKTRACE = "1" + } + } + + tracing_config { + mode = "Active" + } +} + +resource "aws_lambda_event_source_mapping" "trigger" { + count = var.is_dev ? 0 : 1 + event_source_arn = aws_dynamodb_table.identity-users.stream_arn + function_name = aws_lambda_function.search_index_lambda.arn + starting_position = "LATEST" +} diff --git a/services/terraform/remote/aws_iam.tf b/services/terraform/remote/aws_iam.tf --- a/services/terraform/remote/aws_iam.tf +++ b/services/terraform/remote/aws_iam.tf @@ -201,16 +201,71 @@ effect = "Allow" principals { - type = "*" - identifiers = ["*"] + type = "Service" + identifiers = ["lambda.amazonaws.com"] } - actions = ["es:*"] - resources = ["${module.shared.opensearch_domain_identity.arn}/*"] + actions = ["sts:AssumeRole"] } } -resource "aws_opensearch_domain_policy" "identity-search" { - domain_name = module.shared.opensearch_domain_identity.domain_name - access_policies = data.aws_iam_policy_document.identity-search.json +resource "aws_iam_role" "search_index_lambda_role" { + name = "search_index_lambda_role" + assume_role_policy = data.aws_iam_policy_document.identity-search.json +} + +data "aws_iam_policy_document" "manage_dynamodb_stream" { + statement { + effect = "Allow" + + actions = [ + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:DescribeStream", + "dynamodb:ListStreams" + ] + resources = [ + module.shared.dynamodb_tables["identity-users"].arn, + module.shared.dynamodb_tables["identity-users"].stream_arn, + "${module.shared.dynamodb_tables["identity-users"].arn}/stream/*", + ] + } +} + +resource "aws_iam_policy" "manage_dynamodb_stream" { + name = "manage_dynamodb_stream" + path = "/" + description = "IAM policy for managing dynamodb streams" + policy = data.aws_iam_policy_document.manage_dynamodb_stream.json +} + +data "aws_iam_policy_document" "lambda_logging" { + statement { + effect = "Allow" + + actions = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ] + + resources = ["arn:aws:logs:*:*:*"] + } +} + +resource "aws_iam_policy" "lambda_logging" { + name = "lambda_logging" + path = "/" + description = "IAM policy for logging from a lambda" + policy = data.aws_iam_policy_document.lambda_logging.json +} + +resource "aws_iam_role_policy_attachment" "lambda_logs" { + role = "${aws_iam_role.search_index_lambda_role.name}" + policy_arn = aws_iam_policy.lambda_logging.arn +} + +resource "aws_iam_role_policy_attachment" "lambda_stream_attach" { + role = "${aws_iam_role.search_index_lambda_role.name}" + policy_arn = aws_iam_policy.manage_dynamodb_stream.arn } diff --git a/services/terraform/remote/aws_vpc.tf b/services/terraform/remote/aws_vpc.tf --- a/services/terraform/remote/aws_vpc.tf +++ b/services/terraform/remote/aws_vpc.tf @@ -42,6 +42,30 @@ map_public_ip_on_launch = true } +resource "aws_vpc_endpoint" "dynamodb_endpoint" { + vpc_id = aws_vpc.default.id + service_name = "com.amazonaws.us-east-2.dynamodb" + vpc_endpoint_type = "Gateway" + + policy = < The following subnets have not been explicitly associated # > with any route tables and are therefore associated with the main route table: