Skip to content

Commit

Permalink
Importing existing SNS + Lambda (#2)
Browse files Browse the repository at this point in the history
* Importing existing SNS

* Updating to use lambda
  • Loading branch information
adenot authored Jun 11, 2024
1 parent c5a2db3 commit ecd7937
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
health-lambda-function-payload.zip
32 changes: 32 additions & 0 deletions health-lambda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import boto3
import json
import os

def lambda_handler(event, context):
sns_client = boto3.client('sns')
topic_arn = os.environ.get('SNS_TOPIC_ARN')
event_rule_name = os.environ.get('EVENT_RULE_NAME')

event_subject = f'ALARM: {event_rule_name}: {event["detail"]["eventTypeCode"]}'
event_message = "".join(
[
f'{event["detail"]["service"]}\n',
f'Event Type: {event["detail"]["eventTypeCode"]}\n',
f'Status: {event["detail"]["statusCode"]}\n',
event["detail"]["eventDescription"][0]["latestDescription"],
]
)

response = sns_client.publish(
TopicArn=topic_arn,
Message=event_message,
Subject=event_subject,
MessageAttributes={
'string': {
'DataType': 'String',
'StringValue': 'String'
}
}
)

print(response)
16 changes: 8 additions & 8 deletions kms.tf
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Create the KMS key
resource "aws_kms_key" "sns" {
count = var.sns_kms_encryption ? 1 : 0
count = var.sns_kms_encryption && var.sns_topic_name != "" ? 1 : 0
deletion_window_in_days = 7
description = "SNS CMK Encryption Key"
enable_key_rotation = true
}

# Define the KMS policy document
data "aws_iam_policy_document" "kms_policy_sns" {
count = var.sns_kms_encryption ? 1 : 0
count = var.sns_kms_encryption && var.sns_topic_name != "" ? 1 : 0

statement {
sid = "Enable Specific IAM User Permissions"
Expand All @@ -17,7 +17,7 @@ data "aws_iam_policy_document" "kms_policy_sns" {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = [
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
Expand All @@ -28,8 +28,8 @@ data "aws_iam_policy_document" "kms_policy_sns" {
}

statement {
sid = "Allow Use of Key for Specific Services"
actions = ["kms:Decrypt", "kms:GenerateDataKey*"]
sid = "Allow Use of Key for Specific Services"
actions = ["kms:Decrypt", "kms:GenerateDataKey*"]
principals {
type = "Service"
identifiers = ["cloudwatch.amazonaws.com", "lambda.amazonaws.com"]
Expand All @@ -40,7 +40,7 @@ data "aws_iam_policy_document" "kms_policy_sns" {

# Update the policy of the KMS key
resource "aws_kms_key_policy" "sns_policy" {
count = var.sns_kms_encryption ? 1 : 0
key_id = aws_kms_key.sns[0].key_id
policy = data.aws_iam_policy_document.kms_policy_sns[0].json
count = var.sns_kms_encryption && var.sns_topic_name != "" ? 1 : 0
key_id = aws_kms_key.sns[0].key_id
policy = data.aws_iam_policy_document.kms_policy_sns[0].json
}
67 changes: 67 additions & 0 deletions lambda.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
resource "aws_iam_role" "health_lambda_iam" {
name = var.event_rule_name
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = { Service = "lambda.amazonaws.com" }
},
]
})
inline_policy {
name = "sns"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["sns:Publish"]
Effect = "Allow"
Resource = var.sns_topic_name != "" ? aws_sns_topic.health_event_topic[0].arn : var.sns_topic_arn
},
{
Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
Effect = "Allow"
Resource = "arn:aws:logs:*:*:*"
}
]
})
}
}

data "archive_file" "health_lambda" {

Check warning on line 34 in lambda.tf

View workflow job for this annotation

GitHub Actions / Lint

Missing version constraint for provider "archive" in `required_providers`

Check warning on line 34 in lambda.tf

View workflow job for this annotation

GitHub Actions / Lint

Missing version constraint for provider "archive" in `required_providers`

Check warning on line 34 in lambda.tf

View workflow job for this annotation

GitHub Actions / Lint

Missing version constraint for provider "archive" in `required_providers`
type = "zip"
source_file = "${path.module}/health-lambda.py"
output_path = "${path.module}/health-lambda-function-payload.zip"
}

resource "aws_lambda_function" "health_lambda" {

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_117: "Ensure that AWS Lambda function is configured inside a VPC"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_116: "Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ)"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_272: "Ensure AWS Lambda function is configured to validate code-signing"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_50: "X-Ray tracing is enabled for Lambda"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_115: "Ensure that AWS Lambda function is configured for function-level concurrent execution limit"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_173: "Check encryption settings for Lambda environmental variable"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_117: "Ensure that AWS Lambda function is configured inside a VPC"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_116: "Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ)"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_272: "Ensure AWS Lambda function is configured to validate code-signing"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_50: "X-Ray tracing is enabled for Lambda"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_115: "Ensure that AWS Lambda function is configured for function-level concurrent execution limit"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_173: "Check encryption settings for Lambda environmental variable"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_117: "Ensure that AWS Lambda function is configured inside a VPC"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_116: "Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ)"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_272: "Ensure AWS Lambda function is configured to validate code-signing"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_50: "X-Ray tracing is enabled for Lambda"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_115: "Ensure that AWS Lambda function is configured for function-level concurrent execution limit"

Check failure on line 40 in lambda.tf

View workflow job for this annotation

GitHub Actions / scan

CKV_AWS_173: "Check encryption settings for Lambda environmental variable"
filename = "${path.module}/health-lambda-function-payload.zip"
function_name = var.event_rule_name
role = aws_iam_role.health_lambda_iam.arn
handler = "health-lambda.lambda_handler"
source_code_hash = data.archive_file.health_lambda.output_base64sha256
runtime = "python3.12"
environment {
variables = {
SNS_TOPIC_ARN = var.sns_topic_name != "" ? aws_sns_topic.health_event_topic[0].arn : var.sns_topic_arn
EVENT_RULE_NAME = var.event_rule_name
}
}
}

resource "aws_cloudwatch_event_target" "health_lambda" {
rule = aws_cloudwatch_event_rule.console.name
target_id = "health_lambda"
arn = aws_lambda_function.health_lambda.arn
}

resource "aws_lambda_permission" "health_lambda" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.health_lambda.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.console.arn
}
18 changes: 5 additions & 13 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,26 @@ locals {
}

resource "aws_cloudwatch_event_rule" "console" {
count = var.sns_topic_name != "" ? 1 : 0
name = "AWSHealthEventRule"
description = "EventBridge rule for AWS Health events"

name = var.event_rule_name
description = "EventBridge rule for AWS Health events"
event_pattern = var.use_default_event_pattern ? jsonencode(local.default_event_pattern) : jsonencode(local.custom_event_pattern)
}

resource "aws_sns_topic" "health_event_topic" {
count = var.sns_topic_name != "" ? 1 : 0
kms_master_key_id = var.sns_kms_encryption ? aws_kms_key.sns[0].id : null # default key does not allow cloudwatch alarms to publish
name = var.sns_topic_name
}

resource "aws_cloudwatch_event_target" "sns" {
count = var.sns_topic_name != "" ? 1 : 0
rule = aws_cloudwatch_event_rule.console[count.index].name
target_id = "SendToSNS"
arn = aws_sns_topic.health_event_topic[count.index].arn
}

resource "aws_sns_topic_subscription" "email_subscription" {
count = var.email_endpoint != null ? 1 : 0
count = var.email_endpoint != "" && var.sns_topic_name != "" ? 1 : 0
topic_arn = aws_sns_topic.health_event_topic[count.index].arn
protocol = "email"
endpoint = var.email_endpoint
}

resource "aws_sns_topic_subscription" "webhook_subscription" {
count = var.webhook_endpoint != "" ? 1 : 0
count = var.webhook_endpoint != "" && var.sns_topic_name != "" ? 1 : 0
topic_arn = aws_sns_topic.health_event_topic[count.index].arn
protocol = "https"
endpoint = var.webhook_endpoint
Expand Down
4 changes: 2 additions & 2 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
output "event_bridge_rule_id" {
value = aws_cloudwatch_event_rule.console[0].id
value = aws_cloudwatch_event_rule.console.id
}

output "sns_topic_arn" {
value = aws_sns_topic.health_event_topic[0].arn
value = var.sns_topic_name != "" ? aws_sns_topic.health_event_topic[0].arn : var.sns_topic_arn
}
16 changes: 14 additions & 2 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
variable "event_rule_name" {
description = "Name for the AWS Health Event Rule"
type = string
default = "AWSHealthEventRule"
}

variable "email_endpoint" {
description = "Email address for notifications (optional)"
description = "Email address for notifications (optional) - only when sns_topic_name is set"
type = string
default = ""
}

variable "webhook_endpoint" {
description = "Webhook URL for notifications (optional)"
description = "Webhook URL for notifications (optional) - only when sns_topic_name is set"
type = string
default = ""
}
Expand Down Expand Up @@ -33,3 +39,9 @@ variable "sns_topic_name" {
description = "Topic name (optional - creates SNS topic)"
default = ""
}

variable "sns_topic_arn" {
type = string
description = "Topic ARN (optional - uses an existing SNS topic)"
default = ""
}
4 changes: 2 additions & 2 deletions versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
version = ">= 4.0"
}
}

required_version = ">= 0.13.0"
}
}

0 comments on commit ecd7937

Please sign in to comment.