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.