如何使用 Amazon VPC 中的 Lambda 函数来检索 Secrets Manager 密钥?

3 分钟阅读
0

我在 Amazon Virtual Private Cloud(Amazon VPC)中配置的 AWS Lambda 函数无法访问 AWS Secrets Manager。

简述

Lambda 函数在安全的 Amazon VPC 中运行,可访问 AWS 服务和互联网。Lambda 服务拥有此 Amazon VPC,它没有连接到默认的 Amazon VPC

只有当您将 Amazon VPC 配置为提供访问权限时,连接到您的 Amazon VPC 的 Lambda 函数才能访问互联网。Lambda 在您的 Amazon VPC 中创建的网络接口使用私有 IP 地址,无法使用互联网网关连接到互联网。

有关更多信息,请参阅 VPC 连接函数的 Internet 和服务访问

**注意:**除非函数必须访问 Amazon VPC 中的其他资源,否则最佳实践是不将 Lambda 函数放置在 Amazon VPC 中。

解决方案

Lambda 网络配置

要允许连接到 Amazon VPC 的 Lambda 函数访问 Secrets Manager,请采取以下方法之一:

将 NAT 网关连接到私有子网

允许您的函数访问互联网。将该函数置于私有子网中,然后将出站流量路由到公有子网中的 NAT 网关。该 NAT 网关采用公共 IP 地址,并通过 VPC 的互联网网关连接到互联网。

使用 Amazon VPC 接口端点

为 Secrets Manager 创建一个 Amazon VPC 接口端点。然后,您的 Amazon VPC 无需访问互联网即可通过 Lambda 函数连接 Secrets Manager。确认 Amazon VPC 端点安全组允许来自 Lambda 安全组或 IP 地址范围的 443 端口入站流量。同时,确认 Lambda 安全组允许流向 Amazon VPC 端点安全组或 IP 地址范围的 443 端口出站流量。

**注意:**如果您使用 AWS PrivateLink VPC 端点,请确保使用 Amazon VPC 为域名系统(DNS)配置 DHCP 选项。有关更多信息,请参阅 Amazon VPC 中的 DNS 属性

例如,以下 AWS CloudFormation 模板在 VPC 的私有子网内建立了一个 Lambda 函数。这允许通过 VPC 端点私有访问 AWS Secrets Manager:

AWSTemplateFormatVersion: "2010-09-09"
Description: "Lambda Secrets Manager"
Resources:
    EC2SecurityGroup:
        Type: "AWS::EC2::SecurityGroup"
        Properties:
            GroupDescription: "launch-wizard-19 created 2022-03-23T11:10:16.721+05:30"
            GroupName: "launch-wizard-19"
            VpcId: !Ref EC2VPC
            SecurityGroupIngress:
              -
                CidrIp: "10.0.0.0/16"
                FromPort: 443
                IpProtocol: "tcp"
                ToPort: 443
            SecurityGroupEgress:
              -
                CidrIp: "10.0.0.0/16"
                FromPort: 443
                IpProtocol: "tcp"
                ToPort: 443


    LambdaFunction:
        Type: "AWS::Lambda::Function"
        Properties:
            Description: "AWS Lambda to AWS Secrets Manager"
            FunctionName: "SecretsManagerLambda"
            Handler: "index.lambda_handler"
            Architectures:
              - "x86_64"
            Code:
              ZipFile: |
                import json
                import boto3
                client = boto3.client('secretsmanager')

                def lambda_handler(event, context):
                    response = client.get_secret_value(
                    SecretId='string',
                    VersionId='string',
                    VersionStage='string'
                    )
                    print(response)
                    # TODO implement
                    return {
                        'statusCode': 200,
                        'body': json.dumps('Hello from Lambda!')
                    }



            MemorySize: 128
            Role: !GetAtt IAMRole.Arn
            Runtime: "python3.11"
            Timeout: 30
            TracingConfig:
                Mode: "PassThrough"
            EphemeralStorage:
                Size: 512
            VpcConfig:
              SecurityGroupIds:
                - !Ref EC2SecurityGroup
              SubnetIds:
                - !Ref EC2Subnet

    EC2VPC:
        Type: "AWS::EC2::VPC"
        Properties:
            CidrBlock: "10.0.0.0/16"
            EnableDnsSupport: true
            EnableDnsHostnames: true
            InstanceTenancy: "default"

    EC2Subnet:
        Type: "AWS::EC2::Subnet"
        Properties:
            AvailabilityZone: !Sub "${AWS::Region}b"
            CidrBlock: "10.0.7.0/24"
            VpcId: !Ref EC2VPC
            MapPublicIpOnLaunch: false
            Tags:
              -
                Key: "Name"
                Value: "Private-new-availability"

    EC2VPCEndpoint:
        Type: "AWS::EC2::VPCEndpoint"
        Properties:
            VpcEndpointType: "Interface"
            VpcId: !GetAtt EC2Subnet.VpcId
            ServiceName: !Sub "com.amazonaws.${AWS::Region}.secretsmanager"
            PolicyDocument: |
                {
                  "Statement": [
                    {
                      "Action": "*",
                      "Effect": "Allow",
                      "Principal": "*",
                      "Resource": "*"
                    }
                  ]
                }
            SubnetIds:
              - !Ref EC2Subnet
            PrivateDnsEnabled: true
            SecurityGroupIds:
              - !Ref EC2SecurityGroup

    IAMRole:
        Type: "AWS::IAM::Role"
        Properties:
            Path: "/"
            RoleName: "Lambdapermissions"
            AssumeRolePolicyDocument: "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
            ManagedPolicyArns:
              - !Ref IAMManagedPolicy


            Description: "Allows Lambda functions to call AWS services on your behalf."

    IAMManagedPolicy:
        Type: "AWS::IAM::ManagedPolicy"
        Properties:
            ManagedPolicyName: "LambdaSecretsPolicy"
            Path: "/"
            PolicyDocument: |
                {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Sid": "Statement1",
                            "Effect": "Allow",
                            "Action": [
                                "secretsmanager:GetSecretValue",
                                "ec2:CreateNetworkInterface",
                                "ec2:DescribeNetworkInterfaces",
                                "ec2:DeleteNetworkInterface"
                            ],
                            "Resource": "*"
                        }
                    ]
                }

Lambda 执行角色权限

Lambda 执行角色授予访问 Secrets Manager 密钥的权限。使用 GetSecretValue API 调用获取 Secrets Manager 密钥。有关更多信息,请参阅示例: 检索密钥值的权限

(可选)AWS Key Management Service(AWS KMS)权限

如果 Secrets Manager 密钥是使用 AWS KMS 客户托管密钥加密,而不是托管密钥 aws/secretsmanager,则需要进行额外配置。确保在 Lambda 执行角色或 AWS KMS 密钥政策中允许 Decrypt API 操作权限。

相关信息

如何解决 Lambda 的权限问题?