Add notifications-sms module to support SMS notifications#256
Add notifications-sms module to support SMS notifications#256
Conversation
doshitan
left a comment
There was a problem hiding this comment.
This feels a little complex. Can you update the tech spec with tradeoffs/rationale and future considerations around some of the decisions? It looks like it's been updated a little bit, but a lot of context feels missing.
In particular, the "simulator" stuff doesn't feel very useful. Can we drop it?
|
Updated Tech Specs with: All Considerations; Implementation Options considered. |
| # Allow access to the phone pool created by CloudFormation | ||
| data.aws_cloudformation_stack.sms_config_set_outputs.outputs["PhonePoolArn"], | ||
| # Allow access to the configuration set created by this module | ||
| "arn:aws:sms-voice:*:${data.aws_caller_identity.current.account_id}:configuration-set/${var.name}-config-set" |
There was a problem hiding this comment.
Is it not possible to get this value from the created resource directly?
There was a problem hiding this comment.
Due to the use of CloudFormation (via aws_cloudformation_stack) and the inability to fully control the timing of its execution, I was intermittently encountering the following error:
`Error: Provider produced inconsistent final plan
When expanding the plan for module.notifications_sms[0].aws_cloudformation_stack.sms_config_set to include new values learned so far during apply, provider "registry.terraform.io/hashicorp/aws" produced an invalid new value for .outputs: was known, but now unknown.
`
With the use of Terraform "data" here allows us to better control the timing and sequence of execution for the CloudFormation stack, preventing the provider from re-evaluating stack outputs in an inconsistent state and eliminating the intermittent plan inconsistency error.
b01e304 to
1a68e31
Compare
- Implements PinpointSMSVoiceV2 service resources
- Supports SMS configuration sets and opt-out lists
- Includes VPC endpoint for secure connectivity
- Provides IAM policies for SMS sending permissions
- Supports delivery receipt logging to CloudWatch
…a Phone Number resource
ae7a043 to
e462bbc
Compare
doshitan
left a comment
There was a problem hiding this comment.
A few notes mostly around docs and some cleanup. But I think we are good to create the template PR.
| <form method="post"> | ||
| <div> | ||
| <label for="phone_number">Receiver Phone Number (E.164 format: +1234567890):</label><br> | ||
| <input type="tel" id="phone_number" name="phone_number" |
There was a problem hiding this comment.
I think we can make this a select element populated by the rendering endpoint, with only the predefined simulator numbers by default.
(longer term we should probably better lock down the email testing endpoint as well, we don't really want to be a vehicle to spam people)
There was a problem hiding this comment.
Restricting this to the simulator numbers here will prevent from testing approved phone numbers. I added an extra message to this form, specifying the phone numbers that can be used for testing if using simulator phone number as originator.
| # 1. Creates AWS End User Messaging SMS configuration set | ||
| # 2. Sets up IAM permissions for SMS sending | ||
| # 3. Configures SMS delivery tracking and opt-out management | ||
| enable_sms_notifications = true |
There was a problem hiding this comment.
The default in the template PR should be false.
infra/app/service/notifications.tf
Outdated
| module.notifications_phone_pool_temp[0].phone_pool_id) | ||
| ) : null | ||
|
|
||
| #SMS environment variables for notifications-sms module |
There was a problem hiding this comment.
| #SMS environment variables for notifications-sms module | |
| # SMS environment variables for notifications-sms module |
docs/infra/sms-notifications.md
Outdated
| - **SIMULATOR**: Test numbers for development (immediate approval, limited recipients) | ||
|
|
||
| ### Simulator Phone Numbers | ||
| AWS Allows to use **simulator** phone numbers as originator to send text. This simulator phone numbers are only allowed to send SMS text to: |
There was a problem hiding this comment.
| AWS Allows to use **simulator** phone numbers as originator to send text. This simulator phone numbers are only allowed to send SMS text to: | |
| AWS Allows to use **simulator** phone numbers as originator to send text. This simulator phone numbers are only allowed to send SMS text to: |
docs/infra/sms-notifications.md
Outdated
| sms_number_type = null # Enter SMS Number Type (e.g: 'SHORT_CODE', 'LONG_CODE', 'TOLL_FREE', 'TEN_DLC', 'SIMULATOR') when available; otherwise leave empty to use simulator number type | ||
| } | ||
| ``` | ||
| *__Note:__* if an AWS End User SMS Registration ID is not provided, a simulator phone number will be automatically provisioned which will allow applications to send SMS test to: |
There was a problem hiding this comment.
Can we point to the above Simulator Phone Numbers section rather than duplicating?
docs/infra/sms-notifications.md
Outdated
| *__Note:__* This assumes your AWS End User Messaging SMS Registration has been approved and configured in `infra/<APP_NAME>/app-config/env-config/dev.tf|staging.tf|prod.tf` | ||
| ### 1. Verify Destination Numbers (Sandbox Accounts) | ||
|
|
||
| In sandbox environments, you can only send SMS to up to 10 verified phone numbers. Steps to register destination phone numbers: |
There was a problem hiding this comment.
| In sandbox environments, you can only send SMS to up to 10 verified phone numbers. Steps to register destination phone numbers: | |
| In sandbox environments, you can only send SMS to up to 10 verified phone numbers. Steps to register destination phone numbers: |
docs/infra/sms-notifications.md
Outdated
|
|
||
| ## Requirements | ||
|
|
||
| 1. **AWS End User Messaging SMS Registration**: All provisioned originating phone numbers require a AWS End User Messaging Registration form to be completed in the AWS End User Messaging Service, and approved by the AWS phone carrier. Without an approved Registration, originating phone numbers cannot be provisioned. |
There was a problem hiding this comment.
All provisioned originating phone numbers require a AWS End User Messaging Registration form to be completed
Still makes it sound like every phone number will need a registration form completed at first glance. Can we clarify?
| 1. **AWS End User Messaging SMS Registration**: All provisioned originating phone numbers require a AWS End User Messaging Registration form to be completed in the AWS End User Messaging Service, and approved by the AWS phone carrier. Without an approved Registration, originating phone numbers cannot be provisioned. | |
| 1. **AWS End User Messaging SMS Registration**: All provisioned originating phone numbers require a AWS End User Messaging Registration form to be completed in the AWS End User Messaging Service, and approved by the AWS phone carrier. Without an approved Registration, originating phone numbers cannot be provisioned. |
There was a problem hiding this comment.
Changed the description of the AWS End User Messaging Registration and its purpose and process
- Break notifications-sms module into two components: * notifications-phone-pool: manages phone pools and phone numbers (CloudFormation) * notifications-sms: manages configuration sets and IAM policies (CloudFormation + Terraform) - Add logic to reuse phone pool on temporary environments or create one f none exists - Add logic to create phone pool for production environment - Update documentations
e462bbc to
890c33d
Compare
- Break notifications-sms module into two components:
* notifications-phone-pool: manages phone pools and phone numbers (CloudFormation)
* notifications-sms: manages configuration sets and IAM policies (CloudFormation + Terraform)
- Add logic to reuse phone pool on temporary environments or create one f none exists
- Add logic to create phone pool for production environment
- Update documentations
b1aa6cc to
599b06a
Compare
| } | ||
| ``` | ||
| *__Note:__* if an AWS End User SMS Registration ID is not provided, a simulator phone number will be automatically provisioned. | ||
| ### 3. Deploy SMS notification infrastructure |
There was a problem hiding this comment.
| ### 3. Deploy SMS notification infrastructure | |
| ### 3. Deploy SMS notification infrastructure |
| ## Testing Setup | ||
|
|
||
| *__Note:__* This assumes your AWS End User Messaging SMS Registration has been approved and configured in `infra/<APP_NAME>/app-config/env-config/dev.tf|staging.tf|prod.tf` | ||
| ### 1. Verify Destination Numbers (Sandbox Accounts) |
There was a problem hiding this comment.
| ### 1. Verify Destination Numbers (Sandbox Accounts) | |
| ### 1. Verify Destination Numbers (Sandbox Accounts) |
|
|
||
| ## Testing Setup | ||
|
|
||
| *__Note:__* This assumes your AWS End User Messaging SMS Registration has been approved and configured in `infra/<APP_NAME>/app-config/env-config/dev.tf|staging.tf|prod.tf` |
There was a problem hiding this comment.
The specific environments will vary by project, can we just point back up to the "Configure SMS settings" section?
| - Registration and phone numbers are region-specific | ||
| - You must create separate registrations for each AWS region where you plan to send SMS | ||
| - Phone numbers provisioned in one region cannot be used in other regions | ||
| - Phone numbers must be provisioned by AWS through the End User Messaging service. You cannot bring existing phone numbers from other carriers or services. |
There was a problem hiding this comment.
| - Phone numbers must be provisioned by AWS through the End User Messaging service. You cannot bring existing phone numbers from other carriers or services. | |
| - Phone numbers must be provisioned by AWS through the End User Messaging service. You cannot bring existing phone numbers from other carriers or services. |
|
|
||
| A company or entity must be registered and approved in AWS End User Messaging before using the service for SMS notifications. | ||
|
|
||
| **Important Regional Considerations:** |
There was a problem hiding this comment.
| **Important Regional Considerations:** | |
| **Important Considerations:** |
| - You must create separate registrations for each AWS region where you plan to send SMS | ||
| - Phone numbers provisioned in one region cannot be used in other regions |
There was a problem hiding this comment.
These feel like sub-points/clarifications of the first one, so indent?
| - You must create separate registrations for each AWS region where you plan to send SMS | |
| - Phone numbers provisioned in one region cannot be used in other regions | |
| - You must create separate registrations for each AWS region where you plan to send SMS | |
| - Phone numbers provisioned in one region cannot be used in other regions |
| A company or entity must be registered and approved in AWS End User Messaging before using the service for SMS notifications. | ||
|
|
||
| **Important Regional Considerations:** | ||
| - Registration and phone numbers are region-specific |
There was a problem hiding this comment.
| - Registration and phone numbers are region-specific | |
| - Registrations and phone numbers are region-specific |
| @@ -0,0 +1,48 @@ | |||
| #!/bin/bash | |||
There was a problem hiding this comment.
| #!/bin/bash | |
| #!/usr/bin/env bash |
| REGION="${1}" | ||
|
|
||
| # Get first available pool without filtering by name | ||
| QUERY="Pools[0].{PoolId:PoolId,PoolArn:PoolArn}" | ||
|
|
||
| # List SMS phone pools using AWS CLI with specified region | ||
| pools=$(aws pinpoint-sms-voice-v2 describe-pools \ | ||
| --region "$REGION" \ | ||
| --query "$QUERY" \ | ||
| --output json 2>/dev/null || echo '{}') | ||
|
|
||
| # Check if any pools were found | ||
| if [[ "$pools" == "{}" ]] || [[ "$pools" == "null" ]]; then | ||
| echo '{"pool_id":"","pool_arn":"","exists":"false"}' | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Extract pool details | ||
| pool_id=$(echo "$pools" | jq -r '.PoolId // ""') | ||
| pool_arn=$(echo "$pools" | jq -r '.PoolArn // ""') | ||
|
|
||
| # Validate that we have valid pool data | ||
| if [[ "$pool_id" == "" ]] || [[ "$pool_id" == "null" ]]; then | ||
| echo '{"pool_id":"","pool_arn":"","exists":"false"}' | ||
| else | ||
| echo "{\"pool_id\":\"$pool_id\",\"pool_arn\":\"$pool_arn\",\"exists\":\"true\"}" | ||
| fi No newline at end of file |
There was a problem hiding this comment.
For formatting standards.
| REGION="${1}" | |
| # Get first available pool without filtering by name | |
| QUERY="Pools[0].{PoolId:PoolId,PoolArn:PoolArn}" | |
| # List SMS phone pools using AWS CLI with specified region | |
| pools=$(aws pinpoint-sms-voice-v2 describe-pools \ | |
| --region "$REGION" \ | |
| --query "$QUERY" \ | |
| --output json 2>/dev/null || echo '{}') | |
| # Check if any pools were found | |
| if [[ "$pools" == "{}" ]] || [[ "$pools" == "null" ]]; then | |
| echo '{"pool_id":"","pool_arn":"","exists":"false"}' | |
| exit 0 | |
| fi | |
| # Extract pool details | |
| pool_id=$(echo "$pools" | jq -r '.PoolId // ""') | |
| pool_arn=$(echo "$pools" | jq -r '.PoolArn // ""') | |
| # Validate that we have valid pool data | |
| if [[ "$pool_id" == "" ]] || [[ "$pool_id" == "null" ]]; then | |
| echo '{"pool_id":"","pool_arn":"","exists":"false"}' | |
| else | |
| echo "{\"pool_id\":\"$pool_id\",\"pool_arn\":\"$pool_arn\",\"exists\":\"true\"}" | |
| fi | |
| # Get region parameter (always provided by Terraform) | |
| region="${1}" | |
| # Get first available pool without filtering by name | |
| query="Pools[0].{PoolId:PoolId,PoolArn:PoolArn}" | |
| # List SMS phone pools using AWS CLI with specified region | |
| pools=$(aws pinpoint-sms-voice-v2 describe-pools \ | |
| --region "${region}" \ | |
| --query "${query}" \ | |
| --output json 2>/dev/null || echo '{}') | |
| # Check if any pools were found | |
| if [[ "${pools}" == "{}" ]] || [[ "${pools}" == "null" ]]; then | |
| echo '{"pool_id":"","pool_arn":"","exists":"false"}' | |
| exit 0 | |
| fi | |
| # Extract pool details | |
| pool_id=$(echo "${pools}" | jq -r '.PoolId // ""') | |
| pool_arn=$(echo "${pools}" | jq -r '.PoolArn // ""') | |
| # Validate that we have valid pool data | |
| if [[ -z "${pool_id}" ]] || [[ "${pool_id}" == "null" ]]; then | |
| echo '{"pool_id":"","pool_arn":"","exists":"false"}' | |
| else | |
| echo "{\"pool_id\":\"${pool_id}\",\"pool_arn\":\"${pool_arn}\",\"exists\":\"true\"}" | |
| fi |
There was a problem hiding this comment.
The script looks to only grab the first phone pool in a region? So the name doesn't feel quite right being plural, maybe more find-an-existing-pool.sh?
Ticket
Resolves #976
Changes
Context for reviewers
Testing
Waiting for AWS to approve requested phone number +18665684902.
Preview environment for app-nextjs
Preview environment for app
Preview environment for app-flask
Preview environment for app-rails