从外部服务器访问这些 appsync graphql 资源的正确方法是什么?

What would be the correct way to access these appsync graphql resources from external server?

我有一个 amplify 项目,其中包含一个通过 amplify-cli 设置的 appsync graphql api。该项目具有认知用户池集成。我的目标是让外部服务器上的 nodeJS 脚本对我的 graphql api 执行查询。我的问题与为架构设置身份验证的正确方法有关...

我想访问的特定模型的摘录:

type Phase @model @auth(rules: [
{allow: private, provider: iam}
{allow: groups, groups: ["companyAdmin"], provider: userPools},
{allow: groups, groups: ["extConnection"], operations: [create, read, update], provider: userPools},
{allow: groups, groupsField: "readGroups", operations: [create, read], provider: userPools},
{allow: groups, groupsField: "editGroups", provider: userPools}]) {
    id: ID!
    description: String
    editGroups: [String]
    readGroups: [String]
}

我的困惑源于阅读有关如何通过 nodejs @aws-sdk v3 调用应用程序同步客户端端点的文档。

Here it seems they are referring to using the connection profiles that have an iam access key id and secrey key: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html

如果我创建一个 IAM 用户并为其提供内置的应用程序同步访问策略:

AWSAppSyncSchemaAuthor ::: AWS managed: Provides access to create, update, and query the schema.

AWSAppSyncPushToCloudWatchLogs ::: AWS managed: Allows AppSync to push logs to user's CloudWatch account.

因为我的模型有一个 iam

的授权规则

{allow: private, provider: iam}

我应该能够允许特定的 IAM 角色或用户访问这些,方法是将此用户添加到我的放大应用程序配置中的自定义 roles.json(因为 allow private iam 上面的行显然只允许来自自动生成范围缩小规则的 iam 请求):https://docs.amplify.aws/cli/graphql/authorization-rules/#use-iam-authorization-within-the-appsync-console ....

然而,这并不理想,因为我在架构中有许多其他模型需要来自内部 lambda 函数的 IAM 交互,但是现在这个 IAM 用户可以访问任何具有 allow 的模型:private provider: iam 因此问题...

  1. 我能否为 IAM 提供商的 @auth 指令制定细化规则,以限制特定 IAM 用户对模型的访问?

  1. 或者我是否应该使用来自我的用户池之一的 cognito 用户,该用户具有满足此模型的身份验证规则的组“extConnection”:

{allow: groups, groups: ["extConnection"], operations: [create, read, update], provider: userPools},

但是我将如何通过 axios npm 包之类的东西构建对此的请求来进行查询?我是否需要创建一个 REST API 网关来作为外部服务器和 graphql 端点之间的中间人来处理这个问题?

我最终找到了通过认知用户池进行身份验证的解决方案。

  1. 该用户需要访问的表,我必须受用户组限制,在本例中为“extConnection”。所以我将这个组添加到用户帐户中。然后我使用此人在这里编写的指南来找到我的解决方案:https://www.fullsapps.com/2019/02/calling-aws-appsync-or-any-graphql-api_14.html .
  2. 然后我使用 npm 包 'amazon-cognito-identity-js' 和 'graphql-request' 构建了认知身份验证握手 headers 和 return 访问令牌。
  3. 我使用访问令牌发出 gql 请求,然后return编辑了所需的数据。

示例代码:

(async () => {
    /* these will need to be updated for each environment */
    const USER_NAME = 'yourusername';
    const PASS_WORD = 'yourpassword';
    const USER_POOL_ID = 'cognitopoolid';
    const CLIENT_ID = 'cognitopoolclientid';
    const ENDPOINT = 'appsyncgraphqlendpointurl';

    /* ************************************************************************ */


    function authUser() {
        // authenticates with cognito to receive the access tokens.
        return new Promise((resolve, reject) => {
            const authenticationData = {
                Username: USER_NAME,
                Password: PASS_WORD
            };
            const authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
            const poolData = {
                UserPoolId: USER_POOL_ID,
                ClientId: CLIENT_ID
            }
            const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
            const userData = {
                Username: authenticationData.Username,
                Pool: userPool
            }
            const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);

            cognitoUser.authenticateUser(authenticationDetails, {
                onSuccess: function (result) {
                    const idToken = result.getIdToken().getJwtToken();
                    const accessToken = result.getAccessToken().getJwtToken();
                    const refreshToken = result.getRefreshToken().getToken();

                    // idToken serves our purposes for now
                    resolve(idToken);
                },
                onFailure: function (err) {
                    reject(err.message);
                }
            });
        });
    }

    async function makeQuery(gqlc) {

        const query = `mutation MyMutation {
          createPayout(input: 
            {
              status: "Pending"
            }
          ) 
          {
            id
            status
            _version
          }
        }`;
        return gqlc.request(query);
    }

    const token = await authUser();
    /* preferably cache the token somewhere and reuse in the future until it 
       expires, then re-auth */
      
    console.log(token);

    const gqlClient = new GraphQLClient(ENDPOINT, {
        headers: {
            Authorization: token
        }
    });

    
    const res = await makeQuery(gqlClient);

    console.log(JSON.stringify(res));
    }
  )();