简体   繁体   中英

Unable to auth into AppSync GraphQL api from Lambda using IAM and AppSyncClient

I'm using an amplify stack and need to perform some actions to my graphql api which has dynamodb behind it. The request in my lambda function returns an Unauthorized error: "Not Authorized to access getSourceSync on type SourceSync", where getSourceSync is the gql query and SourceSync is the model name.

My schema.grapqhl for this particular model is set up as following. Note auth rule allow private provider iam:

type SourceSync @model (subscriptions: { level: off }) @auth(rules: [
    {allow: private, provider: iam}
    {allow: groups, groups: ["Admins"], provider: userPools},
    {allow: groups, groups: ["Users"], operations: [create], provider: userPools},
    {allow: groups, groupsField: "readGroups", operations: [create, read], provider: userPools},
    {allow: groups, groupsField: "editGroups", provider: userPools}]) {
    id: ID! @primaryKey
    name: String
    settings_id: ID @index(name: "bySettingsId", queryField: "sourceSyncBySettingsId")
    settings: Settings @hasOne(fields: ["settings_id"])
    childLookup: String
    createdAt: AWSDateTime!
    updatedAt: AWSDateTime!
    _createdBy: String
    _lastChangedBy: String
    _localChanges: AWSJSON
    readGroups: [String]
    editGroups: [String]
}

My lambda function's role has the following inline policy attached to it. (Actual ID values have been omitted for security purposes on this post):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:us-east-1:111myaccountID:apis/11mygraphqlapiID/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "appsync:GetType"
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        }
    ]
}

And finally my lambda function is set up as follows with a simple query test:

/* stuff */

"use strict";
const axios = require("axios");
const awsAppSync = require("aws-appsync").default;
const gql = require("graphql-tag");
require("cross-fetch/polyfill");
const { PassThrough } = require("stream");
const aws = require("aws-sdk");

aws.config.update({
    region: process.env.AWS_REGION,

});

const appSync = new aws.AppSync();

const graphqlClient = new awsAppSync({
    url: process.env.API_GRAPHQLAPIENDPOINTOUTPUT,
    region: process.env.AWS_REGION,
    auth: {
        type: "AWS_IAM",
        credentials: aws.config.credentials,
    },
    disableOffline: true
});

exports.handler = async (event, context) => {
    
    console.log('context :: '+JSON.stringify(context));
    
    console.log('aws config :: '+JSON.stringify(aws.config));
    
          const sourceSyncTypes = await appSync
          .getType({
            apiId: process.env.API_GRAPHQLAPIIDOUTPUT,
            format: "JSON",
            typeName: "SourceSync",
          })
          .promise();
          console.log('ss = '+JSON.stringify(sourceSyncTypes));
    
    try {
    const qs = gql`query GetSourceSync {
  getSourceSync(id: "ov3") {
    id
    name
  }
}`;
    const res = await graphqlClient.query({query: qs, fetchPolicy: 'no-cache'});
    console.log(JSON.stringify(res));
    
    }
    catch(e) {
        console.log('ERR :: '+e);
        console.log(JSON.stringify(e));
    }
    
};

Found the solution, there seems to be an issue with triggering a rebuild of the resolvers on the api after permitting a function to access the graphql api. However there is a distinction to note:

  1. If the graphql api is part of an amplify app stack, then only functions created through the amplify cli for that app (ex: amplify add function ) and that are given access to the api through there will be able to access the api.

    • additonally during the update when you either create, or update the function to give it permissions, you must ensure that during the amplify push operation, the api stack will also be updating. you can trigger this by simply adding or removing a space in a comment inside of your amplify/backend/api//schema.graphql file.
  2. If the function was created "adhoc" directly through the aws console, but it is trying to access a graphql api that was created as part of an amplify app stack, then you will need to put that function's role in amplify/backend/api/< apiname>/custom-roles.json in the format

    { "adminRoleNames": ["<role name>", "<role name 2>", ...] }

Documentation references here .

  1. If neither your api or lambda function were created with the amplify cli as part of an app stack, then just need to give access to the graphql resources for query, mutation and subscription to the lambda's role in IAM, via inline policies or a pre-defined policy.

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