Skip to content

How do I allow Lambda functions connected to an Amazon VPC to access Secrets Manager?

4 minute read
0

My AWS Lambda function in an Amazon Virtual Private Cloud (Amazon VPC) can't access AWS Secrets Manager.

Short description

Lambda functions connected to your Amazon VPC can access the internet only when you configure your Amazon VPC to provide access.

For more information, see Internet access when attached to a VPC

Note: It's a best practice not to place Lambda functions in an Amazon VPC unless the function must access other resources in the Amazon VPC.

Resolution

Lambda network configuration

To allow a Lambda function that's connected to an Amazon VPC to access Secrets Manager, follow one of these methods:

Attach a NAT gateway to a private subnet

Give your function internet access. Place the function in private subnets and route the outbound traffic to a NAT gateway in a public subnet. The NAT gateway has a public IP address and connects to the internet through the VPC's internet gateway.

Use an Amazon VPC interface endpoint

Set up an Amazon VPC interface endpoint for Secrets Manager. Your Amazon VPC then connects Secrets Manager from your Lambda function without internet access. Verify that the Amazon VPC endpoint security group allows port 443 inbound traffic from the Lambda security group or IP address range. Also, verify that the Lambda security group allows port 443 outbound traffic to the Amazon VPC endpoint security group or IP address range.

Note: If you use AWS PrivateLink VPC endpoints, then make sure that you configure the DHCP options with your Amazon VPC for Domain Name System (DNS). For more information, see DNS attributes for your Amazon VPC.

The following AWS CloudFormation template establishes a Lambda function inside a VPC's private subnet that allows private access to Secrets Manager through VPC endpoints:

AWSTemplateFormatVersion: "2010-09-09"
Description: "Lambda Secrets Manager"
Resources:
    EC2SecurityGroup:
        Type: "AWS::EC2::SecurityGroup"
        Properties:
            GroupDescription: "Security group for Lambda and VPC endpoint"
            GroupName: "lambda-secretsmanager-sg"
            VpcId: !Ref EC2VPC
            SecurityGroupIngress:
              -
                CidrIp: "[IP_ADDRESS]"
                FromPort: 443
                IpProtocol: "tcp"
                ToPort: 443
            SecurityGroupEgress:
              -
                CidrIp: "[IP_ADDRESS]"
                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='arn:aws:secretsmanager:us-east-1:123456789012:secret:MySecret-AbCdEf'
                    )
                    secret = response['SecretString']
                    # Use the secret value in your application logic
                    # Do not log or print the secret value
                    return {
                        'statusCode': 200,
                        'body': json.dumps('Secret retrieved successfully')
                    }

            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: "[IP_ADDRESS]"
            EnableDnsSupport: true
            EnableDnsHostnames: true
            InstanceTenancy: "default"

    EC2Subnet:
        Type: "AWS::EC2::Subnet"
        Properties:
            AvailabilityZone: !Sub "${AWS::Region}b"
            CidrBlock: "[IP_ADDRESS]"
            VpcId: !Ref EC2VPC
            MapPublicIpOnLaunch: false
            Tags:
              -
                Key: "Name"
                Value: "Private-subnet"

    EC2VPCEndpoint:
        Type: "AWS::EC2::VPCEndpoint"
        Properties:
            VpcEndpointType: "Interface"
            VpcId: !GetAtt EC2Subnet.VpcId
            ServiceName: !Sub "com.amazonaws.${AWS::Region}.secretsmanager"
            PolicyDocument: |
                {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Sid": "AllowLambdaGetSecretValue",
                      "Effect": "Allow",
                      "Principal": {
                        "AWS": "arn:aws:iam::123456789012:role/Lambdapermissions"
                      },
                      "Action": "secretsmanager:GetSecretValue",
                      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:MySecret-AbCdEf"
                    }
                  ]
                }
            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": "SecretsManagerAccess",
                            "Effect": "Allow",
                            "Action": "secretsmanager:GetSecretValue",
                            "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:MySecret-AbCdEf"
                        },
                        {
                            "Sid": "VPCNetworkInterfaceAccess",
                            "Effect": "Allow",
                            "Action": [
                                "ec2:CreateNetworkInterface",
                                "ec2:DescribeNetworkInterfaces",
                                "ec2:DescribeSubnets",
                                "ec2:DeleteNetworkInterface",
                                "ec2:AssignPrivateIpAddresses",
                                "ec2:UnassignPrivateIpAddresses"
                            ],
                            "Resource": "*"
                        }
                    ]
                }

Note: Replace 123456789012 with your AWS account ID, MySecret-AbCdEf with your secret name, and us-east-1 with your AWS Region.

Lambda execution role permissions

Grant permissions to the Lambda execution role to access Secrets Manager secrets. Use the GetSecretValue API call to get the Secrets Manager secret. For more information, see Example: Permission to retrieve individual secret values.

(Optional) AWS KMS permissions

If the Secrets Manager secret is encrypted with an AWS Key Management Service (AWS KMS) customer managed key, then check your configuration requirements. Make sure to allow the Decrypt API action permission in either the Lambda execution role or the AWS KMS key policy. For more information, see Secret encryption and decryption in AWS Secrets Manager.

Note: If you use the default AWS managed key, then no additional AWS KMS permissions are required.

Related information

Activate internet access for VPC-connected Lambda functions

Using an AWS Secrets Manager VPC endpoint

Use AWS Secrets Manager secrets in AWS Lambda functions