i created a terraform that build http api gateway and connect to cognito. everything work well.
i wanted to pull the user_id + email and watch them on dynamodb, so i created a lambda function that do just that and attached it to cognito as a trigger.
i gave all the necessary permmisions through IAM role, and for some reason nothing is happening.(there are no lambda logs errors)
i tried to create another lambda function with the same permissions and with the same code - and when i attach it manually to cognito - it works!
why is it that when i create the lambda function on terraform and attach to it all it need - nothing happened, and when i attach it manually - it works?
please share your thoughts with me
my dynamodb
resource "aws_dynamodb_table" "my_table" {
name = "my-table"
billing_mode = "PAY_PER_REQUEST"
hash_key = "user_id"
attribute {
name = "user_id"
type = "S"
}
}
my cognito
resource "aws_cognito_user_pool" "user_pool" {
name = "user-pool"
username_configuration {
case_sensitive = false
}
alias_attributes = ["email", "preferred_username"]
auto_verified_attributes = ["email"]
password_policy {
minimum_length = 8
temporary_password_validity_days = 7
}
verification_message_template {
default_email_option = "CONFIRM_WITH_CODE"
email_subject = "Account Confirmation"
email_message = "Your confirmation code is {####}"
}
lambda_config {
post_authentication = aws_lambda_function.myfunction.arn
}
schema {
attribute_data_type = "String"
developer_only_attribute = false
mutable = true
name = "email"
required = true
string_attribute_constraints {
min_length = 1
max_length = 256
}
}
}
resource "aws_cognito_user_pool_client" "client" {
name = "demo-app-cognito-client"
user_pool_id = aws_cognito_user_pool.user_pool.id
generate_secret = true
supported_identity_providers = ["COGNITO"]
refresh_token_validity = 90
allowed_oauth_flows = ["code", "implicit"]
allowed_oauth_scopes = ["phone", "email", "openid", "profile", "aws.cognito.signin.user.admin"]
allowed_oauth_flows_user_pool_client = true
prevent_user_existence_errors = "ENABLED"
callback_urls = ["${aws_apigatewayv2_stage.lambda_stage.invoke_url}/"]
explicit_auth_flows = [
"ALLOW_REFRESH_TOKEN_AUTH",
"ALLOW_USER_PASSWORD_AUTH",
"ALLOW_ADMIN_USER_PASSWORD_AUTH"
]
}
resource "aws_cognito_user_pool_domain" "cognito-domain" {
domain = var.domain_prefix
user_pool_id = aws_cognito_user_pool.user_pool.id
}
my IAM
resource "aws_iam_role" "cognito_role" {
name = "cognito_role"
assume_role_policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "",
"Effect" : "Allow",
"Principal" : {
"Service" : "lambda.amazonaws.com"
},
"Action" : "sts:AssumeRole"
}
]
})
}
resource "aws_iam_policy" "cognito_project_policy" {
name = "CognitoProjectPolicy"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action" : [
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface",
"ec2:DescribeInstances",
"ec2:AttachNetworkInterface",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents",
"logs:GetLogEvents",
"logs:FilterLogEvents",
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:UpdateItem"
],
"Resource": "*"
}
]
})
}
# IAM Role Policy Attachment for "cognito-role"
resource "aws_iam_role_policy_attachment" "cognito_project_policy_attach" {
role = aws_iam_role.cognito_role.name
policy_arn = aws_iam_policy.cognito_project_policy.arn
}
# IAM Role Policy Attachment AmazonDynamoDBFullAccess
resource "aws_iam_role_policy_attachment" "AmazonDynamoDBFullAccess" {
role = aws_iam_role.cognito_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"
}
# IAM Role Policy Attachment AmazonCognitoPowerUser
resource "aws_iam_role_policy_attachment" "AmazonCognitoPowerUser" {
role = aws_iam_role.cognito_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonCognitoPowerUser"
}
# IAM Role Policy Attachment AmazonCognitoDeveloperAuthenticatedIdentities
resource "aws_iam_role_policy_attachment" "AmazonCognitoDeveloperAuthenticatedIdentities" {
role = aws_iam_role.cognito_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonCognitoDeveloperAuthenticatedIdentities"
}
my lambda terraform
resource "aws_lambda_function" "myfunction" {
filename = "myfunction.zip"
function_name = "myfunction"
role = aws_iam_role.cognito_role.arn
handler = "myfunction.lambda_handler"
runtime = "python3.10"
timeout = 300
source_code_hash = data.archive_file.post_authentication.output_base64sha256
environment {
variables = {
DYNAMODB_TABLE = aws_dynamodb_table.my_table.name
}
}
vpc_config {
subnet_ids = aws_subnet.private_subnets[*].id
security_group_ids = [aws_security_group.sg.id]
}
}
resource "aws_lambda_permission" "store_user_to_dynamodb_permission" {
statement_id = "AllowExecutionFromCognito"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.myfunction.function_name
principal = "cognito-idp.amazonaws.com"
source_arn = aws_cognito_user_pool.user_pool.arn
}
my lambda function
import json
import boto3
from datetime import datetime
dynamodb = boto3.resource('dynamodb')
def lambda_handler(event, context):
try:
user_name = event['userName']
trigger_source = event['triggerSource']
user_attributes = event['request']['userAttributes']
email = user_attributes.get('email', '')
login_time = datetime.now().isoformat()
status = 'success' if trigger_source == 'PostAuthentication_Authentication' else 'failed'
table = dynamodb.Table('users')
table.put_item(
Item={
'user_id': user_name,
'email': email,
'login_time': login_time,
'status': status
}
)
return event
except KeyError as e:
return {
'errorMessage': str(e),
'errorType': 'KeyError',
'requestId': context.aws_request_id}
i tried to create another lambda function with the same permissions and with the same code - and when i attach it manually to cognito - it works!
What did you attach manually?
Hi Gary. i created another Lambda function with the same code and permissions - AmazonDynamoDBFullAccess AmazonCognitoPowerUser AmazonCognitoDeveloperAuthenticatedIdentities
and added it in the cognito as a trigger(added it to the original lambda that i created on terraform)