diff --git a/requirements.txt b/requirements.txt index 5c7639c236dbd4a1a83c19240ff743cdc88d41ca..35dd243ecdd341c9300901ac2e6a6beb2ff55643 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ dnspython requests +twilio diff --git a/sms-notify.tf b/sms-notify.tf new file mode 100644 index 0000000000000000000000000000000000000000..62a167b31525a27ed94ae45f6a90c0ce9e4b481e --- /dev/null +++ b/sms-notify.tf @@ -0,0 +1,172 @@ +variable "twilio_account_sid" { + description = "Twilio account SID." +} + +variable "twilio_api_key" { + description = "Twilio API key." +} + +variable "twilio_api_secret" { + description = "Twilio API secret." +} + +# It would have been nicer to buy the phone number with Terraform and the +# Twilio provider. unfortunately the sign up for the provider is closed right +# now. So instead the friendly name, that's something. +variable "twilio_from_number" { + default = "AmILive" + description = "Twilio from phone number." +} + +resource "aws_lambda_function" "sms_notify" { + runtime = var.runtime + function_name = "${local.function_name_prefix}-sms-notify" + role = local.lambda_role_arn + source_code_hash = filebase64sha256("payload.zip") + s3_bucket = local.payloads_bucket_name + s3_key = local.payload_object_name + s3_object_version = local.payload_object_version + package_type = "Zip" + handler = "sms_notify.handler" + description = "Send SMS message notification using Twilio." + memory_size = var.memory_size + tags = local.common_tags + timeout = var.timeout + + environment { + variables = { + ENV = local.env + MODULE = local.module + TOPIC_ARN = local.topic_arn + VERSION = local.payload_object_version + TWILIO_ACCOUNT_SID = var.twilio_account_sid + TWILIO_API_KEY = var.twilio_api_key + TWILIO_API_SECRET = var.twilio_api_secret + TWILIO_FROM_NUMBER = var.twilio_from_number + TWILIO_TO_NUMBER = local.my_phone_number + } + } + + # Create the log group with retention before the function is created. + # Otherwise it's created without retention and need to be imported. + depends_on = [ + aws_cloudwatch_log_group.sms_notify, + ] +} + +locals { + sms_notify_function_arn = aws_lambda_function.sms_notify.arn + sms_notify_function_name = aws_lambda_function.sms_notify.function_name + sms_notify_function_version = aws_lambda_function.sms_notify.version +} + +output "sms_notify_function_arn" { + description = "ARN of the SMS notification Lambda function." + value = local.sms_notify_function_arn +} + +output "sms_notify_function_name" { + description = "Name of the SMS notification Lambda function." + value = local.sms_notify_function_name +} + +output "sms_notify_function_version" { + description = "Version of the SMS notification Lambda function." + value = local.sms_notify_function_version +} + +resource "aws_lambda_alias" "sms_notify" { + name = "${local.function_name_prefix}_${local.sms_notify_function_name}" + function_name = local.sms_notify_function_arn + function_version = local.sms_notify_function_version +} + +locals { + sms_notify_function_alias_arn = aws_lambda_alias.sms_notify.arn + sms_notify_function_alias_name = aws_lambda_alias.sms_notify.name +} + +output "sms_notify_function_alias_arn" { + description = "ARN of the SMS notification Lambda function alias." + value = local.sms_notify_function_alias_arn +} + +output "sms_notify_function_alias_name" { + description = "Name of the SMS notification Lambda function alias." + value = local.sms_notify_function_alias_name +} + +resource "aws_lambda_permission" "sms_notify" { + statement_id = "AllowExecutionFromSNS" + action = "lambda:InvokeFunction" + principal = "sns.amazonaws.com" + source_arn = local.topic_arn + function_name = local.sms_notify_function_name +} + +resource "aws_sns_topic_subscription" "sms_notify" { + endpoint = local.sms_notify_function_arn + protocol = "lambda" + topic_arn = local.topic_arn + depends_on = [ + aws_lambda_permission.sms_notify, + ] +} +resource "aws_cloudwatch_log_group" "sms_notify" { + name = "/aws/lambda/${local.function_name_prefix}-sms-notify" + retention_in_days = var.log_retention + tags = local.common_tags +} + +locals { + sms_notify_log_group_arn = aws_cloudwatch_log_group.sms_notify.arn + sms_notify_log_group_name = aws_cloudwatch_log_group.sms_notify.name +} + +output "sms_notify_log_group_arn" { + description = "ARN of the CloudWatch log groups for the SMS notify Lambda function invocations." + value = local.sms_notify_log_group_arn +} + +output "sms_notify_log_group_name" { + description = "Name of the CloudWatch log groups for the SMS notify Lambda function invocations." + value = local.sms_notify_log_group_name +} + +data "aws_iam_policy_document" "sms_notify" { + statement { + effect = "Allow" + + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ] + + resources = [local.sms_notify_log_group_arn, ] + } +} + +locals { + sms_notify_log_policy_doc = data.aws_iam_policy_document.sms_notify.json +} + +resource "aws_iam_policy" "sms_notify_log" { + name = "${local.module}-${local.env}-sms-notify-log" + policy = local.sms_notify_log_policy_doc + tags = local.common_tags +} + +locals { + sms_notify_log_policy_arn = aws_iam_policy.log.arn + sms_notify_log_policy_name = aws_iam_policy.log.name +} + +output "sms_notify_log_policy_arn" { + value = local.sms_notify_log_policy_arn + description = "CloudWatch log IAM policy for SMS notifications ARN." +} + +output "sms_notify_log_policy_name" { + value = local.sms_notify_log_policy_name + description = "CloudWatch log IAM policy for SMS notifications name." +} diff --git a/sns.tf b/sns.tf index 725e2e56dbfd217070759383b159c1cfe987eddb..6ddf0d9e1380330a45144f574e9521c301eb095d 100644 --- a/sns.tf +++ b/sns.tf @@ -25,6 +25,10 @@ variable "subscriptions" { description = "A list of subscriptions to the SNS topic." } +locals { + my_phone_number = var.subscriptions[0][0] +} + output "subscriptions" { description = "A list of subscriptions to the SNS topic." value = var.subscriptions diff --git a/src/sms_notify.py b/src/sms_notify.py new file mode 100644 index 0000000000000000000000000000000000000000..4564f2d659681b9da89a517e4e6a2c7b782d1622 --- /dev/null +++ b/src/sms_notify.py @@ -0,0 +1,26 @@ +import os +import twilio.rest # pylint: disable=import-error + + +TWILIO_ACCOUNT_SID = os.environ["TWILIO_ACCOUNT_SID"] +TWILIO_API_KEY = os.environ["TWILIO_API_KEY"] +TWILIO_API_SECRET = os.environ["TWILIO_API_SECRET"] +TWILIO_FROM_NUMBER = os.environ["TWILIO_FROM_NUMBER"] +TWILIO_TO_NUMBER = os.environ["TWILIO_TO_NUMBER"] + + +# pylint: disable=unused-argument +def handler(event, context): + message = event["Records"][0]["Sns"]["Message"] + client = twilio.rest.Client( + TWILIO_API_KEY, TWILIO_API_SECRET, TWILIO_ACCOUNT_SID + ) + client.messages.create( + body=message, + from_=TWILIO_FROM_NUMBER, + to=TWILIO_TO_NUMBER, + ) + + +if __name__ == "__main__": + handler({"Records": [{"Sns": {"Message": "foo"}}]}, "context")