简体   繁体   中英

AWS Lambda function unable to access AppSync GraphQL API - permission denied

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM