-
Notifications
You must be signed in to change notification settings - Fork 1
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
Email Notifications [mimics main branch] #140
Closed
Closed
Changes from 52 commits
Commits
Show all changes
106 commits
Select commit
Hold shift + click to select a range
ab8e5a4
Bring over WIP from template-infra branch
rocketnova 9ab6473
Enable notifications
rocketnova e772c1e
Restrict access
rocketnova 18ee918
Conditionally return values based on verification method
rocketnova d62b062
Deal with pinpoint_email_channel role_arn
rocketnova 391b603
Separate a verified sender identity from a pinpoint app
rocketnova 9a607bb
Refactor outputs and variables
rocketnova 0c417ad
Add code for aws_sesv2_email_identity_policy
rocketnova 179b385
Drop workspace prefix for notifications config
rocketnova 79f1bb9
Connect notifications and email-identity modules with app-config and …
rocketnova c07cb33
Rework idp to remove dependency on data output which would otherwise …
rocketnova 11eee11
Add test email to satisfy tests
rocketnova a3e203b
Fix IAM role name collision
rocketnova c649240
Grant Github Actions auth for notifications: ses & mobiletargeting
rocketnova 5dbcda6
Remove deprecated pinpoint identity role
rocketnova f0a9759
Move email identity into resources subdir
rocketnova 7330a31
Refactor to support re-using existing email identities
rocketnova d7b5e35
Fix depends_on syntax
rocketnova 3a80dbf
Simplify
rocketnova f6a57ed
Simplify and use domain name
rocketnova 06bae3a
Auto-add dns records for domain verification
rocketnova 9a53c2c
Merge branch 'main' into rocket/notifications
coilysiren 1e24692
diff reduction
coilysiren 64268b1
spacing and docs
coilysiren 46dd4cd
use jsonencode
coilysiren 0e4eb4c
module path
coilysiren a3834ee
prefix
coilysiren 2b7bda9
try to fix verification records
coilysiren d2c2bf3
try using count
coilysiren 33e654d
use route53 config from truss
coilysiren e3bbbdd
fix vars
coilysiren 044b13c
trigger ci
coilysiren c38a5ec
fix regex
coilysiren bb99fa7
use 'mail' subdomain
coilysiren 939f6fd
try subdomain again
coilysiren ca0a0d4
try subdomain again again
coilysiren a9e50da
revert to the original stuff
coilysiren bda7066
strip last
coilysiren 09b6f08
fix incorrect var
coilysiren bd3f474
add back TLD
coilysiren 11b8712
mail dot
coilysiren c45728a
mail_from_domain
coilysiren 9c967c9
outbound subdomain
coilysiren f52cdf5
try again
coilysiren ab4da73
use trussworks patterns
coilysiren 60edf04
update vars
coilysiren 359f8ef
pass in seperate domain names
coilysiren c487417
workon mail from domain
coilysiren 802536f
update vars
coilysiren 5580c74
typo
coilysiren a7df4f9
route53 is on the wrong domain
coilysiren 57bd7c7
small TXT change
coilysiren e688f90
move folders, remove some complexity around PR envs
coilysiren bea59b1
use existing zone
coilysiren 3ab84b2
fix validation errors
coilysiren 6de293c
dont double up on notes services
coilysiren 5e212a0
fix conditional
coilysiren 27fda90
Merge branch 'main' into kai/notifications
coilysiren 6557098
more files means less merge conflicts
coilysiren 23e653b
move module around
coilysiren e667aee
setup notifications client
coilysiren d5aedaa
add vars to service
coilysiren cc8e679
swap to real versions
coilysiren 4fdb991
update output
coilysiren 1f00ad9
remove errant module
coilysiren 5add212
Revert "remove errant module"
coilysiren 7f2ebe4
remove correct stuff
coilysiren f36741a
Merge remote-tracking branch 'origin' into kai/notifications-2
coilysiren 2366ca9
Merge remote-tracking branch 'origin' into kai/notifications
coilysiren d8ecbfe
Revert "swap to real versions"
coilysiren 3df9175
name based on PR apps
coilysiren 7ba2cdb
Merge branch 'kai/notifications' into kai/notifications-2
coilysiren 67710e8
Revert "Revert "swap to real versions""
coilysiren 2483ed3
string concat
coilysiren 42f781d
string concat
coilysiren bd6e835
auto code review
coilysiren 75e7bc4
typo
coilysiren 31ff496
narrow env var scope
coilysiren d421603
domain_identity_arn
coilysiren 52643a5
cleanup some vars
coilysiren f2d43bf
validation + test
coilysiren a6d6d83
Revert "validation + test"
coilysiren d8b89e2
use domain name as name
coilysiren 8a10e95
remove some name
coilysiren 7081ed2
comment
coilysiren d1218bb
move stuff around
coilysiren 98d8036
ignore a bunch of stuff
coilysiren e3379d2
fix domain vars
coilysiren 8a72123
testing
coilysiren 592a188
pull from correct var hopefully
coilysiren 09a192d
use default email config, instead of explicit one
coilysiren 9794f45
various renames
coilysiren 1fa2229
revert idp stuff
coilysiren 5910294
delete app first
coilysiren 31eb7b2
delete it please, thanks
coilysiren fcfa6f4
update some var refs
coilysiren b8cd1fe
put everything back
coilysiren 103f386
update vars
coilysiren fe2678d
reorg
coilysiren e1c6c2f
a var name
coilysiren e46c6b7
Merge branch 'kai/notifications-2' into kai/notifications
coilysiren cd3088a
typo
coilysiren 545c659
bool
coilysiren b155ab2
testing env
coilysiren 0584221
fix ifs
coilysiren e820044
fix domain input
coilysiren File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,31 @@ | ||
# Notifications configuration | ||
locals { | ||
notifications_config = var.enable_notifications ? { | ||
# Set to an SES-verified email address to be used when sending emails. | ||
# Docs: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-email.html | ||
sender_email = null | ||
# Pinpoint app name. | ||
name = "${var.app_name}-${var.environment}" | ||
|
||
# The method to use to verify the sender email address. | ||
# - Must be 'email' or 'domain'. | ||
# - If method is 'email', AWS will send you an email with a one-time link. Click on | ||
# the link to verify the email address. | ||
# - If method is 'domain', then custom domains are required and the domain used will | ||
# match the one set in the env-config. See /docs/infra/set-up-custom-domains.md | ||
# Docs: https://docs.aws.amazon.com/pinpoint/latest/userguide/channels-email-manage-verify.html | ||
email_verification_method = "domain" | ||
|
||
# Configure the name that users see in the "From" section of their inbox, so that it's | ||
# clearer who the email is from. | ||
sender_display_name = null | ||
sender_display_name = "coilysiren" | ||
|
||
# Set to the email address to be used when sending emails. | ||
# - If enable_notifications is true, this is required. | ||
# - If email_verification_method is set to 'domain', make sure the domain name of the | ||
# sender_email matches the domain provided in the env-config. | ||
# Docs: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-email.html | ||
sender_email = "[email protected]" | ||
|
||
# Configure the REPLY-TO email address if it should be different from the sender. | ||
# Note: Only used by the identity-provider service. | ||
reply_to_email = null | ||
reply_to_email = "[email protected]" | ||
} : null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,30 @@ locals { | |
|
||
network_config = module.project_config.network_configs[local.environment_config.network_name] | ||
|
||
# Notifications locals. | ||
# | ||
# 1. If notifications are enabled and the verification method is 'email', then we | ||
# extract the domain_name from the sender_email. For example: | ||
# example.com from sender_email: [email protected] | ||
# | ||
# 2. If notifications are enabled and the verification method is 'domain', then we | ||
# construct the domain_name using the format: <terraform workspace><environment.<domain> | ||
# For example: t-123456-dev.bar.com | ||
|
||
mail_from_domain = "mail.${local.notifications_sender_email_domain_name}" | ||
|
||
notifications_sender_email_domain_name = module.app_config.enable_notifications ? ( | ||
local.notifications_config.email_verification_method == "email" ? | ||
regex("@(.*)", local.notifications_config.sender_email)[0] : | ||
"${local.prefix}${var.environment_name}.${local.service_config.domain_name}" | ||
) : null | ||
|
||
notifications_sender_email = module.app_config.enable_notifications ? ( | ||
local.notifications_config.email_verification_method == "email" ? | ||
local.notifications_config.sender_email : | ||
"${regex("(.*)@", local.notifications_config.sender_email)[0]}@${local.notifications_sender_email_domain_name}" | ||
) : null | ||
|
||
# Identity provider locals. | ||
# If this is a temporary environment, re-use an existing Cognito user pool. | ||
# Otherwise, create a new one. | ||
|
@@ -233,6 +257,29 @@ module "storage" { | |
is_temporary = local.is_temporary | ||
} | ||
|
||
module "email_identity" { | ||
count = module.app_config.enable_notifications ? 1 : 0 | ||
source = "../../modules/email-identity" | ||
|
||
email_verification_method = local.notifications_config.email_verification_method | ||
name = local.notifications_config.name | ||
sender_email = local.notifications_sender_email | ||
mail_from_domain = local.mail_from_domain | ||
domain_name = local.notifications_sender_email_domain_name | ||
} | ||
|
||
module "notifications" { | ||
count = module.app_config.enable_notifications ? 1 : 0 | ||
source = "../../modules/notifications" | ||
|
||
email_configuration_set_name = module.email_identity[0].email_configuration_set_name | ||
email_identity_arn = module.email_identity[0].email_identity_arn | ||
|
||
name = "${local.prefix}${local.notifications_config.name}" | ||
sender_display_name = local.notifications_config.sender_display_name | ||
sender_email = local.notifications_sender_email | ||
} | ||
|
||
# If the app has `enable_identity_provider` set to true AND this is not a temporary | ||
# environment, then create a new identity provider. | ||
module "identity_provider" { | ||
|
@@ -247,9 +294,12 @@ module "identity_provider" { | |
verification_email_message = local.identity_provider_config.verification_email.verification_email_message | ||
verification_email_subject = local.identity_provider_config.verification_email.verification_email_subject | ||
|
||
sender_email = local.notifications_config == null ? null : local.notifications_config.sender_email | ||
sender_display_name = local.notifications_config == null ? null : local.notifications_config.sender_display_name | ||
reply_to_email = local.notifications_config == null ? null : local.notifications_config.reply_to_email | ||
sender_email = module.app_config.enable_notifications ? local.notifications_sender_email : null | ||
sender_display_name = module.app_config.enable_notifications ? local.notifications_config.sender_display_name : null | ||
reply_to_email = module.app_config.enable_notifications ? local.notifications_config.reply_to_email : null | ||
|
||
# This requires an email identity that has been verified for sending. | ||
email_identity_arn = module.app_config.enable_notifications ? module.email_identity[0].verified_email_identity_arn : null | ||
} | ||
|
||
# If the app has `enable_identity_provider` set to true AND this *is* a temporary | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Configures AWS SES to send additional logging to AWS Cloudwatch. | ||
# See https://docs.aws.amazon.com/ses/latest/dg/event-destinations-manage.html | ||
resource "aws_ses_event_destination" "logs" { | ||
name = "${var.name}-email-identity-logs" | ||
configuration_set_name = aws_sesv2_configuration_set.email.configuration_set_name | ||
enabled = true | ||
matching_types = [ | ||
"bounce", | ||
"click", | ||
"complaint", | ||
"delivery", | ||
"open", | ||
"reject", | ||
"renderingFailure", | ||
"send" | ||
] | ||
|
||
cloudwatch_destination { | ||
dimension_name = "email_type" | ||
default_value = "other" | ||
value_source = "messageTag" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# This module manages an SESv2 email identity. | ||
data "aws_caller_identity" "current" {} | ||
data "aws_region" "current" {} | ||
|
||
locals { | ||
stripped_domain_name = replace(var.domain_name, "/[.]$/", "") | ||
stripped_mail_from_domain = replace(var.mail_from_domain, "/[.]$/", "") | ||
dash_domain = replace(var.domain_name, ".", "-") | ||
} | ||
|
||
# Verify email sender identity. | ||
# Docs: https://docs.aws.amazon.com/pinpoint/latest/userguide/channels-email-manage-verify.html | ||
resource "aws_sesv2_email_identity" "sender" { | ||
email_identity = var.email_verification_method == "email" ? var.sender_email : local.stripped_domain_name | ||
configuration_set_name = aws_sesv2_configuration_set.email.configuration_set_name | ||
} | ||
|
||
# The configuration set applied to messages that is sent through this email channel. | ||
resource "aws_sesv2_configuration_set" "email" { | ||
configuration_set_name = var.name | ||
|
||
delivery_options { | ||
tls_policy = "REQUIRE" | ||
} | ||
|
||
reputation_options { | ||
reputation_metrics_enabled = true | ||
} | ||
|
||
sending_options { | ||
sending_enabled = true | ||
} | ||
|
||
suppression_options { | ||
suppressed_reasons = ["BOUNCE", "COMPLAINT"] | ||
} | ||
} | ||
|
||
# Allow AWS Pinpoint to send email on behalf of this email identity. | ||
# Docs: https://docs.aws.amazon.com/pinpoint/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_resource-based-policy-examples-access-ses-identities | ||
resource "aws_sesv2_email_identity_policy" "sender" { | ||
email_identity = aws_sesv2_email_identity.sender.email_identity | ||
policy_name = "PinpointEmail" | ||
|
||
policy = jsonencode( | ||
{ | ||
Version = "2008-10-17", | ||
Statement = [ | ||
{ | ||
Sid = "PinpointEmail", | ||
Effect = "Allow", | ||
Principal = { | ||
Service = "pinpoint.amazonaws.com" | ||
}, | ||
Action = "ses:*", | ||
Resource = "${aws_sesv2_email_identity.sender.arn}", | ||
Condition = { | ||
StringEquals = { | ||
"aws:SourceAccount" = "${data.aws_caller_identity.current.account_id}" | ||
}, | ||
StringLike = { | ||
"aws:SourceArn" = "arn:aws:mobiletargeting:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:apps/*" | ||
} | ||
} | ||
} | ||
] | ||
} | ||
) | ||
} | ||
|
||
# If email_verification_method is "domain", create a Route53 hosted zone for the sending | ||
# domain. | ||
resource "aws_route53_zone" "zone" { | ||
count = var.email_verification_method == "domain" ? 1 : 0 | ||
name = var.domain_name | ||
# checkov:skip=CKV2_AWS_38:TODO(https://github.com/navapbc/template-infra/issues/560) enable DNSSEC | ||
} | ||
|
||
resource "aws_sesv2_email_identity_mail_from_attributes" "sender" { | ||
email_identity = aws_sesv2_email_identity.sender.email_identity | ||
mail_from_domain = local.stripped_mail_from_domain | ||
|
||
depends_on = [aws_sesv2_email_identity.sender] | ||
} | ||
|
||
# DNS records for email identity verification if email_verification_method is "domain" | ||
resource "aws_route53_record" "dkim" { | ||
count = var.email_verification_method == "domain" ? 3 : 0 | ||
|
||
allow_overwrite = true | ||
ttl = 60 | ||
type = "CNAME" | ||
zone_id = aws_route53_zone.zone[0].zone_id | ||
name = "${aws_sesv2_email_identity.sender.dkim_signing_attributes[0].tokens[count.index]}._domainkey" | ||
records = ["${aws_sesv2_email_identity.sender.dkim_signing_attributes[0].tokens[count.index]}.dkim.amazonses.com"] | ||
|
||
depends_on = [aws_sesv2_email_identity.sender] | ||
} | ||
|
||
resource "aws_route53_record" "spf_mail_from" { | ||
count = var.email_verification_method == "domain" ? 1 : 0 | ||
|
||
allow_overwrite = true | ||
ttl = "600" | ||
type = "TXT" | ||
zone_id = aws_route53_zone.zone[0].zone_id | ||
name = aws_sesv2_email_identity_mail_from_attributes.sender.mail_from_domain | ||
records = ["v=spf1 include:amazonses.com ~all"] | ||
} | ||
|
||
resource "aws_route53_record" "mx_send_mail_from" { | ||
count = var.email_verification_method == "domain" ? 1 : 0 | ||
|
||
allow_overwrite = true | ||
type = "MX" | ||
ttl = "600" | ||
zone_id = aws_route53_zone.zone[0].zone_id | ||
name = aws_sesv2_email_identity_mail_from_attributes.sender.mail_from_domain | ||
records = ["10 feedback-smtp.${data.aws_region.current.name}.amazonses.com"] | ||
} | ||
|
||
resource "aws_route53_record" "mx_receive" { | ||
count = var.email_verification_method == "domain" ? 1 : 0 | ||
|
||
allow_overwrite = true | ||
type = "MX" | ||
ttl = "600" | ||
name = var.mail_from_domain | ||
zone_id = aws_route53_zone.zone[0].zone_id | ||
records = ["10 inbound-smtp.${data.aws_region.current.name}.amazonaws.com"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
output "email_configuration_set_name" { | ||
value = aws_sesv2_configuration_set.email.configuration_set_name | ||
} | ||
|
||
output "email_identity_arn" { | ||
value = aws_sesv2_email_identity.sender.arn | ||
} | ||
|
||
output "verified_email_identity_arn" { | ||
value = aws_sesv2_email_identity.sender.verified_for_sending_status ? aws_sesv2_email_identity.sender.arn : null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
variable "email_verification_method" { | ||
type = string | ||
description = "The method to use to verify the sender email address" | ||
default = "email" | ||
validation { | ||
condition = can(regex("^(email|domain)$", var.email_verification_method)) | ||
error_message = "email_verification_method must be either 'email' or 'domain'" | ||
} | ||
} | ||
|
||
variable "name" { | ||
type = string | ||
description = "Name of the notifications project/application" | ||
} | ||
|
||
variable "sender_email" { | ||
type = string | ||
description = "Email address to use to send notification emails" | ||
} | ||
|
||
variable "domain_name" { | ||
description = "The domain name to configure SES." | ||
type = string | ||
} | ||
|
||
variable "mail_from_domain" { | ||
type = string | ||
description = "Subdomain (of the route53 zone) which is to be used as MAIL FROM address" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like the email should end in @platform-test-dev.navapbc.com
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah