diff --git a/terraform/modules/eventbridge/cloudwatch.tf b/terraform/modules/eventbridge/cloudwatch.tf new file mode 100644 index 00000000..76f2756e --- /dev/null +++ b/terraform/modules/eventbridge/cloudwatch.tf @@ -0,0 +1,8 @@ +resource "aws_cloudwatch_log_group" "eventbridge_log_group" { + name = "/aws/events/${aws_cloudwatch_event_rule.module_event.name}" +} + +resource "aws_cloudwatch_log_stream" "eventbridge_log_stream" { + name = "eventbridge_log_stream" + log_group_name = aws_cloudwatch_log_group.eventbridge_log_group.name +} \ No newline at end of file diff --git a/terraform/modules/eventbridge/data.tf b/terraform/modules/eventbridge/data.tf new file mode 100644 index 00000000..c4324585 --- /dev/null +++ b/terraform/modules/eventbridge/data.tf @@ -0,0 +1,5 @@ +data "aws_caller_identity" "current" {} + +/*data "aws_ecs_task_definition" "latest" { + task_definition = var.task_definition_arn +}*/ diff --git a/terraform/modules/eventbridge/iam.tf b/terraform/modules/eventbridge/iam.tf new file mode 100644 index 00000000..4d4e1b58 --- /dev/null +++ b/terraform/modules/eventbridge/iam.tf @@ -0,0 +1,36 @@ +resource "aws_iam_role" "eventbridge_role" { + name = "${var.iam_prefix}-${var.resource_prefix}-eventbridge_access_role" + permissions_boundary = var.target_account_cloudone ? local.permission_boundary_arn : null + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "events.amazonaws.com" + } + }] + }) +} + +resource "aws_iam_role_policy" "eventbridge_policy" { + role = aws_iam_role.eventbridge_role.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = [ + "ecs:RunTask", + "lambda:InvokeFunction", + "iam:PassRole", + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "sns:Publish" + ] + Resource = "*" + Effect = "Allow" + }] + }) +} \ No newline at end of file diff --git a/terraform/modules/eventbridge/locals.tf b/terraform/modules/eventbridge/locals.tf new file mode 100644 index 00000000..24d404b4 --- /dev/null +++ b/terraform/modules/eventbridge/locals.tf @@ -0,0 +1,5 @@ +locals { + ecs_conditions = var.target_type == "ecs-task" + lambda_conditions = var.target_type == "lambda" + permission_boundary_arn = terraform.workspace == "stage" || terraform.workspace == "prod" ? null : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:policy/PermissionBoundary_PowerUser" +} diff --git a/terraform/modules/eventbridge/main.tf b/terraform/modules/eventbridge/main.tf new file mode 100644 index 00000000..9ffb4c1f --- /dev/null +++ b/terraform/modules/eventbridge/main.tf @@ -0,0 +1,38 @@ +resource "aws_cloudwatch_event_rule" "module_event" { + name = var.eventbridge_name + schedule_expression = var.schedule_expression + role_arn = aws_iam_role.eventbridge_role.arn +} + + + +# For ECS Task +resource "aws_cloudwatch_event_target" "ecs_target" { + count = local.ecs_conditions ? 1 : 0 + + rule = aws_cloudwatch_event_rule.module_event.name + arn = var.target_arn + target_id = "${var.target_type}-${aws_cloudwatch_event_rule.module_event.name}" + role_arn = var.role_arn + ecs_target { + task_definition_arn = var.task_definition_arn + task_count = 1 + launch_type = "FARGATE" + network_configuration { + subnets = var.private_subnet_ids + security_groups = var.ecs_security_groups + assign_public_ip = var.assign_public_ip + } + } +} + +# For Lambda Function +resource "aws_cloudwatch_event_target" "lambda_target" { + count = local.lambda_conditions ? 1 : 0 + + rule = aws_cloudwatch_event_rule.module_event.name + arn = var.target_arn + target_id = "${var.target_type}-${aws_cloudwatch_event_rule.module_event.name}" + role_arn = aws_iam_role.eventbridge_role.arn + +} diff --git a/terraform/modules/eventbridge/outputs.tf b/terraform/modules/eventbridge/outputs.tf new file mode 100644 index 00000000..5a7c62f7 --- /dev/null +++ b/terraform/modules/eventbridge/outputs.tf @@ -0,0 +1,17 @@ +# Output for the EventBridge rule name +output "eventbridge_rule_name" { + value = aws_cloudwatch_event_rule.module_event.name + description = "The name of the EventBridge rule." +} + +# Output for the ECS EventBridge target ID, providing a default value if no resource is created +output "eventbridge_ecs_target_id" { + value = length(aws_cloudwatch_event_target.ecs_target) > 0 ? aws_cloudwatch_event_target.ecs_target[0].target_id : "No ECS target created" + description = "The ID of the EventBridge target for the ECS task." +} + +# Output for the Lambda EventBridge target ID, providing a default value if no resource is created +output "eventbridge_lambda_target_id" { + value = length(aws_cloudwatch_event_target.lambda_target) > 0 ? aws_cloudwatch_event_target.lambda_target[0].target_id : "No Lambda target created" + description = "The ID of the EventBridge target for the Lambda function." +} diff --git a/terraform/modules/eventbridge/variables.tf b/terraform/modules/eventbridge/variables.tf new file mode 100644 index 00000000..722d0d57 --- /dev/null +++ b/terraform/modules/eventbridge/variables.tf @@ -0,0 +1,83 @@ +variable "eventbridge_name" { + description = "Name of the EventBridge rule" + type = string +} + +variable "schedule_expression" { + description = "Schedule expression for the EventBridge rule" + type = string +} + +variable "target_type" { + description = "Type of the EventBridge target (e.g., 'ecs-task', 'lambda', 'sns')" + type = string +} + +variable "target_arn" { + description = "ARN of the EventBridge target" + type = string +} + +variable "ecs_cluster_arn" { + description = "ARN of the ECS cluster for ECS task type targets" + type = string + default = "" +} + +variable "task_definition_arn" { + description = "ARN of the ECS task definition for ECS task type targets" + type = string + default = "" +} + +variable "private_subnet_ids" { + description = "List of private subnet IDs for ECS task type targets" + type = list(string) + default = [] +} + +variable "ecs_security_groups" { + description = "List of security group IDs for ECS task type targets" + type = list(string) + default = [] +} + +variable "assign_public_ip" { + description = "Whether to assign a public IP to the ECS task. Valid values: 'ENABLED', 'DISABLED'" + type = string + default = "DISABLED" +} + +/*variable "input" { + description = "Input passed to the target, must be JSON" + type = string + default = "{}" +} + +variable "input_paths" { + description = "JSON paths to be extracted from the event and used in the input template" + type = map(string) + default = {} +}*/ + +variable "resource_prefix" { + description = "The prefix to add when creating resources" + type = string +} + +variable "iam_prefix" { + description = "The string prefix for IAM roles and policies to conform to NCI power-user compliance" + type = string + default = "power-user" +} + +variable "target_account_cloudone"{ + description = "to add check conditions on whether the resources are brought up in cloudone or not" + type = bool + default = true +} + +variable "role_arn" { + description = "The ARN of the IAM role to use for EventBridge." + type = string +}