Amazon VPC 内の Lambda 関数を使用して Secrets Manager のシークレットを取得するにはどうすればよいですか?

所要時間3分
0

Amazon Virtual Private Cloud (Amazon VPC) 内の AWS Lambda 関数が AWS Secrets Manager にアクセスできません。

簡単な説明

Lambda 関数は、AWS サービスとインターネットにアクセスできる安全な Amazon VPC で実行されます。この Amazon VPC は Lambda サービスが所有しており、デフォルトの Amazon VPC には接続されていません。

Amazon VPC に接続されている Lambda 関数がインターネットにアクセスできるのは、Amazon VPC がアクセスを提供するように設定した場合のみです。Lambda が Amazon VPC 内に作成するネットワークインターフェイスはプライベート IP アドレスを使用し、インターネットゲートウェイを使用してインターネットに接続することはできません。

詳細については、「Internet and service access for VPC-connected functions」を参照してください。

メモ: Lambda 関数が Amazon VPC 内の他のリソースにアクセスする必要がある場合を除き、Amazon VPC には Lambda 関数を配置しないことがベストプラクティスです。

解決策

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 オプションを設定してください。詳細については、「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 のシークレットを取得します。詳細については、「Example: Permission to retrieve secret values」を参照してください。

(オプション) AWS Key Management Service (AWS KMS) 権限

Secrets Manager のシークレットがマネージドキー aws/secretsmanager の代わりに AWS KMS カスタマーマネージドキーで暗号化されている場合は、追加の設定が必要です。Decrypt API アクション権限を Lambda 実行ロールまたは AWS KMS キーポリシーのいずれかとして許可するようにしてください。

関連情報

Lambda のアクセス権に関する問題をトラブルシューティングする方法を教えてください。

コメントはありません