6

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?

demosito
  • 223
  • 1
  • 7

2 Answers2

6

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": "*"
        }
    ]
}
Marcin
  • 215,873
  • 14
  • 235
  • 294
  • 1
    With 'IfExists' part it works indeed, thank you! However, I wonder does this really mean that modifying the interface on lambda creation is different from updating it as regular IAM user/role. I.e. when I issue ec2:CreateNetworkInterface it will have ec2:Vpc key in the request, whilst during lambda deployment it does not. If that's the case, then this solution is correct. – demosito Dec 24 '20 at 12:27
  • 1
    @demosito You can get more info about `ifExists` [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_IfExists). As explained there, sometimes execution of some actions requires access to various resources. Without `IfExist` the condition will be enforced for each such resource even though it may not support such condition, resulting in deny. `Ifexists` applies the conditions to resources and actions which provide such condition key. – Marcin Dec 24 '20 at 12:33
  • I understand this, however, the condition without `IfExists` doesn't work even for when "Action" contains a single entry (I tested with ec2:CreateNetworkInterface). Which means that the `ec2:Vpc` key is indeed not present in that request, although according to the [docs](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html#amazonec2-actions-as-permissions) it should. Which leads me to conclusion that during deployment of a lambda function these actions are performed somehow differently. – demosito Dec 24 '20 at 14:53
0

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.

Maurice
  • 11,482
  • 2
  • 25
  • 45
  • Thank you for your reply, but like I said, I tried to check the exact conditions you proposed (ec2:Vpc and ec2:Subnet) with "Condition": {"StringEquals": {"ec2:Vpc": "${my_vpc_arn}" }} entry, but this raised PermissionDenied error. It looks like these keys aren't being set in the requests for some reason. – demosito Dec 24 '20 at 11:49