簡體   English   中英

如何使用 IAM 通過 AWS Lambda 調用 AppSync?

[英]How can I use IAM to invoke AppSync wtihin AWS Lambda?

我目前正在使用 AppSync 在 AWS Lambda 中實施訂閱突變。 我想使用 IAM 並避免使用任何其他類型的 AUTH 機制,因為我在 AWS 堆棧中調用它。 不幸的是,我收到以下 403 錯誤:

(摘自 SQS 的 CloudWatch 日志)

 {
    "errorMessage": "Response not successful: Received status code 403",
    "name": "ServerError",
    "errorType": "UnrecognizedClientException",
    "message": "The security token included in the request is invalid."
 }

我試過遵循這些無濟於事,但我不知道我錯過了什么:

這是我當前調用它的代碼:

import AWS from "aws-sdk";
import { AWSAppSyncClient } from "aws-appsync";
import { Mutation, mutations } from "./mutations/";
import "cross-fetch/polyfill";

/**
 *
 */

AWS.config.update({
  region: Config.region,
});

export class AppSyncClient {
  client: AWSAppSyncClient<any>;
  constructor() {
    if (!env.APPSYNC_ENDPOINT) {
      throw new Error("APPSYNC_ENDPOINT not defined");
    }

    /**
     * We create the AppSyncClient with the AWS_IAM
     * authentication.
     */
    this.client = new AWSAppSyncClient({
      url: env.APPSYNC_ENDPOINT,
      region: Config.region,
      auth: {
        credentials: AWS.config.credentials!,
        type: "AWS_IAM",
      },
      disableOffline: true,
    });
  }

  /**
   * Sends a mutation on the AppSync Client
   * @param mutate The Mutation that will be sent with the variables.
   * @returns
   */
  sendMutation(mutate: Mutation) {
    const mutation = mutations[mutate.type] as any;
    const variables = mutate.variables;
    console.log("Sending the mutation");
    console.log("Variables is ", JSON.stringify(variables));
    return this.client.mutate({
      mutation,
      fetchPolicy: "network-only",
      variables,
    });
  }
}

這是來自 Lambda SQS 的當前 IAM:

{
    "Statement": [
        {
            "Action": [
                "appsync:GraphQL"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:appsync:us-east-2:747936726382:apis/myapi"
            ]
        }
    ],
    "Version": "2012-10-17"
}

我知道這不是來自 lambda 的 IAM 問題,因為我已經嘗試暫時授予它完全訪問權限,但仍然出現 403 錯誤。

我還驗證了 AppSync 配置了 IAM 權限(作為附加提供者)。

你們有什么想法嗎? 我印象深刻的是,這是一個幾乎沒有配置參考的鬼主題。

我終於搞定了。 我第三次去重讀了Adrian Hall 的帖子,它確實讓我找到了解決方案。

請注意,我安裝了不需要但簡化了流程的 AWS AppSync 客戶端(否則您必須自己簽署 URL。有關詳情,請參閱 Adrian Hall 的帖子)。

有幾件事:

  • 您需要通過包含cross-fetch來填充“提取”(否則您將受到來自 AppSync 內部使用的 Apollo 客戶端的不變違規的影響)。
  • 您需要將 lambda 的內部 IAM 憑證(我什至不知道存在)傳遞給 AppSyncClient 的配置部分。
  • 您需要為 lambda 的 IAM 角色添加適當的權限,在這種情況下: ["appsync:GraphQL"]用於操作。

這是一些代碼:

這是 AppSync 代碼。

// The code is written in TypeScript.
// https://adrianhall.github.io/cloud/2018/10/26/backend-graphql-trigger-appsync/
// https://www.edwardbeazer.com/using-appsync-client-from-lambda/
import { env } from "process";
import { Config, env as Env } from "../../../../shared";
// This is such a bad practice
import AWS from "aws-sdk";
import { AWSAppSyncClient } from "aws-appsync";
import { Mutation, mutations } from "./mutations/";
// Very important, otherwise it won't work!!! You'll have Invariant Violation 
// from Apollo Client.
import "cross-fetch/polyfill";

/**
 *
 */
AWS.config.update({
  region: Config.region,
  credentials: new AWS.Credentials(
    env.AWS_ACCESS_KEY_ID!,
    env.AWS_SECRET_ACCESS_KEY!,
    env.AWS_SESSION_TOKEN!
  ),
});

export class AppSyncClient {
  client: AWSAppSyncClient<any>;
  constructor() {
    // Your AppSync endpoint - The Full URL.
    if (!Env.APPSYNC_ENDPOINT) {
      throw new Error("APPSYNC_ENDPOINT not defined");
    }

    /**
     * We create the AppSyncClient with the AWS_IAM
     * authentication.
     */
    this.client = new AWSAppSyncClient({
      url: Env.APPSYNC_ENDPOINT,
      region: Config.region,
      auth: {
        credentials: AWS.config.credentials!,
        type: "AWS_IAM",
      },
      disableOffline: true,
    });
  }

  /**
   * Sends a mutation on the AppSync Client
   * @param mutate The Mutation that will be sent with the variables.
   * @returns
   */
  // The mutation is a object that holds the mutation in 
  // the `gql` tag. You can ommit this part. 
  sendMutation(mutate: Mutation) {
    const mutation = mutations[mutate.type] as any;
    const variables = mutate.variables;
    // This is the important part.
    return this.client.mutate({
      mutation,
      // Specify "no-cache" in the policy. 
      // network-only won't work.
      fetchPolicy: "no-cache",
      variables,
    });
  }
}

我們需要在 AppSync 授權機制中啟用 IAM。 是的,可以啟用多個身份驗證。 我目前正在同時使用 OPEN_ID 和 IAM。

https://us-east-2.console.aws.amazon.com/appsync/home?region=us-east-2#/myappsync-id/v1/settings

在此處輸入圖像描述

這是執行 GQL 的 Lambda IAM 策略:

{
    "Statement": [
        {
            "Action": [
                "appsync:GraphQL"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:appsync:us-east-2:747936726382:apis/ogolfgja65edlmhkcpp3lcmwli/*"
           
            ]
        }
    ],
    "Version": "2012-10-17"
}

您可以通過以下方式進一步限制此處arn:${Partition}:appsync:${Region}:${Account}:apis/${GraphQLAPIId}/types/${TypeName}/fields/${FieldName}

arn:aws:appsync:us-east-2:747936726382:apis/ogolfgja65edlmhkcpp3lcmwli/types/Mutation/field/myCustomField"

請注意,我們需要更好地限制這一點,因為我們目前授予它對 API 的完全訪問權限。

在 your.gql 文件(AppSync GraphQL 架構)中,將 @aws_iam 指令添加到用於將訂閱發送到的突變中,以限制來自前端的訪問。

  type Mutation {
  addUsersMutationSubscription(
    input: AddUsersSagaResultInput!
  ): AddUsersSagaResult @aws_iam
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM