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
How do I troubleshoot permissions issues with Lambda?