授予 Lambda 函数访问 Amazon VPC 中资源的权限
使用 Amazon Virtual Private Cloud(Amazon VPC),您可以在自己的 AWS 账户中创建私有网络,以用于托管 Amazon Elastic Compute Cloud(Amazon EC2)实例、Amazon Relational Database Service(Amazon RDS)实例和 Amazon ElastiCache 实例等资源。您可以通过包含相关资源的私有子网将函数附加到 VPC,从而向您的 Lambda 函数授予访问在 Amazon VPC 中托管的资源的权限。按照以下各节中的说明,通过 Lambda 控制台、AWS Command Line Interface(AWS CLI)或 AWS SAM 将 Lambda 函数附加到 Amazon VPC。
注意
每个 Lambda 函数都在由 Lambda 服务拥有和管理的 VPC 内运行。这些 VPC 由 Lambda 自动维护,对客户不可见。配置您的函数以访问 Amazon VPC 中的其他 AWS 资源,不会影响在其中运行函数的由 Lambda 托管的 VPC。
Sections
所需的 IAM 权限
要将 Lambda 函数附加到您的 AWS 账户中的 Amazon VPC,Lambda 需要具有创建和管理网络接口的权限,以向您的函数授予访问该 VPC 中资源的权限。
Lambda 创建的网络接口被称为 Hyperplane 弹性网络接口,简称 Hyperplane ENI。要了解有关这些网络接口的更多信息,请参阅 了解 Hyperplane 弹性网络接口(ENI)。
您可以通过将 AWS 托管式策略 AWSLambdaVPCAccessExecutionRole 附加到函数的执行角色,从而向函数授予所需的权限。当您在 Lambda 控制台中创建新函数并将其附加到 VPC 时,Lambda 会自动为您添加此权限策略。
如果您希望创建自己的 IAM 权限策略,请务必添加以下所有权限:
-
ec2:CreateNetworkInterface
-
ec2:DescribeNetworkInterfaces:仅当所有资源 (
"Resource": "*"
) 都允许执行此操作时,此操作才有效。 -
ec2:DescribeSubnets
-
ec2:DeleteNetworkInterface:如果您没有在执行角色中为 DeleteNetworkInterface 指定资源 ID,则函数可能无法访问 VPC。请指定唯一的资源 ID,或包含所有资源 ID,例如
"Resource": "arn:aws:ec2:us-west-2:123456789012:*/*"
。 -
ec2:AssignPrivateIpAddresses
-
ec2:UnassignPrivateIpAddresses
请注意,函数的角色需要这些权限只是为了创建网络接口,而不是调用您的函数。将函数附加到 Amazon VPC 后,即使您从函数的执行角色中移除了这些权限,您仍然可以成功调用该函数。
要将您的函数附加到 VPC,Lambda 还需要使用您的 IAM 用户角色验证网络资源。确保您的用户角色具有以下 IAM 权限:
-
ec2:DescribeSecurityGroups
-
ec2:DescribeSubnets
-
ec2:DescribeVpcs
注意
Lambda 服务使用授予函数执行角色的 Amazon EC2 权限,将函数附加到 VPC。不过,您还会隐式向函数的代码授予这些权限。这意味着函数代码能够进行这些 Amazon EC2 API 调用。有关遵循安全性最佳实践的建议,请参阅 安全最佳实操。
将 Lambda 函数附加到您的 AWS 账户 中的 Amazon VPC
通过 Lambda 控制台、AWS CLI 或 AWS SAM 将您的函数附加到您的 AWS 账户中的 Amazon VPC。如果使用 AWS CLI 或 AWS SAM,或者使用 Lambda 控制台将现有的函数附加到 VPC,请确保函数的执行角色具有上一节中列出的必要权限。
Lambda 函数无法直接连接到具有专用实例租赁的 VPC。要连接到专用 VPC 中的资源,请使其与具有默认租赁的第二个 VPC 对等
连接到 VPC 时的互联网访问权限
默认情况下,Lambda 函数可以访问公共互联网。当您将函数附加到 VPC 时,该函数只能访问该 VPC 内可用的资源。要使您的函数能够访问互联网,您还需要将 VPC 配置为可以访问互联网。要了解更多信息,请参阅 为连接到 VPC 的 Lambda 函数启用互联网访问权限。
IPv6 支持
您的函数可以通过 IPv6 连接到双堆栈 VPC 子网中的资源。默认情况下,此选项处于关闭状态。要允许出站 IPv6 流量,请使用控制台或使用带有 create-function--vpc-config Ipv6AllowedForDualStack=true
选项。
注意
要在 VPC 中允许出站 IPv6 流量,连接到该函数的所有子网都必须是双堆栈子网。Lambda 不支持 VPC 中针对仅限 IPv6 的子网的出站 IPv6 连接,不支持针对未连接到 VPC 的函数的出站 IPv6 连接,也不支持使用 VPC 端点(AWS PrivateLink)的入站 IPv6 连接。
您可以更新函数代码以通过 IPv6 显式连接到子网资源。以下 Python 示例会打开一个套接字并连接到 IPv6 服务器。
例 :连接到 IPv6 服务器
def connect_to_server(event, context): server_address = event['host'] server_port = event['port'] message = event['message'] run_connect_to_server(server_address, server_port, message) def run_connect_to_server(server_address, server_port, message): sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0) try: # Send data sock.connect((server_address, int(server_port), 0, 0)) sock.sendall(message.encode()) BUFF_SIZE = 4096 data = b'' while True: segment = sock.recv(BUFF_SIZE) data += segment # Either 0 or end of data if len(segment) < BUFF_SIZE: break return data finally: sock.close()
将 Lambda 与 Amazon VPC 结合使用的最佳实践
为确保您的 Lambda VPC 配置符合最佳实践指南,请遵循以下各节中的建议。
安全最佳实操
要将您的 Lambda 函数附加到 VPC,您需要向函数的执行角色授予一些 Amazon EC2 权限。在创建函数用来访问 VPC 中资源的网络接口时将需要这些权限。不过,还会向函数的代码隐式授予这些权限。这意味着函数代码具有进行这些 Amazon EC2 API 调用的权限。
为遵循最低权限原则,请在函数的执行角色中添加与如下例类似的拒绝策略。此策略可防止您的函数调用 Lambda 服务用于将函数附加到 VPC 的 Amazon EC2 API。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": [ "ec2:CreateNetworkInterface", "ec2:DeleteNetworkInterface", "ec2:DescribeNetworkInterfaces", "ec2:DescribeSubnets", "ec2:DetachNetworkInterface", "ec2:AssignPrivateIpAddresses", "ec2:UnassignPrivateIpAddresses" ], "Resource": [ "*" ], "Condition": { "ArnEquals": { "lambda:SourceFunctionArn": [ "arn:aws:lambda:us-west-2:123456789012:function:my_function" ] } } } ] }
AWS 提供了安全组和网络访问控制列表(ACL)功能来增强 VPC 中的安全性。安全组可以控制您的资源的入站和出站流量,网络 ACL 可以控制您的子网的入站和出站流量。安全组为大多数子网提供足够的访问控制。如果需要为 VPC 增加额外安全保护,您可以使用网络 ACL。有关使用 Amazon VPC 时的安全最佳实践的一般指南,请参阅《Amazon Virtual Private Cloud 用户指南》中的 VPC 的安全最佳实践。
性能最佳实践
当您将函数附加到 VPC 时,Lambda 会检查是否有可用来连接的可用网络资源(Hyperplane ENI)。Hyperplane ENI 与特定的安全组和 VPC 子网组合相关联。将一个函数附加到 VPC 后,如果在附加其他函数时指定相同的子网和安全组,这将意味着 Lambda 可以共享网络资源,无需创建新的 Hyperplane ENI。有关 Hyperplane ENI 及其生命周期的更多信息,请参阅 了解 Hyperplane 弹性网络接口(ENI)。
了解 Hyperplane 弹性网络接口(ENI)
Hyperplane ENI 是一种托管式资源,在您的 Lambda 函数和您希望函数连接到的资源之间充当网络接口。当您将函数附加到 VPC 时,Lambda 服务会自动创建和管理这些 ENI。
Hyperplane ENI 对您并不直接可见,因此您无需对其进行配置或管理。不过,了解其工作原理有助您在将函数附加到 VPC 时了解其行为。
首次使用特定的子网和安全组组合将函数附加到 VPC 时,Lambda 将创建一个 Hyperplane ENI。您账户中使用相同子网和安全组组合的其他函数也可以使用该 ENI。Lambda 会尽可能重复使用现有的 ENI 来优化资源利用率并减少新 ENI 的创建。每个 Hyperplane ENI 最多支持 65,000 个连接/端口。如果连接数超过此限制,Lambda 会根据网络流量和并发要求自动扩展 ENI 的数量。
对于新函数,当 Lambda 创建 Hyperplane ENI 时,您的函数仍处于“待处理”状态,因此无法调用。只有在 Hyperplane ENI 准备就绪后,您的函数才会变为“活动”状态,这可能需要几分钟。对于现有函数,您无法执行以该函数为目标的其他操作(例如创建版本或更新函数的代码),但可以继续调用该函数的早期版本。
注意
如果 Lambda 函数持续 30 天保持空闲状态,Lambda 将会回收任何未使用的 Hyperplane ENI,并将函数状态设置为空闲。新调用尝试将会失败,并且函数会重新进入“待处理”状态,直到 Lambda 完成 Hyperplane ENI 创建或分配。有关 Lambda 函数状态的更多信息,请参阅 Lambda 函数状态。
将 IAM 条件键用于 VPC 设置
您可以将特定于 Lambda 的条件键用于 VPC 设置,从而为您的 Lambda 函数提供额外的权限控制。例如,您可以要求组织中的所有函数都连接到 VPC。您还可以指定函数的用户可以使用和不能使用的子网和安全组。
Lambda 在 IAM policy 中支持以下条件键:
-
lambda:VpcIds – 允许或拒绝一个或多个 VPC。
-
lambda:SubnetIds – 允许或拒绝一个或多个子网。
-
lambda:SecurityGroupIds – 允许或拒绝一个或多个安全组。
Lambda API 操作 CreateFunction 和 UpdateFunctionConfiguration 支持这些条件键。有关在 IAM policy 中使用条件键的更多信息,请参阅《IAM 用户指南》中的IAM JSON policy 元素:条件。
提示
如果您的函数已包含来自前一个 API 请求的 VPC 配置,则可以发送不带 VPC 配置的 UpdateFunctionConfiguration
请求。
带有用于 VPC 设置的条件键的示例策略
以下示例演示如何将条件键用于 VPC 设置。创建具有所需限制的策略语句后,为目标用户或角色附加策略语句。
确保用户仅部署与 VPC 连接的函数
要确保所有用户仅部署与 VPC 连接的函数,您可以拒绝不包含有效 VPC ID 的函数创建和更新操作。
请注意,VPC ID 不是 CreateFunction
或 UpdateFunctionConfiguration
请求的输入参数。Lambda 根据子网和安全组参数检索 VPC ID 值。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "EnforceVPCFunction", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "Null": { "lambda:VpcIds": "true" } } } ] }
拒绝用户访问特定的 VPC、子网或安全组
要拒绝用户访问特定 VPC,请使用 StringEquals
检查 lambda:VpcIds
条件的值。以下示例拒绝用户访问 vpc-1
和 vpc-2
。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "EnforceOutOfVPC", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "StringEquals": { "lambda:VpcIds": ["vpc-1", "vpc-2"] } } }
要拒绝用户访问特定子网,请使用 StringEquals
检查 lambda:SubnetIds
条件的值。以下示例拒绝用户访问 subnet-1
和 subnet-2
。
{ "Sid": "EnforceOutOfSubnet", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "ForAnyValue:StringEquals": { "lambda:SubnetIds": ["subnet-1", "subnet-2"] } } }
要拒绝用户访问特定安全组,请使用 StringEquals
检查 lambda:SecurityGroupIds
条件的值。以下示例拒绝用户访问 sg-1
和 sg-2
。
{ "Sid": "EnforceOutOfSecurityGroups", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "ForAnyValue:StringEquals": { "lambda:SecurityGroupIds": ["sg-1", "sg-2"] } } } ] }
允许用户使用特定 VPC 设置创建和更新函数
要允许用户访问特定的 VPC,请使用 StringEquals
检查 lambda:VpcIds
条件的值。以下示例允许用户访问 vpc-1
和 vpc-2
。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "EnforceStayInSpecificVpc", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Allow", "Resource": "*", "Condition": { "StringEquals": { "lambda:VpcIds": ["vpc-1", "vpc-2"] } } }
要允许用户访问特定子网,请使用 StringEquals
检查 lambda:SubnetIds
条件的值。以下示例允许用户访问 subnet-1
和 subnet-2
。
{ "Sid": "EnforceStayInSpecificSubnets", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Allow", "Resource": "*", "Condition": { "ForAllValues:StringEquals": { "lambda:SubnetIds": ["subnet-1", "subnet-2"] } } }
要允许用户访问特定的安全组, 请使用 StringEquals
检查 lambda:SecurityGroupIds
条件的值。以下示例允许用户访问 sg-1
和 sg-2
。
{ "Sid": "EnforceStayInSpecificSecurityGroup", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Allow", "Resource": "*", "Condition": { "ForAllValues:StringEquals": { "lambda:SecurityGroupIds": ["sg-1", "sg-2"] } } } ] }
VPC 教程
在以下教程中,您会将 Lambda 函数连接到 VPC 中的资源。