Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UML-3738: eventbridge & lambda permissions #3014

Merged
merged 37 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6241ea7
change file name
jay-whitwell Dec 18, 2024
4f1b147
add sqs and variables
jay-whitwell Dec 18, 2024
09e4c27
update variable names
jay-whitwell Dec 18, 2024
c7ed1f7
instance key and && operator
jay-whitwell Dec 18, 2024
fe64258
add event target bus name
jay-whitwell Dec 18, 2024
f751c42
allow lambda messages from sqs
jay-whitwell Dec 18, 2024
28c9aa9
add vars and outputs
jay-whitwell Dec 18, 2024
8d51e77
use arn instead of id
jay-whitwell Dec 19, 2024
96267a6
just use name
jay-whitwell Dec 19, 2024
afdcd8f
propagate outputs
jay-whitwell Dec 19, 2024
3f94b96
rewmove lambda var
jay-whitwell Dec 19, 2024
f1ecb94
add lambda permission and change to arn
jay-whitwell Dec 19, 2024
92e9da9
ensure queue visibility timeout aligns
jay-whitwell Dec 19, 2024
f20e259
correct ecr
jay-whitwell Dec 20, 2024
3ee5bf8
stop pipeline pass on failed preprod plan
jay-whitwell Dec 20, 2024
cb4f4a1
update lambda to allow execute from sqs
jay-whitwell Dec 20, 2024
38429e7
explicitly declare resource
jay-whitwell Dec 20, 2024
9a707d2
add sqs queue policy resource
jay-whitwell Dec 20, 2024
bbe42cc
allow lambda decrypt permissions
jay-whitwell Dec 20, 2024
34029af
remove condition
jay-whitwell Jan 7, 2025
22c424a
rename kms
jay-whitwell Jan 7, 2025
47a288e
allow permissions on kms key
jay-whitwell Jan 7, 2025
99830a9
temporarily comment kms
jay-whitwell Jan 8, 2025
16726ce
enable kms cmk
jay-whitwell Jan 8, 2025
6f96365
Merge branch 'main' into UML-3738
jay-whitwell Jan 8, 2025
1fcee82
update kms vars
jay-whitwell Jan 8, 2025
3b0193b
remove duplicated key
jay-whitwell Jan 8, 2025
fef52f0
add cmk
jay-whitwell Jan 8, 2025
275bd20
conditionally create resources in upper environments
jay-whitwell Jan 8, 2025
c67b8d6
conditionally create resources
jay-whitwell Jan 8, 2025
51b9234
remove old kms
jay-whitwell Jan 8, 2025
6db8e0a
use correct kms key
jay-whitwell Jan 9, 2025
d44a3b6
allow describe key on lambda role
jay-whitwell Jan 9, 2025
2320b4d
allow decrypt on *
jay-whitwell Jan 10, 2025
dfca208
try specific target key arn
jay-whitwell Jan 10, 2025
56be0c4
Merge branch 'main' into UML-3738
jay-whitwell Jan 10, 2025
9b05d9f
update account ids
jay-whitwell Jan 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/pull-request-path.yml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ jobs:
- update_documentation
- docker_build_scan_push
- run_behat_suite
- terraform_preproduction_plan_environment
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -332,7 +333,7 @@ jobs:

- name: workflow has ended without issue
run: |
if ${{ contains(needs.run_behat_suite.result, 'success') && contains(needs.ecr_scan_results.result, 'success') }}; then
if ${{ contains(needs.run_behat_suite.result, 'success') && contains(needs.ecr_scan_results.result, 'success') && contains(needs.terraform_preproduction_plan_environment.result, 'success') }}; then
echo "${{ needs.workflow_variables.outputs.safe_branch_name }} PR environment tested, built and deployed"
echo "Tag Used: ${{ needs.workflow_variables.outputs.safe_branch_name }}-${{ needs.workflow_variables.outputs.short_sha }}"
echo "URL: https://${{ needs.workflow_variables.outputs.workspace_name }}.use-lasting-power-of-attorney.service.gov.uk"
Expand Down
23 changes: 18 additions & 5 deletions lambda-functions/event-receiver/app/main.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
package main

import (
"context"
"fmt"

"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)

func Handler(ctx context.Context) (string, error) {
fmt.Println("Hello World")
return "Hello World!", nil
func handler(event events.SQSEvent) error {
for _, record := range event.Records {
err := processMessage(record)
if err != nil {
return err
}
}
fmt.Println("done")
return nil
}

func processMessage(record events.SQSMessage) error {
fmt.Printf("Processed message %s\n", record.Body)
fmt.Printf("Hello, world!\n")
return nil
}

func main() {
lambda.Start(Handler)
lambda.Start(handler)
fmt.Printf("Hello, world!\n")
}
35 changes: 4 additions & 31 deletions terraform/account/kms.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ module "sessions_actor_mrk" {
}
}

module "sqs_mrk" {
module "event_receiver_mrk" {
source = "./modules/multi_region_kms"

key_description = "KMS key for sqs"
key_alias = "sqs-mrk"
key_description = "KMS key for received events"
key_alias = "${local.environment}-event-receiver-mrk"
key_policy = data.aws_iam_policy_document.event_receiver_kms.json
deletion_window_in_days = 7

providers = {
Expand Down Expand Up @@ -147,20 +148,6 @@ data "aws_iam_policy_document" "cloudwatch_kms" {
}
}

module "event_receiver_mrk" {
source = "./modules/multi_region_kms"

key_description = "KMS key for received events"
key_alias = "event-receiver-mrk"
key_policy = data.aws_iam_policy_document.event_receiver_kms.json
deletion_window_in_days = 7

providers = {
aws.primary = aws.eu_west_1
aws.secondary = aws.eu_west_2
}
}

data "aws_iam_policy_document" "event_receiver_kms" {
statement {
sid = "Allow Encryption by Service"
Expand Down Expand Up @@ -199,18 +186,4 @@ data "aws_iam_policy_document" "event_receiver_kms" {
]
}
}

statement {
sid = "Enable Root account permissions on Key"
effect = "Allow"
actions = ["kms:*"]
resources = ["*"]

principals {
type = "AWS"
identifiers = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:root",
]
}
}
}
52 changes: 51 additions & 1 deletion terraform/environment/lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module "lambda_update_statistics" {
memory = 1024
}


# Additional IAM permissions
resource "aws_iam_role_policy" "lambda_update_statistics" {
name = "lambda-update-statistics-${local.environment_name}"
Expand Down Expand Up @@ -89,16 +90,65 @@ resource "aws_lambda_permission" "cloudwatch_to_update_statistics_lambda" {
}

module "event_receiver" {
count = local.environment.event_bus_enabled ? 1 : 0
source = "./modules/lambda"
lambda_name = "event-receiver"
environment_variables = {
ENVIRONMENT = local.environment_name
REGION = data.aws_region.current.name
}
image_uri = "${data.aws_ecr_repository.use_an_lpa_event_receiver.repository_url}:${var.container_version}"
ecr_arn = data.aws_ecr_repository.use_an_lpa_upload_statistics.arn
ecr_arn = data.aws_ecr_repository.use_an_lpa_event_receiver.arn
environment = local.environment_name
kms_key = data.aws_kms_alias.cloudwatch_encryption.target_key_arn
timeout = 900
memory = 128
}

resource "aws_iam_role_policy" "lambda_event_receiver" {
count = local.environment.event_bus_enabled ? 1 : 0
name = "${local.environment_name}-lambda-event-receiver"
role = module.event_receiver[0].lambda_role.name
policy = data.aws_iam_policy_document.lambda_event_receiver[0].json
}


data "aws_iam_policy_document" "lambda_event_receiver" {
count = local.environment.event_bus_enabled ? 1 : 0
statement {
sid = "${local.environment_name}EventReceiverSQS"
effect = "Allow"
actions = [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
]
resources = [module.eu_west_1[0].receive_events_sqs_queue_arn[0]]
}

statement {
sid = "${local.environment_name}KMSDecrypt"
effect = "Allow"
actions = [
"kms:Decrypt",
"kms:DescribeKey"
]
resources = [data.aws_kms_alias.event_receiver.target_key_arn]
}
}

resource "aws_lambda_event_source_mapping" "receive_events_mapping" {
count = local.environment.event_bus_enabled ? 1 : 0
event_source_arn = module.eu_west_1[0].receive_events_sqs_queue_arn[0]
function_name = module.event_receiver[0].lambda_name
enabled = true
}

resource "aws_lambda_permission" "receive_events_permission" {
count = local.environment.event_bus_enabled ? 1 : 0
statement_id = "AllowExecutionFromSQS"
action = "lambda:InvokeFunction"
function_name = module.event_receiver[0].lambda_name
principal = "sqs.amazonaws.com"
source_arn = module.eu_west_1[0].receive_events_sqs_queue_arn[0]
}
5 changes: 5 additions & 0 deletions terraform/environment/modules/lambda/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ output "lambda_role" {
description = "The lambda role"
value = aws_iam_role.lambda_role
}

output "lambda_name" {
description = "The lambda name"
value = aws_lambda_function.lambda_function.function_name
}
4 changes: 4 additions & 0 deletions terraform/environment/region.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module "eu_west_1" {
ecs_task_roles = module.iam.ecs_task_roles
environment_name = local.environment_name
event_bus_enabled = local.environment.event_bus_enabled
event_reciever_kms_key_arn = data.aws_kms_alias.event_receiver.target_key_arn
google_analytics_id_use = local.environment.google_analytics_id_use
google_analytics_id_view = local.environment.google_analytics_id_view
gov_uk_onelogin_client_id_secret_name = local.environment.gov_uk_onelogin_client_id_secret_name
Expand All @@ -33,6 +34,7 @@ module "eu_west_1" {
lpa_codes_endpoint = local.environment.lpa_codes_endpoint
lpas_collection_endpoint = local.environment.lpas_collection_endpoint
lpa_data_store_endpoint = local.environment.lpa_data_store_endpoint
receive_account_ids = local.environment.receive_account_ids
mock_onelogin_enabled = local.environment.mock_onelogin_enabled
mock_onelogin_service_container_version = local.mock_onelogin_version
mock_onelogin_service_repository_url = data.aws_ecr_repository.mock_onelogin.repository_url
Expand Down Expand Up @@ -108,6 +110,7 @@ module "eu_west_2" {
ecs_task_roles = module.iam.ecs_task_roles
environment_name = local.environment_name
event_bus_enabled = local.environment.event_bus_enabled
event_reciever_kms_key_arn = data.aws_kms_alias.event_receiver.target_key_arn
google_analytics_id_use = local.environment.google_analytics_id_use
google_analytics_id_view = local.environment.google_analytics_id_view
gov_uk_onelogin_client_id_secret_name = local.environment.gov_uk_onelogin_client_id_secret_name
Expand All @@ -121,6 +124,7 @@ module "eu_west_2" {
lpa_codes_endpoint = local.environment.lpa_codes_endpoint
lpas_collection_endpoint = local.environment.lpas_collection_endpoint
lpa_data_store_endpoint = local.environment.lpa_data_store_endpoint
receive_account_ids = local.environment.receive_account_ids
mock_onelogin_enabled = local.environment.mock_onelogin_enabled
mock_onelogin_service_container_version = local.mock_onelogin_version
mock_onelogin_service_repository_url = data.aws_ecr_repository.mock_onelogin.repository_url
Expand Down
11 changes: 7 additions & 4 deletions terraform/environment/region/event_bus.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
module "event_bus" {
source = "./modules/event_bus"
environment_name = var.environment_name
event_bus_enabled = var.event_bus_enabled
current_region = data.aws_region.current.name
source = "./modules/event_bus"
environment_name = var.environment_name
event_bus_enabled = var.event_bus_enabled
current_region = data.aws_region.current.name
receive_account_ids = var.receive_account_ids
queue_visibility_timeout = local.queue_visibility_timeout
event_reciever_kms_key_arn = var.event_reciever_kms_key_arn
providers = {
aws.region = aws.region
}
Expand Down
2 changes: 2 additions & 0 deletions terraform/environment/region/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ locals {
admin_desired_count = local.is_active_region ? 1 : 0
mock_onelogin_desired_count = var.environment_name != "production" && var.mock_onelogin_enabled && local.is_active_region ? 1 : 0

queue_visibility_timeout = 900

# Replace the region in the ARN of the DynamoDB tables with the region of the current stack as the tables are created in the primary region
# and replicated to the secondary region. This allows use to grant access to the tables in the secondary region for applications running in the secondary region.
dynamodb_tables_arns = {
Expand Down
65 changes: 65 additions & 0 deletions terraform/environment/region/modules/event_bus/bus.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
resource "aws_cloudwatch_event_bus" "main" {
count = var.event_bus_enabled ? 1 : 0
name = var.environment_name
provider = aws.region
}

resource "aws_cloudwatch_event_archive" "main" {
count = var.event_bus_enabled ? 1 : 0
name = var.environment_name
event_source_arn = aws_cloudwatch_event_bus.main[0].arn
provider = aws.region
}

resource "aws_cloudwatch_event_rule" "receive_events_from_mlpa" {
count = var.event_bus_enabled ? 1 : 0
name = "${var.environment_name}-mlpa-events-to-use"
description = "Receive events from mlpa"
event_bus_name = aws_cloudwatch_event_bus.main[0].name

event_pattern = jsonencode({
source = ["opg.poas.makeregister"],
detail-type = ["lpa-access-granted"]
})

provider = aws.region
}

resource "aws_cloudwatch_event_bus_policy" "cross_account_receive" {
count = length(var.receive_account_ids) > 0 && var.event_bus_enabled ? 1 : 0
event_bus_name = aws_cloudwatch_event_bus.main[0].name
policy = data.aws_iam_policy_document.cross_account_receive[0].json
provider = aws.region
}

# Allow MLPA account to send messages
data "aws_iam_policy_document" "cross_account_receive" {
count = var.event_bus_enabled ? 1 : 0
statement {
sid = "CrossAccountAccess"
effect = "Allow"
actions = [
"events:PutEvents",
]
resources = [
aws_cloudwatch_event_bus.main[0].arn
]

principals {
type = "AWS"
identifiers = var.receive_account_ids
}
}
}

resource "aws_cloudwatch_event_target" "receive_events" {
count = var.event_bus_enabled ? 1 : 0
rule = aws_cloudwatch_event_rule.receive_events_from_mlpa[0].name
arn = aws_sqs_queue.receive_events_queue[0].arn
event_bus_name = aws_cloudwatch_event_bus.main[0].name
dead_letter_config {
arn = aws_sqs_queue.receive_events_deadletter[0].arn
}

provider = aws.region
}
Loading
Loading