Restrict lambda permissions to access VPCs

Viewed 1091

When deploying a lambda function to a VPC you're required to grant a bunch of network interface related permissions to lambda's execution role. AWS manuals advice to use AWSLambdaVPCAccessExecutionRole managed policy for this, which looks like this:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "ec2:CreateNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DeleteNetworkInterface",
                "ec2:AssignPrivateIpAddresses",
                "ec2:UnassignPrivateIpAddresses"
            ],
            "Resource": "*"
        }
    ]
}

As one can see, this policy doesn't restrict network interfaces that the lambda can modify, thus potentially allowing it to mess with networking outside its own VPC. I'd like to limit the actions that the lambda can do to the VPC or subnets that it's actually deployed into. However, so far I failed to come with a working policy for that.

I tried to check the VPC in the policy like this:

"Condition": {"StringEquals": {"ec2:Vpc": "${my_vpc_arn}" }}

but still got permission denied.

CloudTrail event contains the following authorization message) decoded with aws sts decode-authorization-message): https://pastebin.com/P9t3QWEY where I can't see any useful keys to check.

So is it possible to restrict a VPC-deployed lambda to only modify particular network interfaces?

2 Answers

You can't restrict the policy to individual NIs, as you don't know their ids until after you create them. But you should be able to restrict access to a specific VPC using the following lambda execution policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AccessToSpecificVPC",
            "Effect": "Allow",
            "Action": [
                "ec2:CreateNetworkInterface",
                "ec2:DeleteNetworkInterface",
                "ec2:UnassignPrivateIpAddresses",
                "ec2:AssignPrivateIpAddresses",
                "ec2:DescribeNetworkInterfaces"
            ],
            "Resource": "*",
            "Condition": {
                "ArnLikeIfExists": {
                    "ec2:Vpc": "arn:aws:ec2:<your-region>:<your-account-id>:vpc/<vpc-id>"
                }
            }
        },
        {
            "Sid": "CWLogsPermissions",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",

                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

The Lambda Service needs to be able to create and remove network interfaces in your VPC. That's because a shared ENI will be deployed in the VPC. Once all execution contexts are terminated this shared ENI will be removed again. This also explains why the describe permissions are needed, because the service probably needs to figure out if a shared ENI is already deployed for the specific lambda function.

Unfortunately that means you can't restrict the delete/modify operations to any particular ENIs as those are created and removed dynamically.

According to the documentation the specific permissions the Role needs are:

  • ec2:CreateNetworkInterface
  • ec2:DescribeNetworkInterfaces
  • ec2:DeleteNetworkInterface

I checked the documentation and the Create + Delete actions allow (among others) the following conditions:

  • ec2:Subnet
  • ec2:Vpc

This means it should be possible. Maybe separating the ec2:* permissions into their own statement with the aforementioned conditions could help you.

Related