AWSTemplateFormatVersion: 2010-09-09 Description: "AWS Cognito example template: CustomSMSSenderWithNewUserPool. This example template creates and configures a Cognito user pool and related resources so that verification and MFA codes are delivered through alternative means instead of through SMS messaging. SMS messaging requires multiple setup steps that can hinder a customer's ability to try out and test Cognito user pools. With this example template, you can avoid the SMS setup and still complete workflows that would send a code to SMS by instead using the CustomSMSSender Lambda trigger to send codes to an SNS topic and deliver them to an email address. This template also defines a CloudFormation custom resource, which links to a helper Lambda function to add or remove the necessary AWS Encryption SDK for the CustomSMSSender Lambda function in the form of a Lambda layer. This example template and approach is strictly for development and testing. For production use the standard setup for SMS is required." Parameters: CognitoCustomSMSSenderTestingSNSTopicSubscriber: Type: String Description: "Provide a valid email address where all SMS messages will be sent instead of through SMS" OptInSNSTopicEncryptionInput: Description: "Choose true if you want to encrypt the SNS topic with a newly created KMS key, or leave it as false to not use encryption" Default: false Type: String AllowedValues: [true, false] Conditions: OptInSNSTopicEncryption: Fn::Equals: [true, Ref: OptInSNSTopicEncryptionInput] OptOutSNSTopicEncryption: Fn::Not: [Condition: OptInSNSTopicEncryption] Outputs: CognitoCustomSMSSenderTestingUserPoolId: Description: "The Id of the Cognito user pool that is created and configured to use a CustomSMSSender Lambda trigger in Cognito Lambda-based SMS messaging testing stack" Value: Ref: CognitoCustomSMSSenderTestingUserPool Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingUserPoolId-${AWS::StackName} CognitoCustomSMSSenderTestingUserPoolARN: Description: "The ARN of the Cognito user pool that is created and configured to use a CustomSMSSender Lambda trigger in the Cognito Lambda-based SMS messaging testing stack" Value: Fn::GetAtt: - CognitoCustomSMSSenderTestingUserPool - Arn Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingUserPoolARN-${AWS::StackName} CognitoCustomSMSSenderTestingUserPoolAppClientId: Description: "The Id of the app client for the Cognito user pool in the Cognito Lambda-based SMS messaging testing stack" Value: Ref: CognitoCustomSMSSenderTestingUserPoolAppClient Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingUserPoolAppClientId-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaRoleARN: Description: "The ARN of the IAM role for the Cognito CustomSMSSender Lambda executions in the Cognito Lambda-based SMS messaging testing stack" Value: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaRole - Arn Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingLambdaRoleARN-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaHelperRoleARN: Description: "The ARN of the IAM role for the Cognito CustomSMSSender helper Lambda executions in the Cognito Lambda-based SMS messaging testing stack" Value: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaHelperRole - Arn Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingLambdaHelperRoleARN-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaName: Description: "Cognito CustomSMSSender Lambda function name in the Cognito Lambda-based SMS messaging testing stack" Value: Ref: CognitoCustomSMSSenderTestingLambda Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingLambdaName-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaARN: Description: "Cognito CustomSMSSender Lambda function ARN in the Cognito Lambda-based SMS messaging testing stack" Value: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambda - Arn Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingLambdaARN-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaHelperName: Description: "Cognito CustomSMSSender helper Lambda function name in the Cognito Lambda-based SMS messaging testing stack" Value: Ref: CognitoCustomSMSSenderTestingLambdaHelper Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingLambdaHelperName-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaHelperARN: Description: "Cognito CustomSMSSender helper Lambda function ARN in the Cognito Lambda-based SMS messaging testing stack" Value: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaHelper - Arn Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingLambdaHelperARN-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaSNSTopicARN: Description: "Cognito CustomSMSSender SNS topic ARN in the Cognito Lambda-based SMS messaging testing stack" Value: Ref: CognitoCustomSMSSenderTestingLambdaSNSTopic Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingLambdaSNSTopicARN-${AWS::StackName} CognitoCustomSMSSenderTestingKMSKeyARN: Description: "Cognito CustomSMSSender KMS key ARN in the Cognito Lambda-based SMS messaging testing stack" Value: Fn::GetAtt: - CognitoCustomSMSSenderTestingKMSKey - Arn Export: Name: Fn::Sub: CognitoCustomSMSSenderTestingKMSKeyARN-${AWS::StackName} Resources: CognitoCustomSMSSenderTestingUserPool: Type: AWS::Cognito::UserPool Properties: UserPoolName: Fn::Sub: CognitoCustomSMSSenderTestingUserPool-${AWS::StackName} AutoVerifiedAttributes: - phone_number MfaConfiguration: "ON" SmsConfiguration: ExternalId: Fn::Sub: CognitoCustomSMSSenderTestingUserPoolSMSExternalId-${AWS::StackName} SnsCallerArn: Fn::GetAtt: - CognitoCustomSMSSenderTestingUserPoolSMSRole - Arn LambdaConfig: CustomSMSSender: LambdaArn: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambda - Arn LambdaVersion: "V1_0" KMSKeyID: Fn::GetAtt: - CognitoCustomSMSSenderTestingKMSKey - Arn UsernameConfiguration: CaseSensitive: true UsernameAttributes: - phone_number CognitoCustomSMSSenderTestingUserPoolAppClient: Type: AWS::Cognito::UserPoolClient Properties: ClientName: CognitoCustomSMSSenderTestingUserPoolAppClient UserPoolId: Ref: CognitoCustomSMSSenderTestingUserPool CognitoCustomSMSSenderTestingUserPoolSMSRole: Type: AWS::IAM::Role Properties: Description: "The IAM role that is required for Cognito user pool SMS configurations in the Cognito Lambda-based SMS messaging testing stack" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: cognito-idp.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - sns:Publish Resource: - "*" PolicyName: ExampleSMSBypassForTesting CognitoCustomSMSSenderTestingLambdaInvocationPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambda - Arn Principal: cognito-idp.amazonaws.com SourceArn: Fn::GetAtt: - CognitoCustomSMSSenderTestingUserPool - Arn CognitoCustomSMSSenderTestingLambdaRole: Type: AWS::IAM::Role Properties: Description: "The IAM role that is created for Lambda function executions in the Cognito user pool Lambda-based SMS messaging testing stack" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com CognitoCustomSMSSenderTestingLambdaPolicyOptInSNSEncryption: Type: AWS::IAM::Policy Condition: OptInSNSTopicEncryption Properties: Roles: - Ref: CognitoCustomSMSSenderTestingLambdaRole PolicyName: Fn::Sub: CognitoCustomSMSSenderTestingLambdaPolicyOptInSNSEncryption-${AWS::StackName} PolicyDocument: Version: 2012-10-17 Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: - Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaLogGroup - Arn - Action: - sns:Publish Effect: Allow Resource: - Ref: CognitoCustomSMSSenderTestingLambdaSNSTopic - Action: - kms:Decrypt Effect: Allow Resource: - Fn::GetAtt: - CognitoCustomSMSSenderTestingKMSKey - Arn - Action: - kms:Encrypt - kms:Decrypt - kms:GenerateDataKey Effect: Allow Resource: - Fn::GetAtt: - CognitoCustomSMSSenderTestingSNSTopicKMSKey - Arn CognitoCustomSMSSenderTestingLambdaPolicyOptOutSNSEncryption: Type: AWS::IAM::Policy Condition: OptOutSNSTopicEncryption Properties: Roles: - Ref: CognitoCustomSMSSenderTestingLambdaRole PolicyName: Fn::Sub: CognitoCustomSMSSenderTestingLambdaPolicyOptOutSNSEncryption-${AWS::StackName} PolicyDocument: Version: 2012-10-17 Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: - Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaLogGroup - Arn - Action: - sns:Publish Effect: Allow Resource: - Ref: CognitoCustomSMSSenderTestingLambdaSNSTopic - Action: - kms:Decrypt Effect: Allow Resource: - Fn::GetAtt: - CognitoCustomSMSSenderTestingKMSKey - Arn CognitoCustomSMSSenderTestingLambda: Type: AWS::Lambda::Function DependsOn: CognitoCustomSMSSenderTestingLambdaLogGroup Properties: Description: "A Lambda function that is created for the Cognito Lambda-based SMS messaging testing stack. This function is executed when the CustomSMSSender Lambda trigger gets triggered" FunctionName: Fn::Sub: CogSMSTesting-${AWS::StackName} Handler: index.handler Role: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaRole - Arn Runtime: python3.9 MemorySize: 512 Timeout: 120 Environment: Variables: KMS_KEY_ARN: Fn::GetAtt: - CognitoCustomSMSSenderTestingKMSKey - Arn SNS_TOPIC_ARN: Ref: CognitoCustomSMSSenderTestingLambdaSNSTopic Code: ZipFile: | import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import DecryptKeyError import base64 import boto3 import botocore import json import logging import os import sys import traceback # Set up logger logger = logging.getLogger() logger.setLevel(logging.INFO) # Initiate environment variables kms_key_arn = os.environ["KMS_KEY_ARN"] sns_topic_arn = os.environ["SNS_TOPIC_ARN"] # Set up an encryption client with an explicit commitment policy: REQUIRE_ENCRYPT_ALLOW_DECRYPT client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) # Create an AWS KMS master key provider kms_kwargs = dict(key_ids=[kms_key_arn]) master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs) # Decrypt the secret code using AWS Encryption SDK def decrypt(ciphertext): try: decrypted_text, encryptor_header = client.decrypt(source=ciphertext, key_provider=master_key_provider) except DecryptKeyError as err: err_info = "Error decrypting with KMS key. Please check if the KMS key with ARN {} exists and the role that the CustomSMSSender Lambda function assumes has the kms:Decrypt permission on the key".format(kms_key_arn) exc_type, exc_value, exc_traceback = sys.exc_info() err_msg = json.dumps({"errorType": exc_type.__name__, "errorMessage": str(exc_value), "errorInfo" : err_info, "stackTrace": traceback.format_exception(exc_type, exc_value, exc_traceback)}) logger.error(err_msg) raise err return decrypted_text.decode() # Lambda function handler def handler(event, context): # Log triggerSource logger.info("triggerSource is " + event["triggerSource"]) # plain_text_code now has the decrypted secret plain_text_code = decrypt(base64.b64decode(event["request"]["code"])) message = "Code from the Cognito Lambda-based SMS messaging testing stack is: " + plain_text_code # Publish to a SNS topic to simulate custom SMS messaging sns_client = boto3.client("sns") try: response = sns_client.publish(TopicArn = sns_topic_arn, Subject = "Cognito Lambda-based SMS messaging testing stack", Message = json.dumps({"default": message}), MessageStructure = "json") logger.info("Published the decrypted code to the SNS topic with ARN: {}".format(sns_topic_arn)) except botocore.exceptions.ClientError as err: err_info = "Error publishing code to the SNS topic." if err.response["Error"]["Code"] == "AuthorizationError": err_info = err_info + " " + "Please check if the role that the CustomSMSSender Lambda function assumes has the sns:Publish permission to the SNS topic with ARN: {}".format(sns_topic_arn) elif err.response["Error"]["Code"] == "InvalidParameter": err_info = err_info + " " + "Please check if request parameters comply with the associated constraints such as SNS topic ARN format and Subject length" elif err.response["Error"]["Code"] == "NotFound": err_info = err_info + " " + "Please check if the desitination SNS topic with ARN: {} exists".format(sns_topic_arn) exc_type, exc_value, exc_traceback = sys.exc_info() err_msg = json.dumps({"errorType": exc_type.__name__, "errorMessage": err.response["Error"]["Message"], "errorCode": err.response["Error"]["Code"], "errorInfo" : err_info, "httpCode" : err.response["ResponseMetadata"]["HTTPStatusCode"], "requestId" : err.response["ResponseMetadata"]["RequestId"], "stackTrace": traceback.format_exception(exc_type, exc_value, exc_traceback)}) logger.error(err_msg) raise err return CognitoCustomSMSSenderTestingLambdaLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: Fn::Sub: /aws/lambda/CogSMSTesting-${AWS::StackName} RetentionInDays: 30 CognitoCustomSMSSenderTestingLambdaHelperResources: Type: Custom::CognitoCustomSMSSenderHelperResources Properties: ServiceToken: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaHelper - Arn LayerName: Fn::Sub: CognitoCustomSMSSenderTestingLambdaLayer-${AWS::StackName} Package: aws-encryption-sdk TargetLambda: Ref: CognitoCustomSMSSenderTestingLambda CognitoCustomSMSSenderTestingLambdaHelperRole: Type: AWS::IAM::Role Properties: Description: "The IAM role that is created for helper Lambda function executions in the Cognito user pool Lambda-based SMS messaging testing stack" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com Policies: - PolicyDocument: Version: 2012-10-17 Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: - Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaHelperLogGroup - Arn - Action: - lambda:PublishLayerVersion - lambda:DeleteLayerVersion - lambda:GetLayerVersion Effect: Allow Resource: - Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:layer:CognitoCustomSMSSenderTestingLambdaLayer-${AWS::StackName}* - Action: - lambda:UpdateFunctionConfiguration Effect: Allow Resource: - Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:CogSMSTesting-${AWS::StackName} PolicyName: Fn::Sub: CognitoCustomSMSSenderTestingLambdaHelperPolicy-${AWS::StackName} CognitoCustomSMSSenderTestingLambdaHelper: Type: AWS::Lambda::Function DependsOn: CognitoCustomSMSSenderTestingLambdaHelperLogGroup Properties: Description: "A Lambda function that adds or removes the AWS Encryption SDK for the CustomSMSSender Lambda function in the Cognito Lambda-based SMS messaging testing stack. It is executed whenever the custom resource is created, updated or deleted" FunctionName: Fn::Sub: CogTestingHelper-${AWS::StackName} Handler: index.handler Role: Fn::GetAtt: - CognitoCustomSMSSenderTestingLambdaHelperRole - Arn Runtime: python3.9 MemorySize: 1024 Timeout: 300 Code: ZipFile: | import boto3 import botocore import cfnresponse import json import logging import pathlib import re import shutil import subprocess from subprocess import CalledProcessError import sys import tempfile import traceback # Exception class CognitoCustomSMSSenderTestingLambdaHelperException(Exception): pass # Set up logger logger = logging.getLogger() logger.setLevel(logging.INFO) # Create a Lambda layer with AWS Encryption SDK def create_layer_version(properties, lambda_client): # Get values from properties layer_name = properties["LayerName"] aws_encryption_sdk = properties["Package"] target_lambda = properties["TargetLambda"] # Create a temporary directory with tempfile.TemporaryDirectory() as temp_dir: lambda_temp_dir = pathlib.Path(temp_dir) temp_lib_python = lambda_temp_dir.joinpath("lib", "python") temp_archive = lambda_temp_dir.joinpath("archive") # Execute pip command to get AWS Encryption SDK try: subprocess.check_call([sys.executable, "-m", "pip", "install", aws_encryption_sdk, "-t", temp_lib_python]) except CalledProcessError as err: err_info = "Error running pip command to install AWS Encryption SDK." exc_type, exc_value, exc_traceback = sys.exc_info() err_msg = json.dumps({"errorType": exc_type.__name__, "errorMessage": str(exc_value), "errorInfo" : err_info, "stackTrace": traceback.format_exception(exc_type, exc_value, exc_traceback)}) logger.error(err_msg) raise err # Create a Lambda layer with AWS Encryption SDK runtimes = ["python%i.%i" % sys.version_info[:2]] archived_file = pathlib.Path(shutil.make_archive(temp_archive, format="zip", root_dir=temp_lib_python.parent)) try: lambda_layer = lambda_client.publish_layer_version(LayerName=layer_name, Description=aws_encryption_sdk, Content={"ZipFile": archived_file.read_bytes()}, CompatibleRuntimes=runtimes) logger.info("Created Cognito CustomSMSSender Lambda layer {}".format(lambda_layer["LayerVersionArn"])) except botocore.exceptions.ClientError as err: err_info = "Error publishing AWS Encryption SDK Lambda layer version." exc_type, exc_value, exc_traceback = sys.exc_info() err_msg = json.dumps({"errorType": exc_type.__name__, "errorMessage": err.response["Error"]["Message"], "errorCode": err.response["Error"]["Code"], "errorInfo" : err_info, "httpCode" : err.response["ResponseMetadata"]["HTTPStatusCode"], "requestId" : err.response["ResponseMetadata"]["RequestId"], "stackTrace": traceback.format_exception(exc_type, exc_value, exc_traceback)}) logger.error(err_msg) raise err # Attach the Lambda layer to the CustomSMSSender Lambda function version_arn = lambda_layer["LayerVersionArn"] try: response = lambda_client.update_function_configuration(FunctionName=target_lambda, Layers=[version_arn]) logger.info("Attached Lambda layer to {}".format(target_lambda)) except botocore.exceptions.ClientError as err: err_info = "Error updating CustomSMSSender Lambda function with AWS Encryption SDK Lambda layer." if err.response["Error"]["Code"] == "ResourceNotFoundException": err_info = err_info + " " + "Please check if Lambda function with ARN: {} exists".format(target_lambda) elif err.response["Error"]["Code"] == "ValidationException": err_info = err_info + " " + "Please check if the parameters in the request are invalid such as Lambda layer ARN format" exc_type, exc_value, exc_traceback = sys.exc_info() err_msg = json.dumps({"errorType": exc_type.__name__, "errorMessage": err.response["Error"]["Message"], "errorCode": err.response["Error"]["Code"], "errorInfo" : err_info, "httpCode" : err.response["ResponseMetadata"]["HTTPStatusCode"], "requestId" : err.response["ResponseMetadata"]["RequestId"], "stackTrace": traceback.format_exception(exc_type, exc_value, exc_traceback)}) logger.error(err_msg) raise err return version_arn # Delete the created Lambda layer def delete_layer_version(version_arn, lambda_client): # Parse Lambda layer Version ARN match = re.fullmatch(r"arn:(?P.*):lambda:(?P.*):(?P\d+):layer:(?P.*):(?P\d+)", version_arn) if not match: raise CognitoCustomSMSSenderTestingLambdaHelperException("Lambda version ARN cannot be parsed while deleting") # Delete the Lambda layer layer_name = match.group("layer_name") version_number = int(match.group("version_number")) try: lambda_client.delete_layer_version(LayerName=layer_name, VersionNumber=version_number) logger.info("Deleted Lambda layer with version ARN {}".format(version_arn)) except botocore.exceptions.ClientError as err: err_info = "Error deleting Lambda layer with version ARN {}.".format(version_arn) exception_type, exception_value, exception_traceback = sys.exc_info() stack_track = traceback.format_exception(exception_type, exception_value, exception_traceback) exc_type, exc_value, exc_traceback = sys.exc_info() err_msg = json.dumps({"errorType": exc_type.__name__, "errorMessage": err.response["Error"]["Message"], "errorCode": err.response["Error"]["Code"], "errorInfo" : err_info, "httpCode" : err.response["ResponseMetadata"]["HTTPStatusCode"], "requestId" : err.response["ResponseMetadata"]["RequestId"], "stackTrace": traceback.format_exception(exc_type, exc_value, exc_traceback)}) logger.error(err_msg) raise err # Lambda handler def handler(event, context): request_type_upper = event["RequestType"].upper() lambda_client = boto3.client("lambda") response_data = {} logger.info("Request type is {}".format(request_type_upper)) try: if request_type_upper == "CREATE": version_arn = create_layer_version(event["ResourceProperties"], lambda_client) cfnresponse.send(event=event, context=context, responseData=response_data, responseStatus=cfnresponse.SUCCESS, physicalResourceId=version_arn) elif request_type_upper == "UPDATE": version_arn = event["PhysicalResourceId"] cfnresponse.send(event=event, context=context, responseData=response_data, responseStatus=cfnresponse.SUCCESS, physicalResourceId=version_arn) elif request_type_upper == "DELETE": version_arn = event["PhysicalResourceId"] delete_layer_version(version_arn, lambda_client) cfnresponse.send(event=event, context=context, responseData=response_data, responseStatus=cfnresponse.SUCCESS, physicalResourceId=version_arn) except Exception as e: logger.error("Internal Failure") cfnresponse.send(event=event, context=context, responseData=response_data, responseStatus=cfnresponse.FAILED, reason=str(e)) CognitoCustomSMSSenderTestingLambdaHelperLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: Fn::Sub: /aws/lambda/CogTestingHelper-${AWS::StackName} RetentionInDays: 30 CognitoCustomSMSSenderTestingLambdaSNSTopic: Type: AWS::SNS::Topic Properties: TopicName: Fn::Sub: CognitoCustomSMSSenderTestingLambdaSNSTopic-${AWS::StackName} Subscription: - Endpoint: Fn::Sub: ${CognitoCustomSMSSenderTestingSNSTopicSubscriber} Protocol: "email" KmsMasterKeyId: Fn::If: - OptInSNSTopicEncryption - Fn::GetAtt: [CognitoCustomSMSSenderTestingSNSTopicKMSKey, Arn] - Ref: AWS::NoValue CognitoCustomSMSSenderTestingKMSKey: Type: AWS::KMS::Key Properties: Description: "The KMS key that is used by the Cognito user pool to encrypt the code and by the CustomSMSSender Lambda function to decrypt the code in the Cognito user pool Lambda-based SMS testing stack." EnableKeyRotation: true PendingWindowInDays: 20 KeyPolicy: Version: 2012-10-17 Id: CognitoCustomSMSSenderTestingKMSKeyPolicy Statement: - Sid: Enable IAM User Permissions Effect: Allow Principal: AWS: - Fn::Sub: arn:aws:iam::${AWS::AccountId}:root Action: kms:* Resource: "*" CognitoCustomSMSSenderTestingSNSTopicKMSKey: Type: AWS::KMS::Key Condition: OptInSNSTopicEncryption Properties: Description: "The KMS key that is used for the testing SNS topic encryption in the Cognito user pool Lambda-based SMS testing stack." EnableKeyRotation: true PendingWindowInDays: 20 KeyPolicy: Version: 2012-10-17 Id: CognitoCustomSMSSenderTestingSNSTopicKMSKeyPolicy Statement: - Sid: Enable IAM User Permissions Effect: Allow Principal: AWS: - Fn::Sub: arn:aws:iam::${AWS::AccountId}:root Action: kms:* Resource: "*"