Skip to content

Import home-unite-us production Cognito Lambdas - #245

Merged
ale210 merged 2 commits into
mainfrom
17-import-hu-cognito-lambdas
Sep 30, 2026
Merged

ale210 merged 2 commits into
mainfrom
17-import-hu-cognito-lambdas

Conversation

@ale210

@ale210 ale210 commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Part of #17 (the "Import the Cognito Lambdas that are still unmanaged" section). The shared-pool half of #17 follows in a separate PR.

Adopts the two Lambda triggers on the production Home Unite Us pool, the role they run as, and the four /aws/lambda/* log groups.

  • customMessage and mergeUsers are the live production functions, despite the naming. home-unite-us-* is QA's pair.
  • The pool's lambda_config now references the functions instead of literal ARNs. The ARNs resolve the same, so this is not a live change.
  • project = home-unite-us tag on everything adopted, plus the two already-managed home-unite-us-* functions.

Code packaging: the deployed zips are committed, under projects/home-unite-us/lambda/prod/, downloaded with aws lambda get-function. Their SHA-256 equals the live CodeSha256, so no code change should be planned. (The source inside them matches lambda/*.js|.py too, but a zip rebuilt here would hash differently and would upload.)

Plan: no replacements. Changes beyond tags:

  • Log retention: all four groups go from never-expire to 180 days, matching the RDS log groups. Applying it deletes anything older.
  • One-time code re-upload, accepted. The plan confirms it: both functions gain filename and source_code_hash, which Terraform can't read back on import, so apply calls UpdateFunctionCode. The planned hashes equal the live CodeSha256 (phhzDzHq… / dwf8UIp7…), so the bytes are identical; no version is published and only last_modified changes. After that the hash is in state and plans are clean. ignore_changes was the alternative and was declined, since it would make the committed zips decorative.

Plan: 11 to import, 0 to add, 9 to change, 0 to destroy. The production pool does not appear, so the lambda_config swap is a no-op.

After merge: re-run the coverage script, and confirm a fresh /aws/lambda/mergeUsers stream appears after the apply.

Out of scope: customMessage runs on the deprecated nodejs18.x runtime.

@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Terraform plan in terraform
With backend config files: terraform/prod.backend.tfvars

Plan: 11 to import, 0 to add, 9 to change, 0 to destroy.
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
!~  update in-place

Terraform will perform the following actions:

  # module.home-unite-us.aws_cloudwatch_log_group.lambda["customMessage"] will be updated in-place
  # (imported from "/aws/lambda/home-unite-us-customMessage")
!~  resource "aws_cloudwatch_log_group" "lambda" {
        arn                         = "arn:aws:logs:us-west-2:035866691871:log-group:/aws/lambda/home-unite-us-customMessage"
        deletion_protection_enabled = false
        id                          = "/aws/lambda/home-unite-us-customMessage"
        kms_key_id                  = null
        log_group_class             = "STANDARD"
        name                        = "/aws/lambda/home-unite-us-customMessage"
        name_prefix                 = null
        region                      = "us-west-2"
!~      retention_in_days           = 0 -> 180
        skip_destroy                = false
!~      tags                        = {
+           "project" = "home-unite-us"
        }
!~      tags_all                    = {
+           "managed-by" = "terraform-incubator"
+           "project"    = "home-unite-us"
        }
    }

  # module.home-unite-us.aws_cloudwatch_log_group.lambda["mergeUsers"] will be updated in-place
  # (imported from "/aws/lambda/home-unite-us-mergeUsers")
!~  resource "aws_cloudwatch_log_group" "lambda" {
        arn                         = "arn:aws:logs:us-west-2:035866691871:log-group:/aws/lambda/home-unite-us-mergeUsers"
        deletion_protection_enabled = false
        id                          = "/aws/lambda/home-unite-us-mergeUsers"
        kms_key_id                  = null
        log_group_class             = "STANDARD"
        name                        = "/aws/lambda/home-unite-us-mergeUsers"
        name_prefix                 = null
        region                      = "us-west-2"
!~      retention_in_days           = 0 -> 180
        skip_destroy                = false
!~      tags                        = {
+           "project" = "home-unite-us"
        }
!~      tags_all                    = {
+           "managed-by" = "terraform-incubator"
+           "project"    = "home-unite-us"
        }
    }

  # module.home-unite-us.aws_cloudwatch_log_group.lambda_prod["customMessage"] will be updated in-place
  # (imported from "/aws/lambda/customMessage")
!~  resource "aws_cloudwatch_log_group" "lambda_prod" {
        arn                         = "arn:aws:logs:us-west-2:035866691871:log-group:/aws/lambda/customMessage"
        deletion_protection_enabled = false
        id                          = "/aws/lambda/customMessage"
        kms_key_id                  = null
        log_group_class             = "STANDARD"
        name                        = "/aws/lambda/customMessage"
        name_prefix                 = null
        region                      = "us-west-2"
!~      retention_in_days           = 0 -> 180
        skip_destroy                = false
!~      tags                        = {
+           "project" = "home-unite-us"
        }
!~      tags_all                    = {
+           "managed-by" = "terraform-incubator"
+           "project"    = "home-unite-us"
        }
    }

  # module.home-unite-us.aws_cloudwatch_log_group.lambda_prod["mergeUsers"] will be updated in-place
  # (imported from "/aws/lambda/mergeUsers")
!~  resource "aws_cloudwatch_log_group" "lambda_prod" {
        arn                         = "arn:aws:logs:us-west-2:035866691871:log-group:/aws/lambda/mergeUsers"
        deletion_protection_enabled = false
        id                          = "/aws/lambda/mergeUsers"
        kms_key_id                  = null
        log_group_class             = "STANDARD"
        name                        = "/aws/lambda/mergeUsers"
        name_prefix                 = null
        region                      = "us-west-2"
!~      retention_in_days           = 0 -> 180
        skip_destroy                = false
!~      tags                        = {
+           "project" = "home-unite-us"
        }
!~      tags_all                    = {
+           "managed-by" = "terraform-incubator"
+           "project"    = "home-unite-us"
        }
    }

  # module.home-unite-us.aws_iam_role.lambda_prod will be updated in-place
  # (imported from "lambda")
!~  resource "aws_iam_role" "lambda_prod" {
        arn                   = "arn:aws:iam::035866691871:role/lambda"
        assume_role_policy    = jsonencode(
            {
                Statement = [
                    {
                        Action    = "sts:AssumeRole"
                        Effect    = "Allow"
                        Principal = {
                            Service = "lambda.amazonaws.com"
                        }
                    },
                ]
                Version   = "2012-10-17"
            }
        )
        create_date           = "2024-10-08T09:25:55Z"
        description           = null
        force_detach_policies = false
        id                    = "lambda"
        managed_policy_arns   = [
            "arn:aws:iam::aws:policy/AmazonCognitoPowerUser",
            "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
        ]
        max_session_duration  = 3600
        name                  = "lambda"
        name_prefix           = null
        path                  = "/"
        permissions_boundary  = null
!~      tags                  = {
+           "project" = "home-unite-us"
        }
!~      tags_all              = {
+           "managed-by" = "terraform-incubator"
+           "project"    = "home-unite-us"
        }
        unique_id             = "*********************"
    }

  # module.home-unite-us.aws_iam_role_policy_attachment.lambda_cognito_prod will be imported
    resource "aws_iam_role_policy_attachment" "lambda_cognito_prod" {
        id         = "lambda/arn:aws:iam::aws:policy/AmazonCognitoPowerUser"
        policy_arn = "arn:aws:iam::aws:policy/AmazonCognitoPowerUser"
        role       = "lambda"
    }

  # module.home-unite-us.aws_iam_role_policy_attachment.lambda_execution_prod will be imported
    resource "aws_iam_role_policy_attachment" "lambda_execution_prod" {
        id         = "lambda/arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
        policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
        role       = "lambda"
    }

  # module.home-unite-us.aws_lambda_function.cognito_custom_message will be updated in-place
!~  resource "aws_lambda_function" "cognito_custom_message" {
        id                             = "home-unite-us-customMessage"
!~      tags                           = {
+           "project" = "home-unite-us"
        }
!~      tags_all                       = {
+           "project"    = "home-unite-us"
#            (1 unchanged element hidden)
        }
#        (31 unchanged attributes hidden)

#        (3 unchanged blocks hidden)
    }

  # module.home-unite-us.aws_lambda_function.cognito_custom_message_prod will be updated in-place
  # (imported from "customMessage")
!~  resource "aws_lambda_function" "cognito_custom_message_prod" {
        architectures                  = [
            "x86_64",
        ]
        arn                            = "arn:aws:lambda:us-west-2:035866691871:function:customMessage"
        code_sha256                    = "phhzDzHq3XSZSCUJFVPk+W7hLFlTdv28iCpnNUdByt4="
        code_signing_config_arn        = null
        description                    = null
+       filename                       = "projects/home-unite-us/lambda/prod/customMessage.zip"
        function_name                  = "customMessage"
        handler                        = "customMessage.handler"
        id                             = "customMessage"
        image_uri                      = null
        invoke_arn                     = "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:035866691871:function:customMessage/invocations"
        kms_key_arn                    = null
!~      last_modified                  = "2024-11-08T01:23:32.000+0000" -> (known after apply)
        layers                         = []
        memory_size                    = 128
        package_type                   = "Zip"
+       publish                        = false
        qualified_arn                  = "arn:aws:lambda:us-west-2:035866691871:function:customMessage:$LATEST"
        qualified_invoke_arn           = "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:035866691871:function:customMessage:$LATEST/invocations"
        region                         = "us-west-2"
        reserved_concurrent_executions = -1
        response_streaming_invoke_arn  = "arn:aws:apigateway:us-west-2:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-2:035866691871:function:customMessage/response-streaming-invocations"
        role                           = "arn:aws:iam::035866691871:role/lambda"
        runtime                        = "nodejs18.x"
        signing_job_arn                = null
        signing_profile_version_arn    = null
        skip_destroy                   = false
+       source_code_hash               = "phhzDzHq3XSZSCUJFVPk+W7hLFlTdv28iCpnNUdByt4="
        source_code_size               = 996
        source_kms_key_arn             = null
!~      tags                           = {
+           "project" = "home-unite-us"
        }
!~      tags_all                       = {
+           "managed-by" = "terraform-incubator"
+           "project"    = "home-unite-us"
        }
        timeout                        = 3
        version                        = "$LATEST"

        ephemeral_storage {
            size = 512
        }

        logging_config {
            application_log_level = null
            log_format            = "Text"
            log_group             = "/aws/lambda/customMessage"
            system_log_level      = null
        }

        tracing_config {
            mode = "PassThrough"
        }
    }

  # module.home-unite-us.aws_lambda_function.cognito_merge_users will be updated in-place
!~  resource "aws_lambda_function" "cognito_merge_users" {
        id                             = "home-unite-us-mergeUsers"
!~      tags                           = {
+           "project" = "home-unite-us"
        }
!~      tags_all                       = {
+           "project"    = "home-unite-us"
#            (1 unchanged element hidden)
        }
#        (31 unchanged attributes hidden)

#        (3 unchanged blocks hidden)
    }

  # module.home-unite-us.aws_lambda_function.cognito_merge_users_prod will be updated in-place
  # (imported from "mergeUsers")
!~  resource "aws_lambda_function" "cognito_merge_users_prod" {
        architectures                  = [
            "x86_64",
        ]
        arn                            = "arn:aws:lambda:us-west-2:035866691871:function:mergeUsers"
        code_sha256                    = "dwf8UIp7DHmfLL8VFH9RXZXBijeFsNB0/TWNoPy93is="
        code_signing_config_arn        = null
        description                    = null
+       filename                       = "projects/home-unite-us/lambda/prod/merge_users.zip"
        function_name                  = "mergeUsers"
        handler                        = "merge_users.lambda_handler"
        id                             = "mergeUsers"
        image_uri                      = null
        invoke_arn                     = "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:035866691871:function:mergeUsers/invocations"
        kms_key_arn                    = null
!~      last_modified                  = "2024-10-14T02:27:58.000+0000" -> (known after apply)
        layers                         = []
        memory_size                    = 128
        package_type                   = "Zip"
+       publish                        = false
        qualified_arn                  = "arn:aws:lambda:us-west-2:035866691871:function:mergeUsers:$LATEST"
        qualified_invoke_arn           = "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:035866691871:function:mergeUsers:$LATEST/invocations"
        region                         = "us-west-2"
        reserved_concurrent_executions = -1
        response_streaming_invoke_arn  = "arn:aws:apigateway:us-west-2:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-2:035866691871:function:mergeUsers/response-streaming-invocations"
        role                           = "arn:aws:iam::035866691871:role/lambda"
        runtime                        = "python3.12"
        signing_job_arn                = null
        signing_profile_version_arn    = null
        skip_destroy                   = false
+       source_code_hash               = "dwf8UIp7DHmfLL8VFH9RXZXBijeFsNB0/TWNoPy93is="
        source_code_size               = 846
        source_kms_key_arn             = null
!~      tags                           = {
+           "project" = "home-unite-us"
        }
!~      tags_all                       = {
+           "managed-by" = "terraform-incubator"
+           "project"    = "home-unite-us"
        }
        timeout                        = 3
        version                        = "$LATEST"

        ephemeral_storage {
            size = 512
        }

        logging_config {
            application_log_level = null
            log_format            = "Text"
            log_group             = "/aws/lambda/mergeUsers"
            system_log_level      = null
        }

        tracing_config {
            mode = "PassThrough"
        }
    }

  # module.home-unite-us.aws_lambda_permission.allow_merge_execution_from_user_pool_prod will be imported
    resource "aws_lambda_permission" "allow_merge_execution_from_user_pool_prod" {
        action              = "lambda:InvokeFunction"
        function_name       = "mergeUsers"
        id                  = "AllowMergeExecutionFromUserPool"
        principal           = "cognito-idp.amazonaws.com"
        qualifier           = null
        region              = "us-west-2"
        source_arn          = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/us-west-2_VH24AGQ3p"
        statement_id        = "*******************************"
        statement_id_prefix = null
    }

  # module.home-unite-us.aws_lambda_permission.allow_message_execution_from_user_pool_prod will be imported
    resource "aws_lambda_permission" "allow_message_execution_from_user_pool_prod" {
        action              = "lambda:InvokeFunction"
        function_name       = "customMessage"
        id                  = "AllowMessageExecutionFromUserPool"
        principal           = "cognito-idp.amazonaws.com"
        qualifier           = null
        region              = "us-west-2"
        source_arn          = "arn:aws:cognito-idp:us-west-2:035866691871:userpool/us-west-2_VH24AGQ3p"
        statement_id        = "*********************************"
        statement_id_prefix = null
    }

Plan: 11 to import, 0 to add, 9 to change, 0 to destroy.

✅ Plan applied in Terraform apply (OIDC) #96

@ale210
ale210 merged commit c8d40e6 into main Sep 30, 2026
ale210 added a commit that referenced this pull request Sep 30, 2026
Part of #17 (the shared-pool half). The Lambda half is #245.

Adopts the hand-made `vrms-dev` Cognito pool as the org's **shared user
pool**, and adds `modules/shared-user-pool-access` for projects to get
clients and, optionally, admin rights on it.

- **`terraform/cognito.tf`:** the pool and its domain, matched to live
AWS. `user_pool_tier = "LITE"`, `prevent_destroy`.
- **No `project` tag, deliberately.** The container module grants
Cognito admin on pools tagged with a project's name, so a tag would give
one project admin over every project's users.
  - **The name stays `vrms-dev`**, because renaming a pool replaces it.
- **`modules/shared-user-pool-access`:** takes a `clients` map and an
optional `task_role_name`. The role option adds an inline policy with
the same four admin actions the container module grants, scoped to this
pool only. Clients ignore `generate_secret` (it isn't readable on import
and would plan a replacement) and have `prevent_destroy`.
- **people-depot:** its three existing clients, plus the admin grant to
its dev backend task role. **That grant is a real IAM change**: the role
has no rights on this pool today.
- **vrms:** its one existing client, no grant. This is the vrms-dev test
the issue asks for.
- people-depot's `COGNITO_USER_POOL` now comes from the pool resource
instead of a literal. It resolves to the same value, so no task
definition change is expected.

**Expected plan:** 6 to import, 1 to add (the inline policy), 0 to
destroy, no replacements, and otherwise tags only.

**Merge note:** this PR and #245 both append to the end of `import.tf`,
so whichever merges second needs a trivial rebase.

Not included: the optional `user_pool` module for projects with their
own pool. home-unite-us already declares its own pools directly, so it
would have no user.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant