我的 GraphQL API:
type MyEntity @model @auth(rules: [
{ allow: owner, ownerField: "ownerId"}
]) {
id: ID!
ownerId: String!
strFld: String!
}
现在,我想要一个 lambda(“myLambda”)来查询
MyEntity
。因此,我将 { allow: private, provider: iam }
添加到 MyEntity
,这允许 lambda 查询它(遵循 这些说明 进行 IAM 身份验证)。然而,除了允许 myLambda 访问 MyEntity
之外,它基本上绕过了所有者保护,并允许任何通过 IAM 连接的客户端编辑任何其他所有者的 MyEntity
。
例如,我没有做任何特别的事情来授予我的 React 客户端 IAM 访问权限,它通常通过用户组查询
MyEntity
。但是,只需将 React 客户端中的 graphql 查询更改为使用 GRAPHQL_AUTH_MODE.AWS_IAM,现在它就可以读取和写入 any MyEntity
,无论所有者如何。
对实体使用 IAM 身份验证时,如何限制它以便只有我的 lambda 可以访问?文档说诸如“IAM 可用于管理访问”之类的内容,但它们没有解释我可以编辑以删除访问的外部(例如,react)客户端将使用什么角色/策略/等。
经过一番挣扎后,我想我明白了。
为了使 lambda 能够调用 Amplify GraphQL API,您需要在 API 中添加身份验证规则,如
{ allow: private, provider: iam }
。您还可以执行 amplify function update
并授予您的函数调用 API 的权限,这将更新该 lambda 的执行角色以有权调用 API。
但是,在 API 中添加 auth 规则还有另一个效果:如果您使用 Cognito 身份验证,它还会将调用 API 的权限添加到身份池使用的“authRole”,这意味着任何登录的用户现在可以进行 IAM 查询来访问此 API。
我不想这样——我试图只授予对 lambda 的访问权限,而不是整个世界。事实上,我不希望我的 Cognito 用户进行任何 IAM 查询(他们应该只使用用户池身份验证),因此我创建了一个额外的空角色并修改了我的身份池以将其用作其 authRole。不幸的是,这是一个巨大的痛苦。我必须为角色创建一个自定义资源,然后覆盖 amplify auth涉及在打字稿中编写 CDK 代码,当它第一次不编译时很难排除故障(编译会生成非常模糊的编译器错误)。
但无论如何,这似乎有效。这就是我所做的:
amplify custom add
为我的空角色添加新资源:
"IdentityPoolAuthRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": {
"Fn::Sub": [
"(myapp)IdentityPoolAuthRole-${env}",
{
"env": {
"Ref": "env"
}
}
]
},
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
}
}
注意:理想情况下,该角色会在其 AssumeRolePolicyDocument 中指定身份池 ID,但这会导致不同环境中的不同身份池出现问题。
然后,
amplify override auth
并将其放入 override.ts 中:
import { AmplifyAuthCognitoStackTemplate, AmplifyProjectInfo } from '@aws-amplify/cli-extensibility-helper';
export function override(resources: AmplifyAuthCognitoStackTemplate, amplifyProjectInfo: AmplifyProjectInfo) {
resources.identityPoolRoleMap.roles["authenticated"] = "(arn of the role created above)-" + amplifyProjectInfo.envName;
}
在我看来,这是一个问题,一旦你授予 lambda 调用放大 API 的权限,就很难保证它的安全。
不幸的是与此相关的放大说明没有提及这一点。
允许:私人/公共非常令人困惑......可能应该是: 允许: guest/loggedInUser/serviceUser 或类似的东西...