diff --git a/Rakefile b/Rakefile index 759a049..187c3b3 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,7 @@ require 'fileutils' require 'rspec/core/rake_task' require 'tmpdir' +require 'aws-sdk-resources' PROJECT_DIR = 'projects' @@ -110,7 +111,7 @@ end desc 'Apply the terraform resources' -task apply: [:configure_state] do +task apply: [:configure_state, :latest_version_id] do tmp_dir = _flatten_project puts "terraform apply -var-file=variables/#{deploy_env}.tfvars #{tmp_dir}" @@ -121,6 +122,23 @@ task apply: [:configure_state] do end +desc 'Latest Lambda version ID' +task :latest_version_id do + lambda_filename = ENV['TF_VAR_LAMBDA_FILENAME'] + target_file = "#{project_name}/#{lambda_filename}" + if lambda_filename + s3 = Aws::S3::Resource.new(region: 'eu-west-1') + bucket = s3.bucket("govuk-lambda-applications-#{deploy_env}") + begin + version_id = bucket.object(target_file).version_id + rescue Aws::S3::Errors::NotFound + abort "File not found: s3://govuk-lambda-applications-#{deploy_env}/#{target_file}" + end + ENV['TF_VAR_LAMBDA_VERSIONID'] = version_id + end +end + + desc 'Destroy the terraform resources' task destroy: [:configure_state] do tmp_dir = _flatten_project @@ -134,7 +152,7 @@ end desc 'Show the plan' -task plan: [:configure_state] do +task plan: [:configure_state, :latest_version_id] do tmp_dir = _flatten_project system("terraform plan -module-depth=-1 -var-file=variables/#{deploy_env}.tfvars #{tmp_dir}") diff --git a/projects/email_alert_notifications/README.md b/projects/email_alert_notifications/README.md new file mode 100644 index 0000000..db0969a --- /dev/null +++ b/projects/email_alert_notifications/README.md @@ -0,0 +1,20 @@ +# Email Alert Notifications + +This project sets up an S3 bucket and a Lambda that parses files, +extracts `data-govuk-request-id` and renames the file accordingly as +either: + + travel-advice-alerts/.msg + +or if the file doesn't contain a `data-govuk-request-id` + + no-request-id/.msg + +## Manual Steps + +There is a manual step required for this 'app'. + +* An SES domain with a RuleSet containing an action that writes to the S3 +bucket (`govuk-email-alert-notifications`). An address on this domain will be +subscribed to all of the travel advice country alerts + diff --git a/projects/email_alert_notifications/resources/email_alert_notifications.tf b/projects/email_alert_notifications/resources/email_alert_notifications.tf new file mode 100644 index 0000000..9807284 --- /dev/null +++ b/projects/email_alert_notifications/resources/email_alert_notifications.tf @@ -0,0 +1,81 @@ +variable "s3_bucket_name" { + default = "govuk-email-alert-notifications" +} + +variable "environment"{ +} + +variable "LAMBDA_FILENAME"{ +} + +variable "LAMBDA_VERSIONID"{ +} + +variable "lambda_bucket"{ + default = "govuk-lambda-applications" +} + +resource "template_file" "s3_bucket_policy" { + template = "${file("projects/email_alert_notifications/templates/email_alert_s3_bucket_policy.json")}" + vars { + account_id = "${element(split(":", aws_iam_role.lambda_execute_and_write_to_email_alert_bucket.arn), 4)}" + bucket_name = "${var.s3_bucket_name}-${var.environment}" + lambda_role = "${aws_iam_role.lambda_execute_and_write_to_email_alert_bucket.arn}" + } +} + +resource "template_file" "put_and_delete_to_email_alert_bucket_policy" { + template = "${file("projects/email_alert_notifications/templates/put_and_delete_to_s3_policy.json")}" + vars { + resource_arn = "${aws_s3_bucket.email_alert_inbox_bucket.arn}" + } +} + +resource "aws_s3_bucket" "email_alert_inbox_bucket" { + bucket = "${var.s3_bucket_name}-${var.environment}" + acl = "public-read" + policy = "${template_file.s3_bucket_policy.rendered}" +} + +resource "aws_iam_role" "lambda_execute_and_write_to_email_alert_bucket" { + name = "lambda_execute_and_write_to_email_alert_bucket" + assume_role_policy = "${file("projects/email_alert_notifications/templates/lambda_assume_role_policy.json")}" +} + +resource "aws_iam_role_policy" "put_and_delete_to_email_alert_bucket" { + name = "put_and_delete_to_email_alert_bucket" + role = "${aws_iam_role.lambda_execute_and_write_to_email_alert_bucket.id}" + policy = "${template_file.put_and_delete_to_email_alert_bucket_policy.rendered}" +} + +resource "aws_iam_role_policy" "write_to_logs" { + name = "write_to_logs" + role = "${aws_iam_role.lambda_execute_and_write_to_email_alert_bucket.id}" + policy = "${file("projects/email_alert_notifications/templates/write_to_logs_policy.json")}" +} + +resource "aws_lambda_function" "rename_email_files_with_request_id"{ + s3_bucket = "${var.lambda_bucket}-${var.environment}" + s3_key="${var.LAMBDA_FILENAME}" + s3_object_version="${var.LAMBDA_VERSIONID}" + function_name = "rename_email_files_with_request_id" + role = "${aws_iam_role.lambda_execute_and_write_to_email_alert_bucket.arn}" + handler = "rename_email_files_with_request_id.lambda_handler" + runtime = "python2.7" +} + +resource "aws_lambda_permission" "allow_email_alert_inbox_bucket" { + statement_id = "AllowExecutionFromS3Bucket" + action = "lambda:InvokeFunction" + function_name = "${aws_lambda_function.rename_email_files_with_request_id.arn}" + principal = "s3.amazonaws.com" + source_arn = "${aws_s3_bucket.email_alert_inbox_bucket.arn}" +} + +resource "aws_s3_bucket_notification" "email_alert_inbox_bucket_notification" { + bucket = "${aws_s3_bucket.email_alert_inbox_bucket.id}" + lambda_function { + lambda_function_arn = "${aws_lambda_function.rename_email_files_with_request_id.arn}" + events = ["s3:ObjectCreated:Put"] + } +} diff --git a/projects/email_alert_notifications/templates/email_alert_s3_bucket_policy.json b/projects/email_alert_notifications/templates/email_alert_s3_bucket_policy.json new file mode 100644 index 0000000..357eec6 --- /dev/null +++ b/projects/email_alert_notifications/templates/email_alert_s3_bucket_policy.json @@ -0,0 +1,32 @@ +{ + "Version": "2012-10-17", + "Id": "${uuid()}", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "${lambda_role}" + }, + "Action": [ + "s3:PutObject", + "s3:DeleteObject", + "s3:GetObject" + ], + "Resource": "arn:aws:s3:::${bucket_name}/*" + }, + { + "Sid": "GiveSESPermissionToWriteEmail", + "Effect": "Allow", + "Principal": { + "Service": "ses.amazonaws.com" + }, + "Action": "s3:PutObject", + "Resource": "arn:aws:s3:::${bucket_name}/*", + "Condition": { + "StringEquals": { + "aws:Referer": "${account_id}" + } + } + } + ] +} diff --git a/projects/email_alert_notifications/templates/lambda_assume_role_policy.json b/projects/email_alert_notifications/templates/lambda_assume_role_policy.json new file mode 100644 index 0000000..7dee58b --- /dev/null +++ b/projects/email_alert_notifications/templates/lambda_assume_role_policy.json @@ -0,0 +1,13 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Effect": "Allow", + "Sid": "" + } + ] +} diff --git a/projects/email_alert_notifications/templates/put_and_delete_to_s3_policy.json b/projects/email_alert_notifications/templates/put_and_delete_to_s3_policy.json new file mode 100644 index 0000000..125e0dc --- /dev/null +++ b/projects/email_alert_notifications/templates/put_and_delete_to_s3_policy.json @@ -0,0 +1,15 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "s3:getObject", + "s3:putObject", + "s3:deleteObject", + "s3:putObjectAcl" + ], + "Effect": "Allow", + "Resource": "${resource_arn}" + } + ] +} diff --git a/projects/email_alert_notifications/templates/write_to_logs_policy.json b/projects/email_alert_notifications/templates/write_to_logs_policy.json new file mode 100644 index 0000000..63a7264 --- /dev/null +++ b/projects/email_alert_notifications/templates/write_to_logs_policy.json @@ -0,0 +1,14 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": "arn:aws:logs:*:*:*" + } + ] +}