我正在尝试遵循最佳实践,我有两个业务模块A和B-都是使用AWS Appsync和IAM。
现在我需要从模块A访问模块B。
所以我创建了HTTP数据资源
(CDK在A模块中实现)
const bModuleApiDS = new HttpDataSource(this, 'BModuleApiDS', {
api: this.api,
endpoint: bApiEndpoint,
name: 'BModuleApiDS',
description: `Data source for : ${bApiEndpoint}`,
authorizationConfig: {
signingRegion: 'eu-west-1',
signingServiceName: 'appsync',
},
serviceRole: iam.Role.fromRoleArn(this, 'ServiceRoleForApiDS', bApiRoleArn),
} as unknown as HttpDataSourceProps);所有的工作在单一帐户(当模块A和模块B是在同一个帐户)。但是当A和B在不同的帐户中时,我得到了一个错误:不允许交叉帐户传递角色。
问题:如何设置角色/角色/应用同步,以便在模块A和模块B位于不同的AWS帐户时工作?
另一次尝试:
在没有角色的情况下部署created)
的角色)
aws appsync update-data-source --api-id kcf4l3xkxxxxxxxcsn6cnfoxm --name BModuleApiDS--type HTTP --service-role-arn arn:aws:iam::9999999999:role/BModuleGraphqlApi-RoleForAModule我收到了以下错误:
An error occurred (AccessDeniedException) when calling the UpdateDataSource operation: Cross-account pass role is not allowed.其中999999999999是B模块,account
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "appsync:GraphQL",
"Resource": "arn:aws:appsync:eu-west-1:999999999999:apis/kcf4l3xkxxxxxxxcsn6cnfoxm/types/Query/fields/queryForModuleA",
"Effect": "Allow"
}
]
}与信任关系:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::111111111111:root",
"arn:aws:iam::111111111111:user/cli"
],
"Service": "appsync.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}同样的问题:如何设置角色/角色/应用同步,以便模块A可以使用IAM授权(而不是api密钥)访问不同AWS帐户中的模块B?
应用同步如何简化对多个微服务()的访问
发布于 2021-12-01 22:05:49
这是一段时间前提出的,可能已经不再有意义了,但它可能对其他人有帮助。
到目前为止(2021年12月1日),AppSync不支持跨帐户AppSync到AppSync通信的IAM授权模式。我不能提供不支持它的低层次原因。
幸运的是,有一项工作在延迟方面有一个很小的损失。
| Account A | | Account B |
| AppSync | <-> | AppSync | 不管用,但是,
| Account A | | Account B |
| AppSync | <-> | APIGateway <-> AppSync works |效果很好。另一个选择是使用Lambda。
| Account A | | Account B |
| AppSync <-> Lambda | <-> | AppSync |但对我来说,这个方法太复杂了。首先,您必须实现lambda。其次,你必须保持这个蓝光温暖,否则它会增加冷启动的延迟,在某些情况下可以高达20秒。因此,作为第一种方法,我将推荐AppSync <-> APIGateway <-> AppSync。
因此,在模块A调用模块B的用例中,我们仍然可以在模块A中使用HTTP数据源,但是它的实现类似于:
// A role in Module A that AppSync will assume to get permissions
// to invoke APIGateway endpoint in Module B
const bModuleDSRole = new Role(this, 'BModuleDSRole', {
roleName: 'BModuleDSRole',
assumedBy: new ServicePrincipal('appsync.amazonaws.com')
});
new Policy(this, 'BModuleDSPolicy', {
policyName: 'BModuleDSPolicy',
roles: [bModuleDSRole],
statements: [
new PolicyStatement({
actions: [
"execute-api:Invoke"
],
resources: [ <bAPIGwEndpointArn> ]
})
]
});
const bModuleDataSource = new CfnDataSource(this, 'BModule', {
apiId: props.apiId,
name: 'BModule',
type: "HTTP",
httpConfig: {
endpoint: <bAPIGwEndpoint>,
authorizationConfig: {
authorizationType: "AWS_IAM",
awsIamConfig: {
signingRegion: <region>,
signingServiceName: "execute-api"
}
}
},
serviceRoleArn: bModuleDSRole.roleArn
});在模块B上,我们创建了一个包含以下元素的APIGateway端点
import { Construct } from 'monocdk';
import { Stage } from '../config/Stages';
import { AuthorizationType as apigateway_auth_type, AwsIntegration, RestApi,} from 'monocdk/aws-apigateway';
import { GraphqlApi } from 'monocdk/aws-appsync';
import { APIGResourcePolicy } from '@amzn/fin_connect_constructs';
import { Effect, Policy, PolicyStatement, Role, ServicePrincipal } from 'monocdk/aws-iam';
export interface RestApiEndpointProps {
stage: Stage,
api: GraphqlApi;
}
export class RestApiEndpoint extends Construct {
readonly apiId: string;
constructor(scope: Construct, id: string, props: RestApiEndpointProps) {
super(scope, id);
// A role in Module B that APIGateway can assume to invoke AppSync
// endpoint also from Module B
// Configure access to MODULEB API
const moduleBRestApiRole = new Role(this, 'MODULEBRestApiRole', {
assumedBy: new ServicePrincipal('apigateway.amazonaws.com'),
roleName: 'MODULEBRestApiRole',
});
new Policy(this, 'MODULEBRestApPolicy', {
policyName: 'MODULEBRestApPolicy',
roles: [moduleBRestApiRole],
statements: [
new PolicyStatement({
actions: [
"appsync:GraphQL"
],
effect: Effect.ALLOW,
resources: [`${props.api.arn}/types/Query/*`]
})
]
});
// A resource policy allow listing the role from Module A.
// the props.stage.apigResourceAccess is something similar to
//apigResourceAccess: [
// {
// "principle": 'arn:aws:iam::112233445566:role/BModuleDSRole',
// "resources": [`execute-api:/prod/*/*`],
// "actions": ['execute-api:Invoke']
// },
//],
const resourcePolicy = new APIGResourcePolicy(this, "APIGResourcePolicy", {
apigResourceAccess: props.stage.apigResourceAccess
});
const api = new RestApi(this, 'moduleb-api-gateway', {
policy: resourcePolicy.policyDocument
});
// This integration will build the AppSync endpoint URL automatically,
// we just have to provide the subdomain of the endpoint Warning not the
// AppSync endpoint API ID but, the subdomain.
const appsyncIntegration = new AwsIntegration({
service: 'appsync-api',
options: {
credentialsRole: moduleBRestApiRole,
integrationResponses: [{
statusCode: '200',
}],
},
path: 'graphql',
region: props.stage.region,
subdomain: props.stage.apiSubdomain,
});
api.root.addMethod('POST', appsyncIntegration, {
authorizationType: apigateway_auth_type.IAM,
methodResponses: [{
statusCode: '200',
}],
});
}
}仅此而已。来自模块B的APIGateway将接收来自AppSync模块A的请求,并将它们转发给AppSync模块B。在响应中,响应将把响应从AppSync模块B传递给AppSync模块A。
https://stackoverflow.com/questions/65698880
复制相似问题