4

I am having trouble calling an AppSync GraphQL query via a AWS Lambda function. I have been using the code in this article, specifically the latter part that uses IAM permissions: https://docs.amplify.aws/lib/graphqlapi/graphql-from-nodejs/q/platform/js#signing-a-request-from-lambda

const https = require("https");
const AWS = require("aws-sdk");
const urlParse = require("url").URL;
const appsyncUrl = process.env.API_MYAPP_GRAPHQLAPIENDPOINTOUTPUT;
const region = process.env.REGION;
const endpoint = new urlParse(appsyncUrl).hostname.toString();
const graphqlQuery = require("./query.js").query;

exports.handler = async (event) => {
  const req = new AWS.HttpRequest(appsyncUrl, region);

  req.method = "POST";
  req.path = "/graphql";
  req.headers.host = endpoint;
  req.headers["Content-Type"] = "application/json";
  req.body = JSON.stringify({
    query: graphqlQuery,
    operationName: "list",
  });

  const signer = new AWS.Signers.V4(req, "appsync", true);
  signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate());

  const data = await new Promise((resolve, reject) => {
    const httpRequest = https.request({ ...req, host: endpoint }, (result) => {
      result.on("data", (data) => {
        resolve(JSON.parse(data.toString()));
      });
    });

    httpRequest.write(req.body);
    httpRequest.end();
  });

  return {
    statusCode: 200,
    body: data,
  };
};

I am using the Amplify CLI. I used the CLI to create the function and ensure it is given access to the GraphQL API.

The specific error I get in the Lambda is:

      {
  "statusCode": 200,
  "body": {
    "errors": [
      {
        "errorType": "UnauthorizedException",
        "message": "Permission denied"
      }
    ]
  }
}

GraphQL is set-up to use Cognito user pool as authentication and I've added IAM as a secondary authentication mechanism via the Amplify CLI. The AWS GraphQL console shows that I have Cognito as my primary authentication mechanism and IAM as secondary.

The Lambda function appears to be permissioned okay as it shows 4 resources (create, update, delete, read) corresponding to the API and Allow: appsync:GraphQL as the Action.

If I run the function locally using amplify mock function myfunction then it executes fine and the result of the GraphQL query is returned correctly.

I can also run the same query successfully via the AppSync UI when I choose IAM as the authentication mechanism.

The table I am accessing is defined in my schema.graphql as:

 type Business
  @model
  @auth(
    rules: [
      { allow: owner }
      { allow: groups, groups: ["Admin"] }
      { allow: private, provider: iam }
    ]
  ) {
  id: ID!
  owner: String!
  name: String!
  emailSuffix: String!
  shortCode: String!
}

I have removed the Auth from the model and that doesn't make a difference.

I've deleted the function and re-created it in case the permissions had somehow got messed up.

So I don't think it is the code, seems to be a permissions error. I'm at a loss as to where the issue could be

UPDATE I have amended the permissions policy inside IAM Manager for the amplify-lambda-execution policy and that appears to have fixed the issue.

The permissions policy initially added by Amplify was of the form:

arn:aws:appsync:MYREGION:MYID:apis/MYAPIID/types/create/*
arn:aws:appsync:MYREGION:MYID:apis/MYAPIID/types/read/*
arn:aws:appsync:MYREGION:MYID:apis/MYAPIID/types/edit/*
arn:aws:appsync:MYREGION:MYID:apis/MYAPIID/types/delete/*

amending this to:

arn:aws:appsync:MYREGION:MYID:apis/MYAPIID/types/*/fields/* 
arn:aws:appsync:MYREGION:MYID:apis/MYAPIID

allows the lambda function to execute and successfully execute the GraphQL query on my table. So it appears to be a problem with the permissions that Amplify adds to the function. Manually overwriting these isn't a great solution.

1 Answer 1

1

The problem started after installed - amplify cli "4.45.2". The old code for autogenerated permissions in the lambda cloudformation template looked like this.

            {
          "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": "myApiGraphQLAPIIdOutput"
                  },
                  "/*"
                ]
              ]
            }
          ]
        }

But after I moved to amplify cli "4.45.2" and give lambda permissions for appsync. It generated :

    {
          "Effect": "Allow",
          "Action": [
            "appsync:GraphQL"
          ],
          "Resource": [
            {
              "Fn::Join": [
                "",
                [
                  "arn:aws:appsync:",
                  {
                    "Ref": "AWS::Region"
                  },
                  ":",
                  {
                    "Ref": "AWS::AccountId"
                  },
                  ":apis/",
                  {
                    "Ref": "myApiGraphQLAPIIdOutput"
                  },
                  "/types/create/*"
                ]
              ]
            },
            {
              "Fn::Join": [
                "",
                [
                  "arn:aws:appsync:",
                  {
                    "Ref": "AWS::Region"
                  },
                  ":",
                  {
                    "Ref": "AWS::AccountId"
                  },
                  ":apis/",
                  {
                    "Ref": "myApiGraphQLAPIIdOutput"
                  },
                  "/types/read/*"
                ]
              ]
            },
            {
              "Fn::Join": [
                "",
                [
                  "arn:aws:appsync:",
                  {
                    "Ref": "AWS::Region"
                  },
                  ":",
                  {
                    "Ref": "AWS::AccountId"
                  },
                  ":apis/",
                  {
                    "Ref": "myApiGraphQLAPIIdOutput"
                  },
                  "/types/update/*"
                ]
              ]
            }
          ]
        }


enter code here

And I got error "permission denied" when trying to reach appsync from lambda.

I think the new cli has some bug when generating appsync permissions for lambda.

I manually moved back on the old generated code in the lambda cloudformation file and it worked.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for sharing the cloud formation files. That is helpful. I am running 4.44.2 of the Amplify CLI. I've not upgraded to 4.45.2. Must be an issue with both versions of the CLI. Updating the cloud formation file manually is better than manually tweaking the permissions via the UI.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.