How can I use Lambda functions in an Amazon VPC to retrieve Secrets Manager secrets?
My AWS Lambda function in an Amazon Virtual Private Cloud (Amazon VPC) can't access AWS Secrets Manager.
Short description
Lambda functions run in a secure Amazon VPC with access to AWS services and the internet. The Lambda service owns this Amazon VPC, and the it isn't connected to your default Amazon VPC.
Lambda functions that are connected to your Amazon VPC can access the internet only when you configure your Amazon VPC to provide access. The network interfaces that Lambda creates within your Amazon VPC use private IP addresses and can't connect to the internet using an internet gateway.
For more information, see Internet and service access for VPC-connected functions.
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.
For example, the following AWS CloudFormation template establishes a Lambda function inside of a VPC's private subnet. This allows private access to AWS Secrets Manager through VPC endpoints:
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 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 secret values.
(Optional) AWS Key Management Service (AWS KMS) permissions
If the Secrets Manager secret is encrypted with an AWS KMS customer managed key instead of the managed key aws/secretsmanager, then additional configuration is required. Make sure to allow the Decrypt API action permission as either the Lambda execution role or the AWS KMS key policy.
Related information
Is it possible to add some CloudFormation template examples?
Thank you for your comment. We'll review and update the Knowledge Center article as needed.
Relevant content
- asked a year agolg...
- Accepted Answerasked 8 months agolg...
- asked 4 years agolg...
- AWS OFFICIALUpdated a year ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated a year ago