aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
89 stars 77 forks source link

Amplify and AppSync - Trying to Call a Lambda Function from an AppSync Pipeline Resolver #1472

Closed defish1962 closed 10 months ago

defish1962 commented 1 year ago

Amplify CLI Version

11.1.1

Question

I am attempting to call a Lambda function from an extended pipeline resolver, but the Lambda function is never invoked.

I have Amplify generated pipeline resolvers for my queries and mutations. I have a mutation called deleteToDo. Before the ToDo can be deleted, I need to check the row in the DynamoDB database to see if the requester belongs to the group that owns the ToDo item.

I have created a Lambda function that does a getToDo call, passing the ID of the ToDo. I then compare the returned groupID with the groupID included in the JWT Token (from a Cognito custom attribute, currentGroup).

The Lambda function is working fine, but when I attempt to call it from the Mutation.deleteToDo.postAuth.2.req.vtl resolver, I get nothing back. If I check the Cloudwatch logs for the Lambda function, it doesn't show anything (no request, no errors).

Here is the code for my resolver (Note, I am just trying to get the Lambda function called and see the result, so the logic isn't complete):

`## [Start] Sandbox Mode Disabled. **

set($lambdaFunctionArn = "arn:aws:lambda:us-east-2:[accountid]:function:VerifyGroupMembership-authres")

$util.log.info("Version 5")

set($id = $ctx.args.input.id)

set($groupID = $ctx.identity.claims.get("custom:currentGroup"))

set($payload = {

"fieldName": "getToDo", "id": $id, "claimsGroupID": $groupID })

$util.log.info("Payload: $payload")

set($invokeLambda = {

"version": "2018-05-29", "operation": "Invoke", "payload": { "functionArn": $lambdaFunctionArn, "arguments": $util.toJson($payload), "request": $util.toJson($ctx.request) } }) $util.log.info("InvokeLambda value: $invokeLambda")

set($response = $util.executeAwsServiceAction($invokeLambda))

$util.log.info("Lambda function response: $response")

set($parsedResponse = $util.parseJson($response))

$util.log.info("Parsed Response: $parsedResponse")

set($body = $util.parseJson($parsedResponse.payload.body))

$util.log.info("Body: $body")

$util.toJson({})

[End] Sandbox Mode Disabled. **

` $response is showing as null when the resolver runs.

I have looked at numerous tutorials and the documentation, but have to admit I am somewhat confused by it all. Since I am using Amplify and Amplify generated resolvers, many of the tutorials don't work with my situation.

I would like to know if it is possible to make a call from a pipeline resolver to a Lambda function, get the value back, and then either prevent the request from going through (not authorized), or let it continue if the user is authorized.

If it is possible, what are the steps that need to be taken. I am confused by the user of the CustomResources.json file. Do I need to add anything there to make this work?

What else am I missing? It would seem that an error response should be generated at least if there is a problem with the configuration, permissions, etc. I simply get no information back from my attempted call to the Lambda function, which is pretty frustrating since I don't know what is needed to make this work.

Thanks for any assistance you can offer.

AnilMaktala commented 1 year ago

Hey @defish1962 šŸ‘‹, Thank you for raising this issue. To determine if the logged-in user group corresponds to the owner of the row being deleted, you can utilize group-based data access. We recommend referring to the relevant section for guidance on resolving your issue. Kindly let us know if this resolves your concern.

defish1962 commented 1 year ago

Hi @AnilMaktala, thanks for your response! I neglected to mention that we are using the Amplify DataStore which does not support OwnerFIeld data access in a multi-tenant environment, and the static group-based data access option will not work for us as there will be hundreds of groups using the app. In other words, we need to restrict access to users who belong to the groupID associated with the row of data in the DynamoDB table.

I was able to get a query to work from a preUpdate resolver, after going into the functions in the AppSync console and specifying a data source. The function defaults to None_DS as the data source.

I know this is different than my original question, but I would still like to know if it is possible to call a Lambda function from a pipeline resolver mapping template. The error messages I got when trying to invoke the Lambda function were either terse or non-existent. I could see by the lack of Lambda function Cloudwatch log data that the function was not being invoked but had no idea how to troubleshoot the issue from the resolver code.

Thanks for any pointers or suggestions you might be able to provide.

BBopanna commented 11 months ago

+1

AWS team - atleast bother to respond on if this is possible or not

phani-srikar commented 11 months ago

Hi @defish1962, it is possible to attach a Lambda data source to the custom resolver you have. You would need to add your lambda function as a data source for your AppSync API and appropriate permissions for the lambda to be successfully invoked by AppSync:

{
    "Action": "sts:AssumeRole",
    "Effect": "Allow",
    "Principal": {
      "Service": "appsync.amazonaws.com"
    }
 }

However, going through your use-case, you might not need a lambda function to fetch the existing record. For the update and delete operations for example, we already fetch the existing record in the auth.1.req.vtl resolver slots when your model has dynamic userpool authorization rule attached to it. So you can just override the auth.1.res.vtl (response mapping template) to add your custom Auth logic. Having said that, have you considered using the dynamic cognito group based authorization strategy? That would allow you to store multiple groups that can access a record and is supported out-of-the-box.

AnilMaktala commented 10 months ago

Hey šŸ‘‹ , This issue is being closed due to inactivity. If you are still experiencing the same problem and need further assistance, please feel free to leave a comment. This will enable us to reopen the issue and provide you with the necessary support.