Amplify-cli: Get apiaivyGraphQLAPIIdOutput in auto generated PostConfirmation Lambda?

Created on 20 Jul 2019  ·  62Comments  ·  Source: aws-amplify/amplify-cli

How get apiaivyGraphQLAPIIdOutput in auto generated PostConfirmation Lambda?

i tried function update, and allow access to appSync, but this dosent work, because a dependsOn Failure.

Any infos?

bug functions

Most helpful comment

Is there an update?

I also did a function update and add permissions to API to access the appsyncid.
I need this id in the lamba cognito trigger post confirmation to send a userid to the dynamodb table: tablename-appsyncID-environment

But I received an Circular dependency error

All 62 comments

@davidbiller What exactly is the error you’re seeing?

It was a circular dependency error.
Should I do it again, and copy the whole error message?

I'm having the same issue when I do amplify update function and add api category access to the lambda post-confirmation trigger:

Ericks-MBP:app Erick$ amplify update function
Using service: Lambda, provided by: awscloudformation
? Please select the Lambda Function you would want to update icontainerPostConfirmation
? Do you want to update permissions granted to this Lambda function to perform on other resources in your project?
 Yes
? Select the category api
Api category has a resource called icontainer
? Select the operations you want to permit for icontainer create, read, update, delete

You can access the following resource attributes as environment variables from your Lambda function
var environment = process.env.ENV
var region = process.env.REGION
var apiIcontainerGraphQLAPIIdOutput = process.env.API_ICONTAINER_GRAPHQLAPIIDOUTPUT
var apiIcontainerGraphQLAPIEndpointOutput = process.env.API_ICONTAINER_GRAPHQLAPIENDPOINTOUTPUT

? Do you want to edit the local lambda function now? No

Then pushing:

Circular dependency between resources: [functionme, authicontainer, functiondeleteDirectory, functionicontainerPostConfirmation, apiicontainer]

edit: here is my backend-config.json https://gist.github.com/ErickTamayo/2fc64c7d886527f968f28c58727be2a7

I second that. Also looking for the way to pass API ID (for the table names) to the postConfirmation lambda.

Same here, if you give a congnito trigger lambda withamplify update function access to the api there a Circular dependency between resources error that appear when you push. It should be possible to make it work with a custom resource. But I begin with amplify and don't really know where and how to put it.

I'm also had this problem, but when trying to allow lambda access to auth. I have created a PostConfirmation trigger for cognito auth (through amplify update auth) and want to set the value of a custom cognito attribute for the user when they confirm their account. (using aws-sdk adminUpdateUserAttributes).

? Please select the Lambda Function you would want to update mycognitoPostConfirmation
? Do you want to update permissions granted to this Lambda function to perform on other resources in your project? Yes
? Select the category auth
Auth category has a resource called mycognito
? Select the operations you want to permit for mycognito update

You can access the following resource attributes as environment variables from your Lambda function
var environment = process.env.ENV
var region = process.env.REGION
var authMycognitoUserPoolId = process.env.AUTH_MYCOGNITO_USERPOOLID

Error: Cannot add mycognitoPostConfirmation due to a cyclic dependency
    at checkForCyclicDependencies (/usr/local/lib/node_modules/@aws-amplify/cli/src/extensions/amplify-helpers/update-amplify-meta.js:243:11)
    at Object.updateamplifyMetaAfterResourceUpdate (/usr/local/lib/node_modules/@aws-amplify/cli/src/extensions/amplify-helpers/update-amplify-meta.js:119:5)
    at Object.updateResource (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-function/provider-utils/awscloudformation/index.js:243:21)
    at process._tickCallback (internal/process/next_tick.js:68:7)

Currently my workaround is to manually edit the auth cloudformation template and add the permissions, however it would be better if we could do this through the cli.

Is there an update?

I also did a function update and add permissions to API to access the appsyncid.
I need this id in the lamba cognito trigger post confirmation to send a userid to the dynamodb table: tablename-appsyncID-environment

But I received an Circular dependency error

Having same issue

+1

Any updates?

Same issue here at the moment. I need the API Id in my CF template. Anyone with a workaround for the time being?

I need the same as @rpostulart, <tablename>-<AppSyncID>-<env>, both in the roles and as an environment variable to target the DB Table.

I am facing the same issue when updating API and adding a new endpoint

I'm having the same issue when adding API access to my postConfirmation function. I tried to update the function again to remove API access, and I still get the circular dependency error. I'm not sure how to undo the issue.

I'm having the same issue when adding API access to my postConfirmation function. I tried to update the function again to remove API access, and I still get the circular dependency error. I'm not sure how to undo the issue.

Amplify env checkout yourEnvName —restore

Alternatively you can search through the cloudformation-template and delete all references to the the post confirmation trigger. I am having the same issue, where i am unable to add access to my graphql api in the post confirmation trigger, the same circular reference occurs.

@kaustavghosh06 any updates on this very common problem? Is there a recommended best practice from the Amplify team to work around this?
Right now, I am updating the IAM role permissions manually to allow my lambda function permission to call my GraphQL api. Manually updating IAM roles is not ideal at all. I don't mind writing CloudFormation to do this but it is not clear how to tie in a custom child CloudFormation template into the Amplify backend CloudFormation template/stack hierarchy.
Having documentation for Amplify that shows how to update IAM roles with custom policy statements would be very beneficial for everyone using Amplify and could solve this problem scenario as well as others.
Thoughts?

Thanks,
Erik

+1

+1

+1

+1 didn't find a good solution yet. would love to get some hints on how to do this correctly. I guess one must create a custom resource and bind both api and postConfirmation function to those as dependencies? not sure tho.

I do this:

  • I create another function and give it access to whatever I need (auth, graphql...)
  • In trigger lambda cloudformation, add permissions to invoke any other lambda to the lambda's execution policy ...
        {
            "Effect": "Allow",
            "Action": [
                "lambda:*"
            ],
            "Resource": [
                "*"
            ]
        }

(if you try to actually specify the lambda by referencing it, you will get get circular reference problem, but you could possibly just use the name in the string instead of *, and as action just specify execute lambda, if you want to use the principle of giving minimal required permissions)

  • In trigger lambda code invoke that newly created lambda ( I think you need to concatenate the env + the name you have given to the lambda):
const env = process.env.ENV
const functionName = 'theNameYouGaveTheOtherFunction-' + env
const payload = {
            sub: sub,
            **other data***
        }
lambda.invoke({
            FunctionName: functionName,
            Payload: JSON.stringify(payload)
        }).promise().then(response0 => {
            console.log("Lambda with AppSync access called")
            const response = JSON.parse(response0.Payload)
            **etc***

@tgjorgoski well, its kinda workaround, but at least you figured out how to do this!

Could you please explain point 2 a bit more in detail? how do you add permissions? what do you mean by "not referencing it but use simple strings"?

Hi @martinjuhasz , I updated my previous comment with more info.

Thanks @tgjorgoski for the guidance you laid out. I did something similar, where I created a separate lambda function, which is called by the trigger (Pre Token Trigger in my case) lambda function. This does seem to slow down the login process quite a bit, since I have one lambda waiting on another, which probably isn't good practice. Did you experience the same thing and did you find any way around it, or perhaps alternatives to invoking a secondary lambda function?

Sorry @ngnathan , I missed the question - for the performance I noticed that if I remove the default "index.js" which amplify cli is generating, and simply copy the main logic from the trigger inside it, the performance gets much better. I think the actual lambda calling each other is not that bad.

@tgjorgoski Thank you so much for the suggestion. Great workaround. Works well!

Thanks @tgjorgoski - that's a great tip!

I did end up completely switching my Pre Token and Post Confirmation logic up. Instead of using a lambda to invoke another lambda, I used a lambda to add the lambda as a Pre Token Trigger / Post Confirmation Trigger. This seems to work well for my purposes. I've documented that in my comment on this thread #3430 (comment)

I want to save the user details in a DynamoDB when they sign up, not when they verify.
Without adding permission to the api, the necessary env variables are not added to the pre signup lambda function, and if I add permissions to the api then I get the same circular dependency error.

Hey all,
Just following back up with the solution I used to solve this circular dependency problem. My issue was with using the Cognito Pre-Token generation lambda trigger which needed to know information about my Appsync API (API ID or endpoint). This circular dependency would occur though for any Cognito lambda trigger that needs to know the API ID or endpoint.

Dependency looks like this:

  • API depends on Cognito
  • Congnito depends on lambda function for Cognito trigger (pre-token generation in my case)
  • Cognito trigger Lambda function depends on API (for API ID and/or endpoint)

My solution was to break the circle by removing the 3rd bullet above, Cognito trigger lambda function depending on API. What I did was:

  • Make sure my CloudFormation template for the Cognito trigger lambda function outputs the IAM role name and ARN that it creates.
  • Create a new "iam" category in backend-config.json and associated filesystem naming conventions for this "iam" category and CloudFormation template. This is where I can add the needed IAM policies to the Cognito trigger lambda function role (for DynamoDB access based on table name or access to Appsync API) since this nested CloudFormation template can depend on both API (for API ID and endpoint) and the Cognito trigger lambda function (for the IAM role Name and ARN).
  • In this “iam” CloudFormation template I also create a SSM Parameter Store parameter holding the API ID and endpoint and grant access to the IAM role for the Cognito trigger lambda function in this same CloudFormation template to retrieve this SSM parameter.
  • Last in the Cognito trigger lambda function CloudFormation template instead of passing the API ID or endpoint directly as a CloudFormation parameter we can now pass the well-known name of the SSM parameter and set it as a lambda function env variable. The lambda function code should then be updated to look up the value of this SSM parameter on its first invocation and store the value as a function variable for all other invocations to use.

This way everything is still completely automated through the Amplify CloudFormation nested stack.

I hope this makes sense and can help others out there!
I hope everyone is staying safe and health!

Cheers,
Erik

Hey @paulsson , any chance you could share your backend-config.json? Many thanks.

@sceptyk sorry I didn't get a reply out earlier. Below is a simplified version of the backend-config.json file. Hopefully that gets you going. It will break the circular dependency that is caused by adding Cognito lambda triggers. Everything is completely automated and there is no weird workarounds with a lambda invoking another lambda.

{
    "api": {
        "MyAppApi": {
            "service": "AppSync",
            "providerPlugin": "awscloudformation",
            "output": {
                "authConfig": {
                    "additionalAuthenticationProviders": [
                        {
                            "authenticationType": "AWS_IAM"
                        }
                    ],
                    "defaultAuthentication": {
                        "authenticationType": "AMAZON_COGNITO_USER_POOLS",
                        "userPoolConfig": {
                            "userPoolId": "authUserAuth"
                        }
                    }
                }
            }
        }
    },
    "auth": {
        "UserAuth": {
            "service": "Cognito",
            "providerPlugin": "awscloudformation",
            "dependsOn": [
                {
                    "category": "function",
                    "resourceName": "UserAuthPreTokenGeneration",
                    "triggerProvider": "Cognito",
                    "attributes": [
                        "Arn",
                        "Name"
                    ]
                }
            ]
        }
    },
    "function": {
        "UserAuthPreTokenGeneration": {
            "service": "Lambda",
            "providerPlugin": "awscloudformation",
            "build": true
        }
        },
    "iam": {
        "UserAuthPreTokenGeneration": {
            "service": "IAM",
            "providerPlugin": "awscloudformation",
            "dependsOn": [
                {
                    "category": "api",
                    "resourceName": "MyAppApi",
                    "attributes": [
                        "GraphQLAPIIdOutput",
                        "GraphQLAPIEndpointOutput"
                    ]
                },
                {
                    "category": "function",
                    "resourceName": "UserAuthPreTokenGeneration",
                    "attributes": [
                        "LambdaExecutionRole"
                    ]
                }
            ]
        }
    }
}

NOTE: The "iam" category section in the above backend-config.json is something I arbitrarily named and added since amplify cli doesn't have such a category.
You must run 'amplify env checkout ' after directly modifying backend-config.json to get 'amplify push' to recognize the changes (you can just checkout the same env as you are currently on).
You can create other AWS resources in a similar fashion that aren't yet supported in amplify CLI. For example, I create KMS keys for encrypting / decrypting secrets stored in SSM Parameter Store by adding a "kms" category in backend-config.json.

@tgjorgoski @chrisco255 @ngnathan @amuresia @martinjuhasz this may be of interest to you as well. You likely won't really want to allow your workaround lambda function to invoke any other function in your account by granting it the below IAM permissions as that goes against security best practices of "least privilege".

        {
            "Effect": "Allow",
            "Action": [
                "lambda:*"
            ],
            "Resource": [
                "*"
            ]
        }

@davidbiller tagging you since you originally opened this issue.

I hope this can help others out since this seems like a very common issue when needing to use Cognito triggers.
I can provide more details if needed.

Cheers!
Erik

Hi @paulsson, I really like your approach to this problem. Thanks for sharing the backend-config.json, this is helpful. Do you think you can share some example source code for your entire custom "iam" service in the backend directory, as well as the changes you make to the cloudformation-template for the lambda function? I understand what you are describing, but it would be great to have example code for the entire modification, since it is not trivial and everyone's problem here is almost identical..

So much appreciated!

Ky

FYI for anyone still looking for a decent work around on this..

My work around for time being is to manage the trigger lambda functions externally via Serverless Framework. It is quite simple since there is native support for cognito triggers in serverless.yml like this:

functions:
  PreTokenGeneration:
    handler: PreTokenGeneration.handler
    events:
      - cognitoUserPool:
          pool: <nameOfUserPool>
          trigger: PreTokenGeneration
          existing: true

It isn't perfect but it is absolutely simple and practical. After trying a few options from this thread, I've come to the conclusion that they are too complicated or indirect, so managing the functions cleanly at the cost of having them in a different framework feels reasonable (to be fair, I do use Serverless for other parts of my app so I have it integrated already)

@paulsson that solution looks quite elegant. Just set that up and works like a charm. In addition to your note above for anyone reading, there needs to be a cloud formation template which would apply a policy AmplifyResourcesPolicy (if you want to copy it from another lambda function) to the role.

@paulsson that solution looks quite elegant. Just set that up and works like a charm. In addition to your note above for anyone reading, there needs to be a cloud formation template which would apply a policy AmplifyResourcesPolicy (if you want to copy it from another lambda function) to the role.

What does the policy need to contain exactly? Do you have an example? I've made the changes that @paulsson suggested with a custom "iam/functionName" folder containing a parmaters.json/template.json file but I'm still getting the circular dependency issue...

@ammarkarachi @dabit3 @kaustavghosh06 - do you know if this will be resolved any time soon? This issue has been open almost a year now :(

Best regards,

Kyle

So after much hacking I've got this working thanks to @paulsson ! Thanks for taking the time to write the steps on how you solved this!

@kylekirkby Sorry AWS beginner here, can you share your parameters.json and template.json configs? I'm having some issues creating the LambdaExecutionRole

cc @paulsson

Hi @quorth0n,

I feel your pain. It took me a few hours of debugging and amplify pushing to get working. I've added my GraphQL API Endpoint URL to SSM with the current environment to ensure this works envs. As stated by @paulsson above you need to modify your backend-config.json file and add a custom resource. Once you've added your custom resource make sure to run amplify env checkout develop to ensure your changes are pulled in. My custom CloudFormation resource stack ended up looking something like this:

/amplify/backend/backend-config.json

{
...
   "api": {
       ...
    },
    "analytics": {
   ...
    },
    "lambdaTriggerPermissions": {
        "postConfirmationPermissions": {
            "service": "Cognito-Lambda-Trigger-Permissions",
            "providerPlugin": "awscloudformation",
            "dependsOn": [
                {
                    "category": "api",
                    "resourceName": "{name-of-your-api-resource}",
                    "attributes": [
                        "GraphQLAPIIdOutput",
                        "GraphQLAPIEndpointOutput"
                    ]
                },
                {
                    "category": "function",
                    "resourceName": "{name-of-your-post-confirmation-lambda-function}",
                    "attributes": [
                        "LambdaExecutionRole"
                    ]
                }
            ]
        }
    }
}

/amplify/backend/lambdaTriggerPermissions/postConfirmationPermissions/template.json

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "",
    "Parameters": {
        "env": {
            "Type": "String"
        },
        "api{name-of-your-api}Output": {
            "Type": "String",
            "Default": "api{name-of-your-api}Output"
        },
        "api{name-of-your-api}GraphQLAPIEndpointOutput": {
            "Type": "String",
            "Default": "api{name-of-your-api}GraphQLAPIEndpointOutput"
        },
        "function{name-of-your-api}PostConfirmationLambdaExecutionRole": {
            "Type": "String",
            "Default": "function{name-of-your-api}PostConfirmationLambdaExecutionRole"
        }
    },
    "Conditions": {},
    "Resources": {
        "GraphQLEndpointParam": {
            "Type": "AWS::SSM::Parameter",
            "Properties": {
                "Name": {
                    "Fn::Join": [
                        "",
                        [
                            "GraphQLEndpoint-",
                            {
                                "Ref": "env"
                            }
                        ]
                    ]
                },
                "Type": "String",
                "Value": {
                    "Ref": "api{name-of-your-api}GraphQLAPIEndpointOutput"
                },
                "Description": "GraphQL API Endpoint for current stage"
            }
        },
        "PostConfirmationCognitoResourcesPolicy": {
            "Type": "AWS::IAM::Policy",
            "Properties": {
                "PolicyName": "post-confirmation-api-execution-policy",
                "Roles": [
                    {
                        "Ref": "function{name-of-your-api}PostConfirmationLambdaExecutionRole"
                    }
                ],
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": [
                                "ssm:*"
                            ],
                            "Resource": "*"
                        },
                        {
                            "Effect": "Allow",
                            "Action": [
                                "appsync:Create*",
                                "appsync:StartSchemaCreation",
                                "appsync:GraphQL",
                                "appsync:Get*",
                                "appsync:List*",
                                "appsync:Update*",
                                "appsync:Delete*"
                            ],
                            "Resource": [
                                {
                                    "Fn::Join": [
                                        "",
                                        [
                                            "arn:aws:appsync:",
                                            {
                                                "Ref": "AWS::Region"
                                            },
                                            ":",
                                            {
                                                "Ref": "AWS::AccountId"
                                            },
                                            ":apis/",
                                            {
                                                "Ref": "api{name-of-your-api}GraphQLAPIIdOutput"
                                            },
                                            "/*"
                                        ]
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        }
    },
    "Outputs": {}
}

/amplify/backend/lambdaTriggerPermissions/postConfirmationPermissions/parameters.json

{
    "api{name-of-your-api}GraphQLAPIEndpointOutput": {
        "Fn::GetAtt": [
            "{name-of-your-api}",
            "Outputs.GraphQLAPIEndpointOutput"
        ]
    },
    "api{name-of-your-api}GraphQLAPIIdOutput": {
        "Fn::GetAtt": [
            "{name-of-your-api}",
            "Outputs.GraphQLAPIIdOutput"
        ]
    },
    "function{name-of-your-api}PostConfirmationLambdaExecutionRole": {
        "Fn::GetAtt": [
            "{name-of-your-api}PostConfirmation",
            "Outputs.LambdaExecutionRole"
        ]
    }
}

Depending on what you're looking to do.. I added an additional module to the parmaeters.json file for the post confirmation function resource.

/amplify/backend/function/name-of-yourPostConfirmation/parameters.json

{
    "modules": "add-to-group,create-project"
}

Then modified my create-project.js file to something like this:

/* eslint-disable-line */
const AWS = require("aws-sdk");
AWS.config.update({ region: process.env.REGION });
const addProject = require("./graphql.js").addProject;
const call_to_graphql = require("./helpers/graphql").call_to_graphql;
const ssm = new AWS.SSM();

async function getEndpoint() {
  var params = {
    Name: "GraphQLEndpoint-" + process.env.ENV,
    WithDecryption: true,
  };
  var request = await ssm.getParameter(params).promise();
  return request.Parameter.Value;
}
// Add a Project to DynamoDB
async function createProject(event) {
  // Get GraphQL URL from SSM
  var graphqlURL = await getEndpoint();
  // Craft the params input array for entry to DynamoDB
  const item = {
    name: "My Project",
    owner: event.userName,
  };
  call_to_graphql(item, addProject, "AddProject", graphqlURL);
  return true;
}

exports.handler = async (event, context, callback) => {
  await createProject(event);
};

Something that caught me by surprise (but makes sense) is that cognito lambda triggers need to be short-lived <5 seconds execution; if not then the function will be triggered multiple times. So I needed to execute a lambda function separately through a custom mutation setup in my graphql schema to do the computation of post sign up business logic.

Hope this helps yourself and others.

Cheers,

Kyle

I'm having the same problem... I have updated the auth like this:

andres@DESKTOP-CPTOQVN:~/TeVi$ amplify update auth
Please note that certain attributes may not be overwritten if you choose to use defaults settings.

You have configured resources that might depend on this Cognito resource.  Updating this Cognito resource could have unintended side effects.

Using service: Cognito, provided by: awscloudformation
 What do you want to do? Walkthrough all the auth configurations
 Select the authentication/authorization services that you want to use: User Sign-Up, Sign-In, connected with AWS IAM cont
rols (Enables per-user Storage features for images or other content, Analytics, and more)
 Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) Yes
 Do you want to enable 3rd party authentication providers in your identity pool? No
 Do you want to add User Pool Groups? No
 Do you want to add an admin queries API? No
 Multifactor authentication (MFA) user login options: OFF
 Email based user registration/forgot password: Enabled (Requires per-user email entry at registration)
 Please specify an email verification subject: Your verification code
 Please specify an email verification message: Your verification code is {####}
 Do you want to override the default password policy for this User Pool? No
 Specify the app's refresh token expiration period (in days): 30
 Do you want to specify the user attributes this app can read and write? No
 Do you want to enable any of the following capabilities? 
 Do you want to use an OAuth flow? No
? Do you want to configure Lambda Triggers for Cognito? Yes
? Which triggers do you want to enable for Cognito Post Confirmation
? What functionality do you want to use for Post Confirmation Create your own module
Succesfully added the Lambda function locally
? Do you want to edit your custom function now? No
Successfully updated resource tevi locally

Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

And then I did amplify push and then I have updated this function to create and update the content of the User table made with @model through the schema.graphql file:

andres@DESKTOP-CPTOQVN:~/TeVi$ amplify update function
Using service: Lambda, provided by: awscloudformation
? Please select the Lambda Function you would want to update teviPostConfirmation
? Do you want to update permissions granted to this Lambda function to perform on other resources in your project? Yes
? Select the category storage
? Storage has 12 resources in this project. Select the one you would like your Lambda to access User:@model(appsync)
? Select the operations you want to permit for User:@model(appsync) create, update

You can access the following resource attributes as environment variables from your Lambda function
        API_TEVI_GRAPHQLAPIIDOUTPUT
        API_TEVI_USERTABLE_ARN
        API_TEVI_USERTABLE_NAME
        ENV
        REGION
? Do you want to invoke this function on a recurring schedule? No
? Do you want to edit the local lambda function now? No
Successfully updated resource

Then I did amplify push and I got this error:

andres@DESKTOP-CPTOQVN:~/TeVi$ amplify push
✔ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name        | Operation | Provider plugin   |
| -------- | -------------------- | --------- | ----------------- |
| Function | teviPostConfirmation | Update    | awscloudformation |
| Auth     | tevi                 | No Change | awscloudformation |
| Api      | tevi                 | No Change | awscloudformation |
| Storage  | s3c1026a67           | No Change | awscloudformation |
? Are you sure you want to continue? Yes
⠼ Updating resources in the cloud. This may take a few minutes...Error updating cloudformation stack
✖ An error occurred when pushing the resources to the cloud

Circular dependency between resources: [functionteviPostConfirmation, authtevi, UpdateRolesWithIDPFunctionOutputs, apitevi, UpdateRolesWithIDPFunction]
An error occured during the push operation: Circular dependency between resources: [functionteviPostConfirmation, authtevi, UpdateRolesWithIDPFunctionOutputs, apitevi, UpdateRolesWithIDPFunction]

How can I fix it?

@paulsson I followed your approach but instead of utilising SSM to store the API key, particularly if its needed as an environment variable for the lamda, I just run a bash script after my amplify push.

This may work for others who are using bash scripts currently to facilitate amplify push due to no pre or post hooks scripts.

In the bash script, I update the lambda env variables using the commandline aws tool... I end up with something like this:

#!/bin/bash 

ROOT_PATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )/.."
AMPLIFY_META_FILE=$ROOT_PATH/amplify/backend/amplify-meta.json
LOCAL_ENV_FILE=$ROOT_PATH/amplify/.config/local-env-info.json

region=$(cat $AMPLIFY_META_FILE | jq -r '.providers.awscloudformation.Region')
env=$(cat $LOCAL_ENV_FILE | jq -r '.envName')
cognito_userpool_id=$(cat $AMPLIFY_META_FILE | jq -r '.auth.cognitoUsers.output.UserPoolId')
appsyncApiId=$(cat $AMPLIFY_META_FILE | jq -r '.api.api.output.GraphQLAPIIdOutput')
dyanmodb_user_table_name="User-${appsyncApiId}-${env}"
variables="\
    {\
        \"Variables\": {\
            \"ENV\": \"$env\",\
            \"REGION\": \"$region\",\
            \"DYNAMODB_USER_TABLE_NAME\": \"$dyanmodb_user_table_name\",\
            \"COGNITO_USERPOOL_ID\": \"$cognito_userpool_id\"\
        }\
    }\
"

echo "Setting CognitoUser Lambda Environment Variables:"
echo $variables

aws lambda update-function-configuration \
--function-name cognitoUser-$env \
--environment "$variables"

note: you need aws cli correctly configured and jq to read json files in bash. my bash files are located in {root project directory}/scripts

@kaustavghosh06 is it possible to modify the CFT to specify an existing lambda function instead of one of the generated ones?

After creating a cognito user we want the post confirmation function to add a user to the dynamodb table to be used as the profile for a user.

When giving access to the appropriate model, we get the Circular dependency between resources.

This is a bit of a concern as it's pretty standard practice to do.

Need to get Table name without circular dependency error.

+1 I am having the same issue. Need to access the AppSync endpoint from the PostConfirmation lambda assigned to the trigger.

A work around for us, we added the graphql ids to out cloudformation which allows us to get the table name and access it by process.env.USER_TABLE_NAME.

Additions to the cloudformation template are Mappings, Variables and the dynamodb:putitem arn permissions policy under lambdaexecutionpolicy

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Lambda resource stack creation using Amplify CLI",
    "Parameters": {
        "GROUP": {
            "Type": "String",
            "Default": ""
        },
        "modules": {
            "Type": "String",
            "Default": "",
            "Description": "Comma-delimmited list of modules to be executed by a lambda trigger. Sent to resource as an env variable."
        },
        "resourceName": {
            "Type": "String",
            "Default": ""
        },
        "trigger": {
            "Type": "String",
            "Default": "true"
        },
        "functionName": {
            "Type": "String",
            "Default": ""
        },
        "roleName": {
            "Type": "String",
            "Default": ""
        },
        "parentResource": {
            "Type": "String",
            "Default": ""
        },
        "parentStack": {
            "Type": "String",
            "Default": ""
        },
        "env": {
            "Type": "String"
        }
    },
    "Mappings": {
        "graphQLAPIIdMap": {
            "dev": {
                "graphQLAPIId": "xxxxxx"
            },
            "prod": {
                "graphQLAPIId": "xxxxxx"
            },
        }
    },
    "Conditions": {
        "ShouldNotCreateEnvResources": {
            "Fn::Equals": [
                {
                    "Ref": "env"
                },
                "NONE"
            ]
        }
    },
    "Resources": {
        "LambdaFunction": {
            "Type": "AWS::Lambda::Function",
            "Metadata": {
                "aws:asset:path": "./src",
                "aws:asset:property": "Code"
            },
            "Properties": {
                "Handler": "index.handler",
                "FunctionName": {
                    "Fn::If": [
                        "ShouldNotCreateEnvResources",
                        "BaseProjectAuthPostConfirmation",
                        {
                            "Fn::Join": [
                                "",
                                [
                                    "BaseProjectAuthPostConfirmation",
                                    "-",
                                    {
                                        "Ref": "env"
                                    }
                                ]
                            ]
                        }
                    ]
                },
                "Environment": {
                    "Variables": {
                        "ENV": {
                            "Ref": "env"
                        },
                        "MODULES": {
                            "Ref": "modules"
                        },
                        "REGION": {
                            "Ref": "AWS::Region"
                        },
                        "GROUP": {
                            "Ref": "GROUP"
                        },
                        "USER_TABLE_NAME": {
                            "Fn::Join": [
                                "",
                                [
                                    "User",
                                    "-",
                                    {
                                        "Fn::FindInMap": [
                                            "graphQLAPIIdMap",
                                            {
                                                "Ref": "env"
                                            },
                                            "graphQLAPIId"
                                        ]
                                    },
                                    "-",
                                    {
                                        "Ref": "env"
                                    }
                                ]
                            ]
                        }
                    }
                },
                "Role": {
                    "Fn::GetAtt": [
                        "LambdaExecutionRole",
                        "Arn"
                    ]
                },
                "Runtime": "nodejs10.x",
                "Timeout": "25",
                "Code": {
                    "S3Bucket": "<removed>",
                    "S3Key": "<removed>"
                },
                "Layers": []
            }
        },
        "LambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "RoleName": {
                    "Fn::If": [
                        "ShouldNotCreateEnvResources",
                        "BaseProjectAuthPostConfirmation",
                        {
                            "Fn::Join": [
                                "",
                                [
                                    "BaseProjectAuthPostConfirmation",
                                    "-",
                                    {
                                        "Ref": "env"
                                    }
                                ]
                            ]
                        }
                    ]
                },
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                }
            }
        },
        "lambdaexecutionpolicy": {
            "DependsOn": [
                "LambdaExecutionRole"
            ],
            "Type": "AWS::IAM::Policy",
            "Properties": {
                "PolicyName": "lambda-execution-policy",
                "Roles": [
                    {
                        "Ref": "LambdaExecutionRole"
                    }
                ],
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": [
                                "logs:CreateLogGroup",
                                "logs:CreateLogStream",
                                "logs:PutLogEvents"
                            ],
                            "Resource": {
                                "Fn::Sub": [
                                    "arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*",
                                    {
                                        "region": {
                                            "Ref": "AWS::Region"
                                        },
                                        "account": {
                                            "Ref": "AWS::AccountId"
                                        },
                                        "lambda": {
                                            "Ref": "LambdaFunction"
                                        }
                                    }
                                ]
                            }
                        },
                        {
                            "Effect": "Allow",
                            "Action": [
                                "dynamodb:PutItem"
                            ],
                            "Resource": [
                                {
                                    "Fn::Join": [
                                        "",
                                        [
                                            "arn:aws:dynamodb:",
                                            {
                                                "Ref": "AWS::Region"
                                            },
                                            ":",
                                            {
                                                "Ref": "AWS::AccountId"
                                            },
                                            ":table/",
                                            {
                                                "Fn::Join": [
                                                    "",
                                                    [
                                                        "User",
                                                        "-",
                                                        {
                                                            "Fn::FindInMap": [
                                                                "graphQLAPIIdMap",
                                                                {
                                                                    "Ref": "env"
                                                                },
                                                                "graphQLAPIId"
                                                            ]
                                                        },
                                                        "-",
                                                        {
                                                            "Ref": "env"
                                                        }
                                                    ]
                                                ]
                                            }
                                        ]
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        }
    },
    "Outputs": {
        "Name": {
            "Value": {
                "Ref": "LambdaFunction"
            }
        },
        "Arn": {
            "Value": {
                "Fn::GetAtt": [
                    "LambdaFunction",
                    "Arn"
                ]
            }
        },
        "LambdaExecutionRole": {
            "Value": {
                "Ref": "LambdaExecutionRole"
            }
        },
        "Region": {
            "Value": {
                "Ref": "AWS::Region"
            }
        }
    }
}

if anyone is OK with a more manual solution to this issue, you can do the following:

  1. add additional IAM auth provider to your GraphQL API
  2. decorate your @model with { allow: private, provider: iam } @auth directive
  3. add the following permission to your lambda's IAM execution role:
        {
            "Action": [
                "appsync:Create*",
                "appsync:StartSchemaCreation",
                "appsync:GraphQL",
                "appsync:Get*",
                "appsync:List*",
                "appsync:Update*",
                "appsync:Delete*"
            ],
            "Resource": [
                "arn:aws:appsync:eu-central-1:2323232:apis/replace-with-yours/*"
            ],
            "Effect": "Allow"
        }

The same issue. I appreciate the "workaround" but it seems really convoluted to implement when it should be something really common. We need to access to dynamoDB tables in the pre-jwt-token generation lambda:

<tablename>-<AppSyncID>-<env>

Hey @kylekirkby ,

your solution almost worked for me but I think that the replacements are partially wrong. The one that worked for me are:

File /amplify/backend/backend-config.json -> as suggested by @kylekirkby

File /amplify/backend/lambdaTriggerPermissions/postConfirmationPermissions/template.json


{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "",
  "Parameters": {
    "env": {
      "Type": "String"
    },
    "api{YOUR-API-NAME}GraphQLAPIEndpointOutput": {
      "Type": "String",
      "Default": "api{YOUR-API-NAME}Output"
    },
    "api{YOUR-API-NAME}GraphQLAPIIdOutput": {
      "Type": "String",
      "Default": "api{YOUR-API-NAME}GraphQLAPIEndpointOutput"
    },
    "function{YOUR-FUNCTION-NAME}LambdaExecutionRole": {
      "Type": "String",
      "Default": "function{YOUR-FUNCTION-NAME}LambdaExecutionRole"
    }
  },
  "Conditions": {},
  "Resources": {
    "GraphQLEndpointParam": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Name": {
          "Fn::Join": [
            "",
            [
              "GraphQLEndpoint-",
              {
                "Ref": "env"
              }
            ]
          ]
        },
        "Type": "String",
        "Value": {
          "Ref": "api{YOUR-API-NAME}GraphQLAPIEndpointOutput"
        },
        "Description": "GraphQL API Endpoint for current stage"
      }
    },
    "PostConfirmationCognitoResourcesPolicy": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "post-confirmation-api-execution-policy",
        "Roles": [
          {
            "Ref": "function{YOUR-FUNCTION-NAME}LambdaExecutionRole"
          }
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "ssm:*"
              ],
              "Resource": "*"
            },
            {
              "Effect": "Allow",
              "Action": [
                "appsync:Create*",
                "appsync:StartSchemaCreation",
                "appsync:GraphQL",
                "appsync:Get*",
                "appsync:List*",
                "appsync:Update*",
                "appsync:Delete*"
              ],
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [
                      "arn:aws:appsync:",
                      {
                        "Ref": "AWS::Region"
                      },
                      ":",
                      {
                        "Ref": "AWS::AccountId"
                      },
                      ":apis/",
                      {
                        "Ref": "api{YOUR-API-NAME}GraphQLAPIIdOutput"
                      },
                      "/*"
                    ]
                  ]
                }
              ]
            }
          ]
        }
      }
    }
  },
  "Outputs": {}
}


file /amplify/backend/lambdaTriggerPermissions/postConfirmationPermissions/template.json


{
  "api{YOUR-API-NAME}GraphQLAPIEndpointOutput": {
    "Fn::GetAtt": [
      "{YOUR-API-NAME}",
      "Outputs.GraphQLAPIEndpointOutput"
    ]
  },
  "api{YOUR-API-NAME}GraphQLAPIIdOutput": {
    "Fn::GetAtt": [
      "{YOUR-API-NAME}",
      "Outputs.GraphQLAPIIdOutput"
    ]
  },
  "function{YOUR-FUNCTION-NAME}LambdaExecutionRole": {
    "Fn::GetAtt": [
      "function{YOUR-FUNCTION-NAME}",
      "Outputs.LambdaExecutionRole"
    ]
  }
}


Thanks @paulsson @kylekirkby .The solution works perfectly. However is there a way to call a graphql end point using a seperate lambda (due to 5 sec constraint ) using a custom SQS deployment and triggering the lambda .

After putting some effort into this issue I also got faced with I came up with the following solution.

I had the exact same use case as @MontoyaAndres: A circular dependency issue caused by a post confirmation function that needs API access (at least to get the GraphQL ID). After diving into this problem and reading tons of solutions and explanations, especially by @paulsson and @kylekirkby I came up with an own, in my opinion even simpler solution. I used the custom resource stack (amplify/backend/api/{your-api-name}/stacks/CustomResources.json) and exported the AppSyncApiId INSTEAD of doing an amplify function update.

[...]
"Outputs": {
    [...]
    "StaticGraphQLAPIId": {
      "Description": "GraphQL API ID with static export name",
      "Value": {
        "Ref": "AppSyncApiId"
      },
      "Export": {
        "Name": {
          "Fn::Join": [
            ":",
            [
              {
                "Fn::Join": [
                  "",
                  [
                    "api",
                    {
                      "Ref": "AppSyncApiName"
                    }
                  ]
                ]
              },
              {
                "Ref": "env"
              },
              "StaticGraphQLApiId"
            ]
          ]
        }
      }
    }
  }

Now I can use this exported value (which contains the dynamic part of all DynamoDB tables) to access DynamoDB from my Lambda function directly importing this value like this:

// amplify/backend/function/{your-post-confirmation-function}/parameters.json

{
  [...]
  "AppSyncApiName": "{your-api-name}"
{

// amplify/backend/function/{your-post-confirmation-function}/{your-post-confirmation-function}-cloudformation-template.json

"Parameters": {
    [...]
    "AppSyncApiName": {
      "Type": "String",
      "Description": "The name of the AppSync API",
      "Default": ""
    }
},

[...]
"Resources": {
  [...]
  "Properties": {
    [...]
    "Environment": {
      "Variables": {
        [...]
        "GRAPHQLID": {
              "Fn::ImportValue": {
                "Fn::Join": [
                  ":",
                  [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "api",
                          {
                            "Ref": "AppSyncApiName"
                          }
                        ]
                      ]
                    },
                    {
                      "Ref": "env"
                    },
                    "StaticGraphQLApiId"
                  ]
                ]
              }
            }

You now have access to process.env.GRAPHQLID from your NodeJS Lambda function and can execute DynamoDB actions according to your personal use case. For DynamoDB access you might extend your post confirmation function resource by corresponding resource policy (also in {your-post-confirmation-function}-cloudformation-template.json).

Hope it helps so that you don't have to spend hours and hours of research. Solving this circular dependency issue in amplify-cli would be appreciated.

It amazes me, that in so many common use cases for Amplify you need to circumvent Amplify and hack it yourself. I like the idea of Amplify, but being told these workarounds to dive into generated files you should rarely see (let alone edit) feels bad. At least these kinds of workarounds should not be necessary on your first tutorial implementing basic functionality. It would be great to see this handled by Amplify.

Btw: For me this problem is actually yak shaving for another basic functionality: syncing your Cognito users with the users in your AppSync. If that first thing would be included in Amplify, I wouldn't even need the Lambda permission to access AppSync in the trigger.

@morgler Absolutely. And beside of that authentication rules are not flexible enough. Simple use cases like showing all properties to some groups but exclude some for public access isn't possible in combination with connections. That's why we decided to build a good old fashioned REST API microservice architecture using serverless framework instead of Amplify Backend.

@bart I also use serverless in production - it's more mature and flexible.

However I haven't completely given up on Amplify over the past years. I still hope this develops into a mature tool that makes micro services even more convenient than serverless. My feeling is, that while two years ago I couldn't use Amplify for anything, today I can at least work around the missing pieces using serverless. I will keep playing with Amplify, but will likely rely on serverless in production for quite some time.

I initially plan to use a Post Confirmation Lambda to call AppSync and auto-create a user profile for each user at the database upon a successful confirm sign up. After reading this thread, it sounds like such a hassle to work around it in Post Confirmation Lambda due to circular dependency.

I realize I am better off letting users to call AppSync directly and create their own profile in the client side when they first login. To me, it is easier to set up a custom createProfile resolver in vtl for user to call.

For people experiencing similar issue with post confirmation lambda, I think it is possible to re-consider your use case. And if it can be moved to client side with a custom resolver, it can be an easier alternative to consider.

Cheers

@bart your solution did not work for me as. I got "No export named api::StaticGraphQLApiId found". Don't you need to add a dependsOn on the lambda since it now depends on the graphql api outputs? But wouldn't this re-introduce the circular issue? I think your solution would work if I do the deploy in two phases (one to export the output, the other to add the lambda), but it didn't work for me in one step.

@hisham Maybe you did something different. I didn't add the dependency because as you said it would re-introduce this circular dependency problem. And I also didn't deploy in two phases. Just did it as described.

I have added dependency to storage->tablename to post-confirmation lambda to save user data, but also have the same issue.
I confused, does dynamodb has dependency on Cognito?

Update:
(09/12/2020)
This is still not working. The bug was obscured by a vague error log that only helps compound the issue, rather than fix it. Classic Amplify. Apologies to all that may have gotten their hopes up 😅


(08/12/2020)
I ran into this issue recently. I have since updated the cli tool globally and the issue seems to be fixed. YMMV!

Steps:

yarn global add @aws-amplify/cli #4.38.0
amplify push --yes

Yet another workaround is to simply not register any trigger when configuring your auth and just set them in the AWS Console afterwards (or through the AWS CLI).

While this goes outside of the Amplify CLI and is not IaC, it's arguably the easiest and quickest option, least prone to errors, maintains dynamic env vars, and involves a quick manual step on the likely least changing part of your stack. This works as far as I can tell, at least for those using an API with Cognito Auth + Cognito triggers that use API/Dynamo access.

Relevant Steps From Scratch:

  • Configure auth, be sure to not set any triggers
  • Create your intended trigger functions, and provide any api/storage access you require through the CLI
  • Configure everything else as normal (e.g. API with Cognito User Pool auth)
  • Go to Cognito in AWS Console and set the relevant trigger lambdas (or through the AWS CLI)

Steps for those already suffering with cyclic dependency issue:

  • Delete any and all references to Cognito triggers in the various files

    • backend/backend-config.json: Delete relevant references in "dependsOn" property

    • backend/auth/{AuthName}/parameters.json:

    • Delete relevant references in "dependsOn" property

    • Reset "triggers" property to a blank string

    • backend/auth/{AuthName}/{AuthName}-cloudformation-template.yml:



      • Delete trigger function Arns & Names (e.g. function{FunctionName}Arn/Name)


      • Delete trigger invoke permissions (e.g. UserPoolPostConfirmationLambdaInvokePermission)


      • Delete whole LambdaConfig under UserPool in Resources section



  • Perform Steps from Scratch if you haven't already done so

You may ask why all the trouble for the second set of steps? I'm not able to remove a single remaining trigger, hence the manual edits. See https://github.com/aws-amplify/amplify-cli/issues/5986

Note to the CLI team: You guys have done an amazing job and I'm sure addressing these problems is quite complex. Nevertheless, if you can fix issues like this, the one I linked to above, being able to add lambda environment vars from the CLI and other common things like that, I'd be much more inclined to recommend Amplify to others. It seems like the vast majority of work for a lot of use cases is done, it's just last mile nitty gritty work. Thanks for all your efforts.

As a workaround, I set up custom SQS resource and add dependency/permission to post on it from postcomfrirmation function, finally added another trigger from SQS which writes to DynamoDB.
A little bit long way but works !

@ayeganyan can you post how you set it up?

Hi @waltermvp

  1. Create SQS in queue category:
    _amplify/backend/queue/postConfirmationQueue-cloudformation-template.json_
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Queue resource stack creation using Amplify CLI",
  "Parameters": {
    "env": {
      "Type": "String"
    }
  },
  "Conditions": {
    "ShouldNotCreateEnvResources": {
      "Fn::Equals": [
        {
          "Ref": "env"
        },
        "NONE"
      ]
    }
  },
  "Resources": {
    "SQS": {
      "Type": "AWS::SQS::Queue",
      "Properties": {
        "QueueName": {
          "Fn::If": [
            "ShouldNotCreateEnvResources",
            "postConfirmationEvent",
            {
              "Fn::Join": [
                "",
                [
                  "postConfirmationEvent",
                  "-",
                  {
                    "Ref": "env"
                  }
                ]
              ]
            }
          ]
        }
      }
    }
  },
  "Outputs": {
    "Name": {
      "Value": {
        "Ref": "SQS"
      }
    },
    "Arn": {
      "Value": {
        "Fn::GetAtt": ["SQS", "Arn"]
      }
    },
    "Region": {
      "Value": {
        "Ref": "AWS::Region"
      }
    }
  }
}
  1. Add the new resource and dependencies on it in _amlify/backend/backend-config.json_
  "queue": {
    "postConfirmationQueue": {
      "service": "SQS",
      "providerPlugin": "awscloudformation"
    }
  },
...
 "authenticationPostConfirmation": {
      "build": true,
      "providerPlugin": "awscloudformation",
      "service": "Lambda",
      "dependsOn": [
        {
          "category": "queue",
          "resourceName": "postConfirmationQueue",
          "attributes": [
            "Name"
          ]
        }
      ]
    },
 "postConfirmationQueueTrigger": {
      "build": true,
      "providerPlugin": "awscloudformation",
      "service": "Lambda"
}
  1. Add permission settings and SQS inputs for postConfirmation function in _amplify/backend/function/authenticationPostConfirmation/authenticationPostConfirmation-cloudformation-template.json_:
{
Parameters:
...
    "queuepostConfirmationQueueName": {
      "Type": "String"
      "Description": "Should be in <category><resource><output> format"
    },
    "queuepostConfirmationQueueArn": {
      "Type": "String"
    },
....
   "Environment": {
     ....
            "SQS_POSTCONFIRMATION_QUEUE": {
              "Ref": "queuepostConfirmationQueueName"
            },
    }
...
...
    "AmplifyResourcesPolicy": {
      "DependsOn": [
        "LambdaExecutionRole"
      ],
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "amplify-lambda-execution-policy",
        "Roles": [
          {
            "Ref": "LambdaExecutionRole"
          }
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "sqs:SendMessage",
                "sqs:GetQueueAttributes"
              ],
              "Resource": [
                {
                  "Fn::Sub": "${queuepostConfirmationQueueArn}"
                }
              ]
            }
          ]
        }
      }
    }
  1. Pass SQS ARN and name as input in amplify/backend/function/authenticationPostConfirmation/parameters.json:
{
  "modules": "custom",
  "resourceName": "authenticationPostConfirmation",
  "queuepostConfirmationQueueArn": {
    "Fn::GetAtt": ["queuepostConfirmationQueue", "Outputs.Arn"]
  },
  "queuepostConfirmationQueueName": {
    "Fn::GetAtt": ["queuepostConfirmationQueue", "Outputs.Name"]
  }
}
  1. Create function and add event source mapping to trigger on SQS events, pass queuepostConfirmationQueueArn and queuepostConfirmationQueueName in the same way as above: _amplify/backend/function/postConfirmationQueueTrigger/postConfirmationQueueTrigger-cloudformation-template.json_
  "Resources": {
    "LambdaFunction": {
...
  },
    "LambdaEventSourceMappingPostConfirmationQueue": {
      "Type": "AWS::Lambda::EventSourceMapping",
      "DependsOn": [
        "AmplifyResourcesPolicy",
        "LambdaExecutionRole"
      ],
      "Properties": {
        "BatchSize": 10,
        "MaximumBatchingWindowInSeconds": 5,
        "Enabled": true,
        "EventSourceArn": {
          "Fn::Sub": "${queuepostConfirmationQueueArn}"
        },
        "FunctionName": {
          "Fn::GetAtt": [
            "LambdaFunction",
            "Arn"
          ]
        }
      }
    },
...
    "AmplifyResourcesPolicy": {
      "DependsOn": [
        "LambdaExecutionRole"
      ],
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "amplify-lambda-execution-policy",
        "Roles": [
          {
            "Ref": "LambdaExecutionRole"
          }
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "sqs:ReceiveMessage",
                "sqs:DeleteMessage",
                "sqs:GetQueueAttributes"
              ],
              "Resource": [
                {
                  "Fn::Sub": "${queuepostConfirmationQueueArn}"
                }
              ]
            },
....
  1. Send to SQS in the function and receive in another function!
  const params = {
    MessageBody: item,
    QueueUrl: process.env.SQS_POSTCONFIRMATION_QUEUE,
  }
  const res = await sqs
    .sendMessage(params)
    .promise()

Hope this will help!

@waltermvp the functionality is broken in latest version (at least 4.39.0)
4.29.8 is working fine

Was this page helpful?
0 / 5 - 0 ratings