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"

    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"
    policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
        {
            Effect = "Allow"
            Action = "lambda:InvokeFunction"
            Resource = var.lambda_function_arn
        }
        ]
    })
}

# 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
    }
}

resource "aws_iam_role" "lambda_validate_token_role" {
    name = "lambda_validate_token_role"

    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
    ]
}

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:

Function Not Found Error

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