美文网首页
AWS中Lambda跨账户跨VPC连接DynamoDB

AWS中Lambda跨账户跨VPC连接DynamoDB

作者: evanzhousy | 来源:发表于2018-12-03 17:04 被阅读0次

概述

楼主最近做了一个项目,需要Lambda去连接一个DynamoDB,难度在于Lambda和DynamoDB分别在两个AWS账户中,同时Lambda处于也要连接RDS的需要,跟RDS也放在同一个VPC中,这无异于再增加了一层难度,也就是说Lambda的traffic需要通过VPC Endpoint先出VPC才能连接DynamoDB。与此同时还有权限问题和身份问题,Lambda需要assume role的权限来操控另一个账户的DynamoDB, 楼主将一步一步来解析这些是如何实现。

建立权限

首先需要给Lambda Function建立一个单独的身份(role), 除了给到你Lambda本身需要的那这些基本权限诸如RDS/CloudWatch的读写权限以外,还需要增加两个规则,一个是AWS提供的VPC读写权限,一个是自定义的AssumeRole Police在Lambda所在的账户中(这里假定是A账户),因为Lambda本身是没有权限去读写在另一个账户的任何资源的,只能通过assume role到DynamoDB所在的AWS账户中(这里假定是B账户)的DynamoDB所绑定的角色来进行读写操作.

以下是账户A中Lambda的身份(role)中拥有的VPC权限和Assume Role权限, 注意Resource指定的Arn号码对应的是B账户中的账户B中DynamoDB所依附的身份(role):

以下是账户B中DynamoDB所依附的身份(role)中所依附的权限规则, 包含了要显式信任的账户A的Lambda身份资源号码(ARN):

以下是账户B中DynamoDB所依附的身份(role)中所依附的权限规则, 包含了对应DynamoDB表的读写权限:

到这一步在IAM中创建权限和身份的工作就完成了,下一步就是进行VPC网络配置。

VPC网络配置

这个章节讲述如何将Lambda的网络请求和数据访问到DynamoDB。需要注意的是我设置Lambda是放在VPC之中,默认只能访问到所在VPC里面的资源,比如同处于一个VPC的RDS. 默认配置下AssumeRole和Lambda对DynamoDB的读写请求都无法通过VPC到达公网。这里就要用到两个新的网管组件,一个是NAT(network address translation)和VPC Endpoint, NAT可以讲VPC内网请求连接到公网,VPC Endpoint则是专门给DynamoDB提供网络请求的数据通道,这样DynamoDB的读写请求和数据交互就不用通过公网了,保证了数据的安全。

1.创建VPC

在AWS VPC服务中创建VPC, 并且给Lambda指定这个刚刚创建的VPC.

2.创建子网Subnet

VPC是由子网作为基本单元所组成的,我们需要最少要创建三个子网subnet,一个子网subnet-a给IGW(internet gateway)用于连接公网所用,另外两个(subnet-b和subnet-c)给Lambda用。创建subnet的时候,CIDR可以用下图的组合:

将创建好的subnet-b和subnet-c绑定到Lambda

3.创建igw公网网关

创建internet gateway,并且绑定到我们一开始创建的VPC上即可。

4.创建NAT Gateway

子网subnet选择subnet-a,就是那个公共子网(public subnet), 下面弹性IP ID选择创建新的EIP按钮即可。

5.创建路由表route table

创建两个新的路由表(route table),为了理解方便,分别叫route-table-a和route-table-b, 

route-table-a作为默认主要路由表,默认所有外网请求通过internet gateway网关来请求VPC外的资源。

route-table-b则是这个项目最为精华的部分了,如下图配置,0.0.0.0/0地址规则表明默认流量是去到NAT的,NAT会又会自动把流量导到Internet gateway网关,这个规则主要是为了assume role的流量服务的,倒数第二行的规则在创建目的地的时候下拉选项里面会自动弹出来,选择我么刚刚创建的VPC endpoint对应的目的地,这样Lambda看到要去到dynamoDB的流量请求就会走VPC endpoint。

同时将这个路由表route-table-b跟我们之前创建的两个私有子网subnet进行关联.

6.创建安全组Security Group

并且把security group绑定到Lambda.

至此,所有网络设置都完成了,下面将讲解如何在代码中实现连接。

代码

const assumeRoleOnDynamoDB = function (results, sts = new AWS.STS({apiVersion: '2012-10-17'})) {

    const params = {

        RoleArn: process.env.AssumedDDBRole,

        RoleSessionName: process.env.RoleSessionName

    };

    return new Promise((resolve, reject) => {

        sts.assumeRole(params, function (err, stsEncryptedData) {

            if (err) {

                console.error("[ERROR] Unable to assume role on Freelunch DynamoDB. ");

                return reject(err);

            }

            return resolve([results, stsEncryptedData]);

        });

    });

};

const upsertDynamoDBTable = function (results, stsEncryptedData) {

    const dynamodb = new AWS.DynamoDB({

        apiVersion: '2012-08-10',

        accessKeyId: stsEncryptedData.Credentials.AccessKeyId,

        secretAccessKey: stsEncryptedData.Credentials.SecretAccessKey,

        sessionToken: stsEncryptedData.Credentials.SessionToken,

        region: process.env.REGION

    });

    const paramsForDDB = {

        TableName: 'TableName',

        Item: { 'data': { "S": "data" }}

    };

    return new Promise((resolve, reject) => {

        dynamodb.putItem(paramsForDDB, function (err, data) {

            if (err) {

                console.error("[ERROR]: Failed to upsert info into DynamoDB. ");

                return reject(err);

            }

            resolve([results, dynamodb])

        });

    });

};

相关文章

网友评论

      本文标题:AWS中Lambda跨账户跨VPC连接DynamoDB

      本文链接:https://www.haomeiwen.com/subject/avaecqtx.html