Introduction to AWS Lambda and Cognito
Understanding AWS Lambda, Cognito Identity Pool, and the validateToken Example
AWS Lambda
AWS Lambda is a serverless compute service that runs code in response to events. It eliminates the need to provision or manage servers, allowing you to focus on your application logic.
- Supports multiple programming languages like Python, Node.js, and Java.
- Triggers can include HTTP requests (via API Gateway), S3 uploads, DynamoDB changes, etc.
- You pay only for the compute time you use.
Cognito Identity Pool
AWS Cognito Identity Pool allows you to grant AWS resource access to users, both authenticated and unauthenticated, using temporary credentials.
- Identity Pools manage user identities and map them to IAM roles.
- Unauthenticated identities are useful for guest access.
- Integrated seamlessly with other AWS services like Lambda, S3, and DynamoDB.
For example, you can configure unauthenticated users to invoke a Lambda function through a role tied to the Cognito Identity Pool.
validateToken Sample
The validateToken
example demonstrates how to:
- Use AWS Cognito Identity Pool to grant unauthenticated access.
- Invoke a Lambda function securely using the AWS SDK.
- Validate tokens and perform checks like route authorization.
Key Components:
- Lambda Function: Implements token validation and page access authorization.
- Cognito Identity Pool: Provides unauthenticated access permissions.
- AWS SDK: Enables Lambda invocation from a browser or application.
Example workflow:
User -> AWS Cognito Identity Pool -> Temporary IAM Role -> Lambda Function
Using this setup, the validateToken
Lambda function validates tokens and returns
authorization responses for requested resources.
Objective
Below are the objective targeted
- Capturing steps required for setting up aws Lambda function
- Capturing steps required for setting up Cognito Identity Pool for unauthenticated access
- Capturing script required for invoking Lambda function using AWS JS SDK
Lambda Function Code
The following is the source code of the `validateToken` Lambda function:
// index.mjs
const TOKEN_PAGE_MAPPING = {
'token123': 'dashboard',
'token456': 'profile',
'token789': 'settings',
'tokenABC': 'reports'
};
const createResponse = (statusCode, body) => ({
statusCode,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify(body)
});
export const handler = async (event) => {
try {
const authHeader = event.headers?.Authorization;
if (!authHeader?.startsWith('Bearer ')) {
return createResponse(401, { error: 'No token provided or invalid format' });
}
const token = authHeader.substring(7);
const requestedPage = event.queryStringParameters?.page;
if (!requestedPage) {
return createResponse(400, { error: 'Page parameter is required' });
}
const allowedPage = TOKEN_PAGE_MAPPING[token];
if (!allowedPage) {
return createResponse(401, { error: 'Invalid token' });
}
if (allowedPage !== requestedPage) {
return createResponse(403, { error: `Token not authorized for page: ${requestedPage}` });
}
return createResponse(200, {
status: 'success',
message: `Token valid for page: ${allowedPage}`,
page: allowedPage,
timestamp: new Date().toISOString()
});
} catch (error) {
console.error('Validation error:', error);
return createResponse(500, { error: 'Internal server error', message: error.message });
}
};
Shell Script Source Code
1. upload-aws-lambda.sh
#!/bin/bash
# upload-aws-lambda.sh
LAMBDA_FUNCTION_NAME="$1"
ZIP_FILE_NAME="$LAMBDA_FUNCTION_NAME.zip"
if [ -f "$ZIP_FILE_NAME" ]; then
echo "Removing existing ZIP file: $ZIP_FILE_NAME"
rm -f "$ZIP_FILE_NAME"
fi
(cd $LAMBDA_FUNCTION_NAME && zip -r ../$LAMBDA_FUNCTION_NAME.zip ./*)
aws lambda update-function-code \
--function-name "$LAMBDA_FUNCTION_NAME" \
--zip-file "fileb://$ZIP_FILE_NAME"
rm -f "$ZIP_FILE_NAME"
2. download-aws-lambda.sh
#!/bin/bash
# download-aws-lambda.sh
LAMBDA_FUNCTION_NAME="$1"
OUTPUT_ZIP_FILE="$LAMBDA_FUNCTION_NAME.zip"
DOWNLOAD_URL=$(aws lambda get-function --function-name "$LAMBDA_FUNCTION_NAME" --query "Code.Location" --output text)
curl -o "$OUTPUT_ZIP_FILE" "$DOWNLOAD_URL"
mkdir -p $LAMBDA_FUNCTION_NAME
unzip $OUTPUT_ZIP_FILE -d $LAMBDA_FUNCTION_NAME
rm $OUTPUT_ZIP_FILE
3. Upload the Function
#!/bin/bash
LAMBDA_FUNCTION_NAME="validateToken"
echo "Uploading function..."
./upload-aws-lambda.sh "$LAMBDA_FUNCTION_NAME"
4. Download the Function
#!/bin/bash
LAMBDA_FUNCTION_NAME="validateToken"
echo "Downloading function..."
./download-aws-lambda.sh "$LAMBDA_FUNCTION_NAME"
Steps to Deploy
- Save the Lambda function code as `index.mjs`.
- Upload the function using
upload-aws-lambda.sh
. - Download the function using
download-aws-lambda.sh
for local development.
validateToken Lambda Function Setup
This section explains the creation, deployment, and testing of the `validateToken` Lambda function.
Test Lambda Function
#!/bin/bash
# test-aws-lambda.sh
LAMBDA_FUNCTION_NAME="$1"
REQUEST_FILE="test/$LAMBDA_FUNCTION_NAME/request.json"
RESPONSE_FILE="test/$LAMBDA_FUNCTION_NAME/response.json"
aws lambda invoke \
--function-name "$LAMBDA_FUNCTION_NAME" \
--cli-binary-format raw-in-base64-out \
--payload file://"$REQUEST_FILE" \
"$RESPONSE_FILE"
cat "$RESPONSE_FILE"
Testing with Request Payload
The following is the test request payload:
{
"headers": {
"Authorization": "Bearer token123"
},
"queryStringParameters": {
"page": "dashboard"
}
}
Steps to Test
- Test the function using
test-aws-lambda.sh
.
Setting Up AWS Guest Access
A step-by-step guide to configure unauthenticated access using Cognito Identity Pool
Overview
This guide walks through setting up guest access using AWS Cognito Identity Pool. We'll create:
- A Cognito Identity Pool
- An IAM Role for unauthenticated access
- A policy allowing Lambda function invocation
- Role attachment to the Identity Pool
Setup Script
Save the following script as setup-guest-access.sh
:
#!/bin/bash
# Create Identity Pool
aws cognito-identity create-identity-pool \
--identity-pool-name "GuestAccessPool" \
--allow-unauthenticated-identities \
--allow-classic-flow
# Store the Identity Pool ID
IDENTITY_POOL_ID=$(aws cognito-identity create-identity-pool \
--identity-pool-name "GuestAccessPool" \
--allow-unauthenticated-identities \
--allow-classic-flow \
--query 'IdentityPoolId' \
--output text)
mkdir temp
# Create trust policy JSON
cat > temp/trust-policy.json << EOL
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "${IDENTITY_POOL_ID}"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "unauthenticated"
}
}
}
]
}
EOL
# Create the IAM role
aws iam create-role \
--role-name CognitoUnAuthRole-001 \
--assume-role-policy-document file://temp/trust-policy.json
# Store the Role ARN
ROLE_ARN=$(aws iam create-role \
--role-name CognitoUnAuthRole-001 \
--assume-role-policy-document file://temp/trust-policy.json \
--query 'Role.Arn' \
--output text)
# Create Lambda invoke policy
cat > temp/lambda-policy.json << EOL
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken"
}
]
}
EOL
# Attach policy to role
aws iam put-role-policy \
--role-name CognitoUnAuthRole \
--policy-name LambdaInvokePolicy \
--policy-document file://temp/lambda-policy.json
# Create roles configuration
cat > temp/roles.json << EOL
{
"unauthenticated": "${ROLE_ARN}"
}
EOL
# Attach role to Identity Pool
aws cognito-identity set-identity-pool-roles \
--identity-pool-id ${IDENTITY_POOL_ID} \
--roles file://temp/roles.json
# Clean up temporary files
rm -rf temp
Step-by-Step Instructions
1. Prepare the Environment
- Ensure AWS CLI is installed and configured
- Save the script as
setup-guest-access.sh
- Make the script executable:
chmod +x setup-guest-access.sh
2. Run the Setup Script
./setup-guest-access.sh
3. Verify the Setup
Check the created resources:
# List Identity Pools
aws cognito-identity list-identity-pools --max-results 10
# Check IAM role
aws iam get-role --role-name CognitoUnAuthRole-001
# Verify role policy
aws iam get-role-policy \
--role-name CognitoUnAuthRole-001 \
--policy-name LambdaInvokePolicy
Script Components Explained
Identity Pool Creation
- Creates a new Identity Pool named "GuestAccessPool"
- Enables unauthenticated access
- Allows classic flow
IAM Role Setup
- Creates a role for unauthenticated users
- Sets up trust relationship with Cognito
- Configures conditions for the Identity Pool
Lambda Access Policy
- Creates a policy allowing Lambda function invocation
- Attaches policy to the IAM role
Role Association
- Associates the IAM role with the Identity Pool
- Configures role for unauthenticated access
Important Notes
- The script creates temporary files in a 'temp' directory which is cleaned up after execution
- Ensure you have sufficient IAM permissions to create these resources
- The Lambda function ARN in the policy should be updated to match your function
- Role names must be unique within your AWS account
Using AWS JS SDK to Invoke validateToken
Below is the complete code for invoking a Lambda function using the AWS JS SDK.
invoke-aws.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lambda Invoker</title>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1048.0.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
<style>
body {
background-color: #f3f4f6;
}
.card {
background: white;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.input-field {
width: 100%;
padding: 0.75rem;
border: 1px solid #e5e7eb;
border-radius: 6px;
margin-top: 0.5rem;
font-size: 0.975rem;
transition: border-color 0.15s ease-in-out;
}
.input-field:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.button {
background-color: #3b82f6;
color: white;
padding: 0.75rem 1.5rem;
border-radius: 6px;
font-weight: 500;
transition: background-color 0.15s ease-in-out;
}
.button:hover {
background-color: #2563eb;
}
.success {
background-color: #ecfdf5;
border: 1px solid #10b981;
}
.error {
background-color: #fef2f2;
border: 1px solid #ef4444;
}
</style>
</head>
<body class="min-h-screen py-8">
<div class="max-w-2xl mx-auto px-4">
<div class="card p-6 mb-8">
<h2 class="text-2xl font-bold text-gray-800 mb-6">AWS Lambda Invoker - validateToken</h2>
<div>
<div>
<label for="token" class="block text-sm font-medium text-gray-700">Token</label>
<input type="text" id="token" class="input-field" placeholder="Enter your token">
</div>
<div>
<label for="page" class="block text-sm font-medium text-gray-700">Page</label>
<select id="page" class="input-field">
<option value="dashboard">Dashboard</option>
<option value="profile">Profile</option>
<option value="settings">Settings</option>
</select>
</div>
<button onclick="invokeLambda()" class="button w-full">Invoke validateToken</button>
</div>
</div>
<div id="result" class="card p-6 hidden"></div>
</div>
<script>
const REGION = 'ap-southeast-2';
const IDENTITY_POOL_ID = 'ap-southeast-2:xxxxxxxx-xxxxxxxxx-xxxx-xxxxxxxxxxxx';
const FUNCTION_NAME = 'validateToken';
AWS.config.region = REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: IDENTITY_POOL_ID
});
const lambda = new AWS.Lambda();
async function invokeLambda() {
const token = document.getElementById('token').value;
const page = document.getElementById('page').value;
const resultDiv = document.getElementById('result');
resultDiv.classList.remove('hidden');
resultDiv.classList.remove('success', 'error');
resultDiv.innerHTML = `
<div class="flex items-center justify-center">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
<span class="ml-3 text-gray-600">Processing...</span>
</div>
`;
const payload = {
headers: {
Authorization: `Bearer ${token}`
},
queryStringParameters: {
page: page
}
};
const params = {
FunctionName: FUNCTION_NAME,
InvocationType: 'RequestResponse',
Payload: JSON.stringify(payload)
};
try {
const response = await lambda.invoke(params).promise();
const result = JSON.parse(response.Payload);
if (result.statusCode === 200) {
resultDiv.classList.add('success');
resultDiv.innerHTML = `
<h4 class="text-lg font-semibold text-green-800 mb-3">Success</h4>
<pre class="bg-white p-4 rounded-lg overflow-x-auto text-sm">${JSON.stringify(JSON.parse(result.body), null, 2)}</pre>
`;
} else {
resultDiv.classList.add('error');
resultDiv.innerHTML = `
<h4 class="text-lg font-semibold text-red-800 mb-3">Error</h4>
<pre class="bg-white p-4 rounded-lg overflow-x-auto text-sm">${JSON.stringify(JSON.parse(result.body), null, 2)}</pre>
`;
}
} catch (error) {
resultDiv.classList.add('error');
resultDiv.innerHTML = `
<h4 class="text-lg font-semibold text-red-800 mb-3">Error</h4>
<p class="text-red-600">${error.message}</p>
`;
console.error('Lambda invocation error:', error);
}
}
</script>
</body>
</html>
Tested Results
1. Initial Test - Before setting up identity pool.

2. Invalid Token - Token not recognized by the Lambda function.

3. Not Authorized - Token provided does not grant access to the requested page.

4. Successful Invocation - Token is valid and authorized for the page.

AWS Identity Pool Stack Setup
Step-by-step setup for Cognito Identity Pool using CloudFormation.
Overview
This guide shows how to use AWS CloudFormation to set up an Identity Pool and configure IAM roles to allow Lambda function invocation.
CloudFormation allows you to automate the creation and management of AWS resources using templates. By defining your infrastructure as code, CloudFormation ensures consistency, reduces manual effort, and enables repeatable deployments.
CloudFormation Template
The CloudFormation template defines the Identity Pool, IAM roles, and a policy to allow Lambda invocation.
AWSTemplateFormatVersion: '2010-09-09'
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudFormation template for creating an AWS Cognito Identity Pool with IAM Role'
Parameters:
IdentityPoolName:
Type: String
Description: Name of the Identity Pool
Default: GuestAccessPool
MinLength: 1
MaxLength: 128
AllowedPattern: '[a-zA-Z0-9_. -]+'
LambdaFunctionArn:
Type: String
Description: ARN of the Lambda function to invoke
Default: arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken
AllowedPattern: '^arn:aws:lambda:[a-z0-9-]+:[0-9]{12}:function:.+$'
ConstraintDescription: Must be a valid Lambda function ARN
Resources:
CognitoIdentityPool:
Type: 'AWS::Cognito::IdentityPool'
Properties:
IdentityPoolName: !Ref IdentityPoolName
AllowUnauthenticatedIdentities: true
AllowClassicFlow: true
IdentityPoolTags: []
# IAM Role for unauthenticated users
CognitoUnAuthRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
'cognito-identity.amazonaws.com:aud': !Ref CognitoIdentityPool
'ForAnyValue:StringLike':
'cognito-identity.amazonaws.com:amr': unauthenticated
# Lambda invoke policy for the role
LambdaInvokePolicy:
Type: 'AWS::IAM::Policy'
Properties:
PolicyName: LambdaInvokePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: lambda:InvokeFunction
Resource: !Ref LambdaFunctionArn
Roles:
- !Ref CognitoUnAuthRole
# Attach the role to the Identity Pool
IdentityPoolRoleAttachment:
Type: 'AWS::Cognito::IdentityPoolRoleAttachment'
Properties:
IdentityPoolId: !Ref CognitoIdentityPool
Roles:
unauthenticated: !GetAtt CognitoUnAuthRole.Arn
Outputs:
IdentityPoolId:
Description: ID of the created Identity Pool
Value: !Ref CognitoIdentityPool
UnAuthRoleArn:
Description: ARN of the unauthenticated IAM Role
Value: !GetAtt CognitoUnAuthRole.Arn
Parameters File
The parameters file provides the dynamic inputs for the CloudFormation stack.
[
{
"ParameterKey": "IdentityPoolName",
"ParameterValue": "MyPublicAccess"
},
{
"ParameterKey": "LambdaFunctionArn",
"ParameterValue": "arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken"
}
]
Stack Creation Script
Execute the following script to deploy the CloudFormation stack:
#!/bin/bash
aws cloudformation create-stack \
--stack-name my-public-identity-pool \
--template-body file://validateToken/identity-pool-stack-config.yaml \
--capabilities CAPABILITY_IAM \
--parameters file://validateToken/identity-pool-stack-params.json
aws cloudformation describe-stacks --stack-name my-public-identity-pool
aws cognito-identity list-identity-pools --max-results 10
Execution Results
Once the script runs successfully, verify the following:
- The Identity Pool with name
MyPublicAccess
is created. - An IAM role is created and attached to the Identity Pool.
- Lambda function permissions are applied to the role.
Complete Guide: Understanding and Implementing Terraform with AWS Lambda
A comprehensive guide to understanding Terraform and implementing it with AWS Lambda.
Part 1: Understanding Terraform
What is Terraform?
Terraform is an Infrastructure as Code (IaC) tool that allows you to define and provide data center infrastructure using a declarative configuration language. Instead of manually setting up cloud resources through a web interface, you define your infrastructure in code.
When to Use Terraform
- Infrastructure Version Control: Track changes to your infrastructure just like source code using Git
- Consistent Environments: Create identical development, staging, and production environments
- Multi-Cloud Deployment: Manage resources across multiple cloud providers with the same workflow
- Automated Infrastructure: Automate the creation and updates of infrastructure as part of CI/CD pipelines
Part 2: Installation and Setup
Installing Terraform
Run the following commands to install Terraform on Ubuntu:
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt update
sudo apt install terraform
AWS Configuration
Terraform will use your existing AWS configuration files:
- Credentials file:
~/.aws/credentials
- Configuration file:
~/.aws/config
Part 3: Implementation
variables.tf
variable "identity_pool_name" {
default = "MyPublicAccess"
}
main.tf
provider "aws" {
region = "ap-southeast-2"
}
resource "aws_iam_role" "lambda_validate_token_role" {
name = "lambda_validate_token_role"
description = "IAM role for validateToken Lambda function to execute and write logs to CloudWatch"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
# Add basic Lambda execution permissions
resource "aws_iam_role_policy_attachment" "lambda_basic" {
role = aws_iam_role.lambda_validate_token_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
# AWS Lambda Function
resource "aws_lambda_function" "validate_token" {
function_name = "validateToken"
runtime = "nodejs18.x"
role = aws_iam_role.lambda_validate_token_role.arn # Updated role
handler = "index.handler"
filename = "function.zip"
source_code_hash = filebase64sha256("function.zip")
depends_on = [
aws_iam_role_policy_attachment.lambda_basic
]
}
# Cognito Identity Pool
resource "aws_cognito_identity_pool" "identity_pool" {
identity_pool_name = var.identity_pool_name
allow_unauthenticated_identities = true
allow_classic_flow = true
}
# IAM Role for unauthenticated users
resource "aws_iam_role" "cognito_unauth_role" {
name = "CognitoUnAuthRole"
description = "IAM role for unauthenticated Cognito users to invoke Lambda validation function"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = "cognito-identity.amazonaws.com"
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"cognito-identity.amazonaws.com:aud" = aws_cognito_identity_pool.identity_pool.id
}
"ForAnyValue:StringLike" = {
"cognito-identity.amazonaws.com:amr" = "unauthenticated"
}
}
}
]
})
}
# IAM Policy for Lambda invocation
resource "aws_iam_policy" "lambda_invoke_policy" {
name = "LambdaInvokePolicy"
description = "Allows invocation of validateToken Lambda function"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = "lambda:InvokeFunction"
Resource = aws_lambda_function.validate_token.arn
}
]
})
depends_on = [
aws_lambda_function.validate_token
]
}
# Attach policy to IAM role
resource "aws_iam_role_policy_attachment" "lambda_invoke_attachment" {
role = aws_iam_role.cognito_unauth_role.name
policy_arn = aws_iam_policy.lambda_invoke_policy.arn
}
# Attach the role to the Identity Pool
resource "aws_cognito_identity_pool_roles_attachment" "identity_pool_roles" {
identity_pool_id = aws_cognito_identity_pool.identity_pool.id
roles = {
"unauthenticated" = aws_iam_role.cognito_unauth_role.arn
}
}
Part 4: Terraform Commands and Outputs
terraform plan
Preview the changes Terraform will make:
$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_cognito_identity_pool.identity_pool will be created
+ resource "aws_cognito_identity_pool" "identity_pool" {
+ allow_classic_flow = true
+ allow_unauthenticated_identities = true
+ arn = (known after apply)
+ id = (known after apply)
+ identity_pool_name = "MyPublicAccess"
+ tags_all = (known after apply)
}
# aws_cognito_identity_pool_roles_attachment.identity_pool_roles will be created
+ resource "aws_cognito_identity_pool_roles_attachment" "identity_pool_roles" {
+ id = (known after apply)
+ identity_pool_id = (known after apply)
+ roles = (known after apply)
}
# aws_iam_policy.lambda_invoke_policy will be created
+ resource "aws_iam_policy" "lambda_invoke_policy" {
+ arn = (known after apply)
+ attachment_count = (known after apply)
+ description = "Allows invocation of validateToken Lambda function"
+ id = (known after apply)
+ name = "LambdaInvokePolicy"
+ name_prefix = (known after apply)
+ path = "/"
+ policy = (known after apply)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# aws_iam_role.cognito_unauth_role will be created
+ resource "aws_iam_role" "cognito_unauth_role" {
+ arn = (known after apply)
+ assume_role_policy = (known after apply)
+ create_date = (known after apply)
+ description = "IAM role for unauthenticated Cognito users to invoke Lambda validation function"
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "CognitoUnAuthRole"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
+ inline_policy (known after apply)
}
# aws_iam_role.lambda_validate_token_role will be created
+ resource "aws_iam_role" "lambda_validate_token_role" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "lambda.amazonaws.com"
}
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ description = "IAM role for validateToken Lambda function to execute and write logs to CloudWatch"
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "lambda_validate_token_role"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
+ inline_policy (known after apply)
}
# aws_iam_role_policy_attachment.lambda_basic will be created
+ resource "aws_iam_role_policy_attachment" "lambda_basic" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
+ role = "lambda_validate_token_role"
}
# aws_iam_role_policy_attachment.lambda_invoke_attachment will be created
+ resource "aws_iam_role_policy_attachment" "lambda_invoke_attachment" {
+ id = (known after apply)
+ policy_arn = (known after apply)
+ role = "CognitoUnAuthRole"
}
# aws_lambda_function.validate_token will be created
+ resource "aws_lambda_function" "validate_token" {
+ architectures = (known after apply)
+ arn = (known after apply)
+ code_sha256 = (known after apply)
+ filename = "function.zip"
+ function_name = "validateToken"
+ handler = "index.handler"
+ id = (known after apply)
+ invoke_arn = (known after apply)
+ last_modified = (known after apply)
+ memory_size = 128
+ package_type = "Zip"
+ publish = false
+ qualified_arn = (known after apply)
+ qualified_invoke_arn = (known after apply)
+ reserved_concurrent_executions = -1
+ role = (known after apply)
+ runtime = "nodejs18.x"
+ signing_job_arn = (known after apply)
+ signing_profile_version_arn = (known after apply)
+ skip_destroy = false
+ source_code_hash = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ source_code_size = (known after apply)
+ tags_all = (known after apply)
+ timeout = 3
+ version = (known after apply)
+ ephemeral_storage (known after apply)
+ logging_config (known after apply)
+ tracing_config (known after apply)
}
Plan: 8 to add, 0 to change, 0 to destroy.
terraform apply
Apply the planned changes:
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_cognito_identity_pool.identity_pool will be created
+ resource "aws_cognito_identity_pool" "identity_pool" {
+ allow_classic_flow = true
+ allow_unauthenticated_identities = true
+ arn = (known after apply)
+ id = (known after apply)
+ identity_pool_name = "MyPublicAccess"
+ tags_all = (known after apply)
}
# aws_cognito_identity_pool_roles_attachment.identity_pool_roles will be created
+ resource "aws_cognito_identity_pool_roles_attachment" "identity_pool_roles" {
+ id = (known after apply)
+ identity_pool_id = (known after apply)
+ roles = (known after apply)
}
# aws_iam_policy.lambda_invoke_policy will be created
+ resource "aws_iam_policy" "lambda_invoke_policy" {
+ arn = (known after apply)
+ attachment_count = (known after apply)
+ description = "Allows invocation of validateToken Lambda function"
+ id = (known after apply)
+ name = "LambdaInvokePolicy"
+ name_prefix = (known after apply)
+ path = "/"
+ policy = (known after apply)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# aws_iam_role.cognito_unauth_role will be created
+ resource "aws_iam_role" "cognito_unauth_role" {
+ arn = (known after apply)
+ assume_role_policy = (known after apply)
+ create_date = (known after apply)
+ description = "IAM role for unauthenticated Cognito users to invoke Lambda validation function"
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "CognitoUnAuthRole"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
+ inline_policy (known after apply)
}
# aws_iam_role.lambda_validate_token_role will be created
+ resource "aws_iam_role" "lambda_validate_token_role" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "lambda.amazonaws.com"
}
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ description = "IAM role for validateToken Lambda function to execute and write logs to CloudWatch"
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "lambda_validate_token_role"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
+ inline_policy (known after apply)
}
# aws_iam_role_policy_attachment.lambda_basic will be created
+ resource "aws_iam_role_policy_attachment" "lambda_basic" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
+ role = "lambda_validate_token_role"
}
# aws_iam_role_policy_attachment.lambda_invoke_attachment will be created
+ resource "aws_iam_role_policy_attachment" "lambda_invoke_attachment" {
+ id = (known after apply)
+ policy_arn = (known after apply)
+ role = "CognitoUnAuthRole"
}
# aws_lambda_function.validate_token will be created
+ resource "aws_lambda_function" "validate_token" {
+ architectures = (known after apply)
+ arn = (known after apply)
+ code_sha256 = (known after apply)
+ filename = "function.zip"
+ function_name = "validateToken"
+ handler = "index.handler"
+ id = (known after apply)
+ invoke_arn = (known after apply)
+ last_modified = (known after apply)
+ memory_size = 128
+ package_type = "Zip"
+ publish = false
+ qualified_arn = (known after apply)
+ qualified_invoke_arn = (known after apply)
+ reserved_concurrent_executions = -1
+ role = (known after apply)
+ runtime = "nodejs18.x"
+ signing_job_arn = (known after apply)
+ signing_profile_version_arn = (known after apply)
+ skip_destroy = false
+ source_code_hash = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ source_code_size = (known after apply)
+ tags_all = (known after apply)
+ timeout = 3
+ version = (known after apply)
+ ephemeral_storage (known after apply)
+ logging_config (known after apply)
+ tracing_config (known after apply)
}
Plan: 8 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_iam_role.lambda_validate_token_role: Creating...
aws_cognito_identity_pool.identity_pool: Creating...
aws_cognito_identity_pool.identity_pool: Creation complete after 0s [id=ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
aws_iam_role.cognito_unauth_role: Creating...
aws_iam_role.lambda_validate_token_role: Creation complete after 2s [id=lambda_validate_token_role]
aws_iam_role_policy_attachment.lambda_basic: Creating...
aws_iam_role.cognito_unauth_role: Creation complete after 2s [id=CognitoUnAuthRole]
aws_cognito_identity_pool_roles_attachment.identity_pool_roles: Creating...
aws_cognito_identity_pool_roles_attachment.identity_pool_roles: Creation complete after 0s [id=ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
aws_iam_role_policy_attachment.lambda_basic: Creation complete after 1s [id=lambda_validate_token_role-xxxxxxxxxxxxxxxxxxxx]
aws_lambda_function.validate_token: Creating...
aws_lambda_function.validate_token: Still creating... [9s elapsed]
aws_lambda_function.validate_token: Creation complete after 14s [id=validateToken]
aws_iam_policy.lambda_invoke_policy: Creating...
aws_iam_policy.lambda_invoke_policy: Creation complete after 1s [id=arn:aws:iam::xxxxxxxxxxxx:policy/LambdaInvokePolicy]
aws_iam_role_policy_attachment.lambda_invoke_attachment: Creating...
aws_iam_role_policy_attachment.lambda_invoke_attachment: Creation complete after 1s [id=CognitoUnAuthRole-xxxxxxxxxxxxxxxxxxxx]
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
terraform destroy
Remove all resources created by Terraform:
$ terraform destroy
aws_iam_role.lambda_validate_token_role: Refreshing state... [id=lambda_validate_token_role]
aws_cognito_identity_pool.identity_pool: Refreshing state... [id=ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
aws_iam_policy.lambda_invoke_policy: Refreshing state... [id=arn:aws:iam::xxxxxxxxxxxx:policy/LambdaInvokePolicy]
aws_iam_role.cognito_unauth_role: Refreshing state... [id=CognitoUnAuthRole]
aws_iam_role_policy_attachment.lambda_basic: Refreshing state... [id=lambda_validate_token_role-xxxxxxxxxxxxxxxxxxxx]
aws_iam_role_policy_attachment.lambda_invoke_attachment: Refreshing state... [id=CognitoUnAuthRole-xxxxxxxxxxxxxxxxxxxx]
aws_cognito_identity_pool_roles_attachment.identity_pool_roles: Refreshing state... [id=ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
aws_lambda_function.validate_token: Refreshing state... [id=validateToken]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# aws_cognito_identity_pool.identity_pool will be destroyed
- resource "aws_cognito_identity_pool" "identity_pool" {
- allow_classic_flow = true -> null
- allow_unauthenticated_identities = true -> null
- arn = "arn:aws:cognito-identity:ap-southeast-2:xxxxxxxxxxxx:identitypool/ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -> null
- id = "ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -> null
- identity_pool_name = "MyPublicAccess" -> null
- openid_connect_provider_arns = [] -> null
- saml_provider_arns = [] -> null
- supported_login_providers = {} -> null
- tags = {} -> null
- tags_all = {} -> null
# (1 unchanged attribute hidden)
}
# aws_cognito_identity_pool_roles_attachment.identity_pool_roles will be destroyed
- resource "aws_cognito_identity_pool_roles_attachment" "identity_pool_roles" {
- id = "ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -> null
- identity_pool_id = "ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -> null
- roles = {
- "unauthenticated" = "arn:aws:iam::xxxxxxxxxxxx:role/CognitoUnAuthRole"
} -> null
}
# aws_iam_policy.lambda_invoke_policy will be destroyed
- resource "aws_iam_policy" "lambda_invoke_policy" {
- arn = "arn:aws:iam::xxxxxxxxxxxx:policy/LambdaInvokePolicy" -> null
- attachment_count = 1 -> null
- id = "arn:aws:iam::xxxxxxxxxxxx:policy/LambdaInvokePolicy" -> null
- name = "LambdaInvokePolicy" -> null
- path = "/" -> null
- policy = jsonencode(
{
- Statement = [
- {
- Action = "lambda:InvokeFunction"
- Effect = "Allow"
- Resource = "arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken"
},
]
- Version = "2012-10-17"
}
) -> null
- policy_id = "xxxxxxxxxxxxxxxxxxxxx" -> null
- tags = {} -> null
- tags_all = {} -> null
# (2 unchanged attributes hidden)
}
# aws_iam_role.cognito_unauth_role will be destroyed
- resource "aws_iam_role" "cognito_unauth_role" {
- arn = "arn:aws:iam::xxxxxxxxxxxx:role/CognitoUnAuthRole" -> null
- assume_role_policy = jsonencode(
{
- Statement = [
- {
- Action = "sts:AssumeRoleWithWebIdentity"
- Condition = {
- "ForAnyValue:StringLike" = {
- "cognito-identity.amazonaws.com:amr" = "unauthenticated"
}
- StringEquals = {
- "cognito-identity.amazonaws.com:aud" = "ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
- Effect = "Allow"
- Principal = {
- Federated = "cognito-identity.amazonaws.com"
}
},
]
- Version = "2012-10-17"
}
) -> null
- create_date = "2024-12-24T10:55:26Z" -> null
- force_detach_policies = false -> null
- id = "CognitoUnAuthRole" -> null
- managed_policy_arns = [
- "arn:aws:iam::xxxxxxxxxxxx:policy/LambdaInvokePolicy",
] -> null
- max_session_duration = 3600 -> null
- name = "CognitoUnAuthRole" -> null
- path = "/" -> null
- tags = {} -> null
- tags_all = {} -> null
- unique_id = "xxxxxxxxxxxxxxxxxxxx" -> null
# (3 unchanged attributes hidden)
}
# aws_iam_role.lambda_validate_token_role will be destroyed
- resource "aws_iam_role" "lambda_validate_token_role" {
- arn = "arn:aws:iam::xxxxxxxxxxxx:role/lambda_validate_token_role" -> null
- assume_role_policy = jsonencode(
{
- Statement = [
- {
- Action = "sts:AssumeRole"
- Effect = "Allow"
- Principal = {
- Service = "lambda.amazonaws.com"
}
},
]
- Version = "2012-10-17"
}
) -> null
- create_date = "2024-12-24T11:36:59Z" -> null
- force_detach_policies = false -> null
- id = "lambda_validate_token_role" -> null
- managed_policy_arns = [
- "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
] -> null
- max_session_duration = 3600 -> null
- name = "lambda_validate_token_role" -> null
- path = "/" -> null
- tags = {} -> null
- tags_all = {} -> null
- unique_id = "xxxxxxxxxxxxxxxxxxxx" -> null
# (3 unchanged attributes hidden)
}
# aws_iam_role_policy_attachment.lambda_basic will be destroyed
- resource "aws_iam_role_policy_attachment" "lambda_basic" {
- id = "lambda_validate_token_role-xxxxxxxxxxxxxxxxxxxx" -> null
- policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -> null
- role = "lambda_validate_token_role" -> null
}
# aws_iam_role_policy_attachment.lambda_invoke_attachment will be destroyed
- resource "aws_iam_role_policy_attachment" "lambda_invoke_attachment" {
- id = "CognitoUnAuthRole-xxxxxxxxxxxxxxxxxxxx" -> null
- policy_arn = "arn:aws:iam::xxxxxxxxxxxx:policy/LambdaInvokePolicy" -> null
- role = "CognitoUnAuthRole" -> null
}
# aws_lambda_function.validate_token will be destroyed
- resource "aws_lambda_function" "validate_token" {
- architectures = [
- "x86_64",
] -> null
- arn = "arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken" -> null
- code_sha256 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -> null
- filename = "function.zip" -> null
- function_name = "validateToken" -> null
- handler = "index.handler" -> null
- id = "validateToken" -> null
- invoke_arn = "arn:aws:apigateway:ap-southeast-2:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken/invocations" -> null
- last_modified = "2024-12-24T11:37:09.868+0000" -> null
- layers = [] -> null
- memory_size = 128 -> null
- package_type = "Zip" -> null
- publish = false -> null
- qualified_arn = "arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken:$LATEST" -> null
- qualified_invoke_arn = "arn:aws:apigateway:ap-southeast-2:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-southeast-2:xxxxxxxxxxxx:function:validateToken:$LATEST/invocations" -> null
- reserved_concurrent_executions = -1 -> null
- role = "arn:aws:iam::xxxxxxxxxxxx:role/lambda_validate_token_role" -> null
- runtime = "nodejs18.x" -> null
- skip_destroy = false -> null
- source_code_hash = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -> null
- source_code_size = 891 -> null
- tags = {} -> null
- tags_all = {} -> null
- timeout = 3 -> null
- version = "$LATEST" -> null
# (6 unchanged attributes hidden)
- ephemeral_storage {
- size = 512 -> null
}
- logging_config {
- log_format = "Text" -> null
- log_group = "/aws/lambda/validateToken" -> null
# (2 unchanged attributes hidden)
}
- tracing_config {
- mode = "PassThrough" -> null
}
}
Plan: 0 to add, 0 to change, 8 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
aws_iam_role_policy_attachment.lambda_invoke_attachment: Destroying... [id=CognitoUnAuthRole-xxxxxxxxxxxxxxxxxxxx]
aws_cognito_identity_pool_roles_attachment.identity_pool_roles: Destroying... [id=ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
aws_lambda_function.validate_token: Destroying... [id=validateToken]
aws_cognito_identity_pool_roles_attachment.identity_pool_roles: Destruction complete after 0s
aws_lambda_function.validate_token: Destruction complete after 1s
aws_iam_role_policy_attachment.lambda_basic: Destroying... [id=lambda_validate_token_role-xxxxxxxxxxxxxxxxxxxx]
aws_iam_role_policy_attachment.lambda_invoke_attachment: Destruction complete after 1s
aws_iam_policy.lambda_invoke_policy: Destroying... [id=arn:aws:iam::xxxxxxxxxxxx:policy/LambdaInvokePolicy]
aws_iam_role.cognito_unauth_role: Destroying... [id=CognitoUnAuthRole]
aws_iam_role_policy_attachment.lambda_basic: Destruction complete after 1s
aws_iam_role.lambda_validate_token_role: Destroying... [id=lambda_validate_token_role]
aws_iam_policy.lambda_invoke_policy: Destruction complete after 1s
aws_iam_role.lambda_validate_token_role: Destruction complete after 1s
aws_iam_role.cognito_unauth_role: Destruction complete after 2s
aws_cognito_identity_pool.identity_pool: Destroying... [id=ap-southeast-2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
aws_cognito_identity_pool.identity_pool: Destruction complete after 1s
Destroy complete! Resources: 8 destroyed.
Part 5: Verification
Post-Destroy Verification
After running terraform destroy, verify resources are no longer accessible:

Screenshot showing Lambda function is no longer accessible
Best Practices
- Always review the plan before applying changes
- Use version control for your Terraform configurations
- Implement proper state management for team environments
- Use variables for reusable configurations
- Regularly backup your Terraform state files
- Test your infrastructure code in a development environment first