我目前正在使用 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's post ,它确实让我找到了解决方案。
请注意,我安装了不需要的 AWS AppSync 客户端,但它简化了过程(否则您必须自己签署 URL。有关这一点,请参阅 Adrian Hall 的帖子)。
有几件事:
cross-fetch
来填充“fetch” (否则,您将受到来自 AppSync 内部使用的 Apollo Client 的 Invariant Violation 的影响)。 ["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"
}
您可以进一步restrict here in the following fashion :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 的全部访问权限。在您的 .gql 文件(AppSync GraphQL 架构)中,将 @aws_iam 指令添加到用于将订阅发送到的突变,以限制来自前端的访问。
type Mutation {
addUsersMutationSubscription(
input: AddUsersSagaResultInput!
): AddUsersSagaResult @aws_iam
}
关于amazon-web-services - 如何使用 IAM 通过 AWS Lambda 调用 AppSync?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67244764/