AWS Compute Blog

Using AWS Lambda IAM condition keys for VPC settings

You can now control the Amazon Virtual Private Cloud (VPC) settings for your AWS Lambda functions using AWS Identity and Access Management (IAM) condition keys. IAM condition keys enable you to further refine the conditions under which an IAM policy statement applies. You can use the new condition keys in IAM policies when granting permissions to create and update functions.

The three new condition keys for VPC settings are lambda:VpcIds, lambda:SubnetIds, and lambda:SecurityGroupIds. The keys allow you to ensure that users can only deploy functions connected to one or more allowed VPCs, subnets, and security groups. If users try to create or update a function with VPC settings that are not allowed, Lambda rejects the operation.

Understanding Lambda and VPCs

All of the Lambda compute infrastructure runs inside VPCs owned by the Lambda service. Lambda functions can only be invoked by calling the Lambda API. There is no direct network access to the execution environment where your functions run.

Non-VPC connected Lambda functions

When your Lambda function is not configured to connect to your own VPCs, the function can access anything available on the public internet. This includes other AWS services, HTTPS endpoints for APIs, or services and endpoints outside AWS. The function cannot directly connect to your private resources inside of your VPC.

VPC connected Lambda functions

You can configure a Lambda function to connect to private subnets in a VPC in your account. When a Lambda function is configured to use a VPC, the Lambda function still runs inside the AWS Lambda service VPC. The function then sends all network traffic through your VPC and abides by your VPC’s network controls. You can use these controls to define where your functions can connect using security groups and network ACLs. Function egress traffic comes from your own network address space, and you have network visibility using VPC flow logs.

You can restrict access to network locations, including the public internet. A Lambda function connected to a VPC has no internet access by default. To give your function access to the internet, you can route outbound traffic to a network address translation (NAT) gateway in a public subnet.

When you configure your Lambda function to connect to your own VPC, it uses a shared elastic network interface (ENI) managed by AWS Hyperplane. The connection creates a VPC-to-VPC NAT and does a cross-account attachment, which allows network access from your Lambda functions to your private resources.

AWS Lambda service VPC with VPC-to-VPT NAT to customer VPC

AWS Lambda service VPC with VPC-to-VPT NAT to customer VPC

The Hyperplane ENI is a managed network interface resource that the Lambda service controls and sits in your VPC inside of your account. Multiple execution environments share the ENI to securely access resources inside of a VPC in your account. You still do not have direct network access to the execution environment.

When are ENIs created?

The network interface creation happens when your Lambda function is created or its VPC settings are updated. When a function is invoked, the execution environment uses the pre-created network interface and quickly establishes a network tunnel to it. This reduces the latency that was previously associated with creating and attaching a network interface during a cold start.

How many ENIs are required?

Because the network interfaces are shared across execution environments, typically only a handful of network interfaces are required per function. Every unique security group:subnet combination across functions in your account requires a distinct network interface. If multiple functions in the same account use the same security group:subnet pairing, it reuses the same network interface. This way, a single application with multiple functions but the same network and security configuration can benefit from the existing interface configuration.

Your function scaling is no longer directly tied to the number of network interfaces. Hyperplane ENIs can scale to support large numbers of concurrent function executions.

If your functions are not active for a long period of time, Lambda reclaims its network interfaces, and the function becomes idle and inactive. You must invoke an idle function to reactivate it. The first invocation fails and the function enters a pending state again until the network interface is available.

Using the new Lambda condition keys for VPC settings

With the new VPC condition key settings, you can specify one or more required VPC, subnets, and security groups. The lambda:VpcIds value is inferred from the subnet and security groups the CreateFunction API caller provides.

The condition syntax is in the format "Condition":{"{condition-operator}":{"{condition-key}":"{condition-value}"}}. You can use condition operators with multiple keys and values to construct policy documents.

I have a private VPC configured with the following four subnets:

Private VPC subnets

Private VPC subnets

I have a MySQL database instance running in my private VPC. The instance is running in us-east-1b in subnet subnet-046c0d0c487b0515b with a failover in us-east-1c in subnet subnet-091e180fa55fb8e83. I have an associated security group sg-0a56588b3406ee3d3 allowing access to the database. As this is a private subnet, I don’t allow internet access.

I want to ensure that any Lambda functions I create with my account must only connect to my private VPC.

  1. I create the following IAM policy document, which I attach to my account in AWS Organizations as a Service Control Policy (SCP). This policy uses Deny with StringNotEquals condition operator to specify a required VPCId. You should ensure another SCP attached to the account allows access to Lambda APIs. Typically, the default SCP called FullAWSAccess provides this access.
    {
        "Version": "2012-10-17",
        "Statement": [
                {
                      "Sid": "Stmt159186333251",
                      "Action": ["lambda:CreateFunction","lambda:UpdateFunctionConfiguration"],
                      "Effect": "Deny",
                      "Resource": "*",
                      "Condition": {"StringNotEquals": {"lambda:VpcIds":["vpc-0eebf3d0fe63a2db1"]}}
                }
        ]
    }
    
  2. I attempt to create a Lambda function that does not connect to my VPC by excluding --vpc-config in the API call.
    aws lambda create-function --function-name MyVPCLambda1 \
      --runtime python3.7 --handler helloworld.handler --zip-file fileb://vpccondition.zip \
      --region us-east-1 --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole
    
  3. I receive an AccessDeniedException error with an explicit deny:

    Lambda function creation AccessDeniedException

    Lambda function creation AccessDeniedException

  4. I attempt to create the Lambda function again and include any one of the subnets in my VPC, along with the security group. I must include both the SubnetIds and SecurityGroupId values with the --vpc-config.
    aws lambda create-function --function-name MyVPCLambda1 \
      --vpc-config "SubnetIds=['subnet-019c87c9b67742a8f'],SecurityGroupIds=['sg-0a56588b3406ee3d3']" \
      --runtime python3.7 --handler helloworld.handler --zip-file fileb://vpccondition.zip \
      --region us-east-1 --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole
    

    The function is created successfully.

    Successfully create Lambda function connected to VPC

    Successfully create Lambda function connected to VPC

I also want to ensure that any Lambda functions created in my account must have the following in the configuration:

  • My private VPC
  • Both subnets containing my database instances
  • The security group including the MySQL database instance
  1. I amend my account service control policy to include restrictions for SubnetIds and SecurityGroupIds. I do not need to specify VpcIds as this is inferred.
    {
        "Version": "2012-10-17",
        "Statement": [
    		{
    			"Sid": "Stmt159186333252",
    			"Action": ["lambda:CreateFunction","lambda:UpdateFunctionConfiguration"],
    			"Effect": "Deny",
    			"Resource": "*",
    			"Condition": {"ForAllValues:StringNotEquals": {"lambda:SubnetIds": ["subnet-046c0d0c487b0515b","subnet-091e180fa55fb8e83"]}}
    		},
    		{
    			"Sid": "Stmt159186333253",
    			"Action": ["lambda:CreateFunction","lambda:UpdateFunctionConfiguration"],
    			"Effect": "Deny",
    			"Resource": "*",
    			"Condition": {"ForAllValues:StringNotEquals": {"lambda:SecurityGroupIds": ["sg-0a56588b3406ee3d3"]}}
    		}
        ]
    }
    
  2. I try to create another Lambda function, using --vpc-config values with a subnet in my VPC that’s not in the allowed permission list, along with the security group.
    aws lambda create-function --function-name MyVPCLambda2 \
      --vpc-config "SubnetIds=['subnet-019c87c9b67742a8f'],SecurityGroupIds=['sg-0a56588b3406ee3d3']" \
      --runtime python3.7 --handler helloworld.handler --zip-file fileb://vpccondition.zip \
      --region us-east-1 --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole
    

    I receive an AccessDeniedException error.

  3. I retry, specifying both valid and allowed SubnetIds and SecurityGroupIds:
    aws lambda create-function --function-name MyVPCLambda2 \
      --vpc-config "SubnetIds=['subnet-046c0d0c487b0515b','subnet-091e180fa55fb8e83'],SecurityGroupIds=['sg-0a56588b3406ee3d3']" \
      --runtime python3.7 --handler helloworld.handler --zip-file fileb://vpccondition.zip \
      --region us-east-1 --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole
    

    The function creation is successful.

    Successfully create Lambda function connected to specific subnets and security groups

    Successfully create Lambda function connected to specific subnets and security groups

With these settings, I can ensure that I can only create Lambda functions with the allowed VPC network security settings. These condition keys can also be used in policies attached to individual users, groups, or roles within your account. You can use Allow policies to grant permission to new users to create or update function with specific VPC settings. And, you can use Deny policies for existing users to restrict existing create and update function permissions to specific VPC settings.

Updating Lambda functions

When updating Lambda function configuration, you do not need to specify the VPC settings if they already exist. Lambda checks the existing VPC settings before making the authorization call to IAM.

The following command to add more memory to the Lambda function, without specifying the VPC configuration, is successful as the configuration already exists.

aws lambda update-function-configuration --function-name MyVPCLambda2 --memory-size 512

Lambda layer condition keys

Lambda also has another existing condition key – lambda:Layer.

Lambda layers allow you to share code and content between multiple Lambda functions, or even multiple applications.

The lambda:Layer condition key allows you to enforce that a function must include a particular layer, or allowed group of layers. You can also prevent using layers. You can limit using layers to only those from your accounts, preventing layers published by accounts that are not yours.

Conclusion

You can now control the VPC settings for your Lambda functions using IAM condition keys.

The new VPC setting condition keys are available in all AWS Regions where Lambda is available. To learn more about the new condition keys and view policy examples, see “Using IAM condition keys for VPC settings” and  “Resource and Conditions for Lambda actions” in the Lambda Developer Guide.  To learn more about using IAM condition keys, see “IAM JSON Policy Elements: Condition” in the IAM User Guide.