首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >appsync到appsync集成- http数据源- AWS IAM

appsync到appsync集成- http数据源- AWS IAM
EN

Stack Overflow用户
提问于 2021-01-13 09:18:28
回答 1查看 697关注 0票数 2

我正在尝试遵循最佳实践,我有两个业务模块A和B-都是使用AWS AppsyncIAM

现在我需要从模块A访问模块B。

所以我创建了HTTP数据资源

(CDK在A模块中实现)

代码语言:javascript
复制
        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);

  1. bApiRoleArn -在B模块中定义,并添加对特定查询的访问(IAM
  2. --B模块
  3. 的appsync url,“与HttpDataSourceProps一样未知”)--出于某种原因,HttpDataSourceProps不公开serviceRole (CDK专用的),因此这是一种强制的方法。(也许是因为我的交叉账户问题?)

所有的工作在单一帐户(当模块A和模块B是在同一个帐户)。但是当A和B在不同的帐户中时,我得到了一个错误:不允许交叉帐户传递角色。

问题:如何设置角色/角色/应用同步,以便在模块A和模块B位于不同的AWS帐户时工作?

另一次尝试:

在没有角色的情况下部署created)

  • Update

  • (默认角色是使用CLI:

的角色)

代码语言:javascript
复制
aws appsync update-data-source --api-id kcf4l3xkxxxxxxxcsn6cnfoxm  --name BModuleApiDS--type HTTP --service-role-arn arn:aws:iam::9999999999:role/BModuleGraphqlApi-RoleForAModule

我收到了以下错误:

代码语言:javascript
复制
An error occurred (AccessDeniedException) when calling the UpdateDataSource operation: Cross-account pass role is not allowed.

其中999999999999是B模块,account

  • 111111111111是A模块,account

  • arn:aws:iam::111111111111:user/cli是具有管理访问权限的部署用户,iam:passRole permission

  • and BModuleGraphqlApi-RoleForAModule定义为:

代码语言:javascript
复制
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "appsync:GraphQL",
            "Resource": "arn:aws:appsync:eu-west-1:999999999999:apis/kcf4l3xkxxxxxxxcsn6cnfoxm/types/Query/fields/queryForModuleA",
            "Effect": "Allow"
        }
    ]
}

与信任关系:

代码语言:javascript
复制
{
  "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?

应用同步如何简化对多个微服务()的访问

EN

回答 1

Stack Overflow用户

发布于 2021-12-01 22:05:49

这是一段时间前提出的,可能已经不再有意义了,但它可能对其他人有帮助。

到目前为止(2021年12月1日),AppSync不支持跨帐户AppSync到AppSync通信的IAM授权模式。我不能提供不支持它的低层次原因。

幸运的是,有一项工作在延迟方面有一个很小的损失。

代码语言:javascript
复制
| Account A |     | Account B |
| AppSync   | <-> | AppSync   | 

不管用,但是,

代码语言:javascript
复制
| Account A |     | Account B                    |
| AppSync   | <-> | APIGateway <-> AppSync works |

效果很好。另一个选择是使用Lambda。

代码语言:javascript
复制
| Account A          |     | Account B |
| AppSync <-> Lambda | <-> | AppSync   |

但对我来说,这个方法太复杂了。首先,您必须实现lambda。其次,你必须保持这个蓝光温暖,否则它会增加冷启动的延迟,在某些情况下可以高达20秒。因此,作为第一种方法,我将推荐AppSync <-> APIGateway <-> AppSync。

因此,在模块A调用模块B的用例中,我们仍然可以在模块A中使用HTTP数据源,但是它的实现类似于:

代码语言:javascript
复制
    // 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端点

代码语言:javascript
复制
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。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65698880

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档