Attribute-based access control for Lambda - AWS Lambda

Attribute-based access control for Lambda

With attribute-based access control (ABAC), you can use tags to control access to your Lambda functions. You can attach tags to a Lambda function, pass them in certain API requests, or attach them to the AWS Identity and Access Management (IAM) principal making the request. For more information about how AWS grants attribute-based access, see Controlling access to AWS resources using tags in the IAM User Guide.

You can use ABAC to grant least privilege without specifying an Amazon Resource Name (ARN) or ARN pattern in the IAM policy. Instead, you can specify a tag in the condition element of an IAM policy to control access. Scaling is easier with ABAC because you don't have to update your IAM policies when you create new functions. Instead, add tags to the new functions to control access.

In Lambda, tags work at the function level. Tags aren't supported for layers, code signing configurations, or event source mappings. When you tag a function, those tags apply to all versions and aliases associated with the function. For information about how to tag functions, see Using tags on Lambda functions.

You can use the following condition keys to control function actions:

  • aws:ResourceTag/tag-key: Control access based on the tags that are attached to Lambda functions.

  • aws:RequestTag/tag-key: Require tags to be present in a request, such as when creating a new function.

  • aws:PrincipalTag/tag-key: Control what the IAM principal (the person making the request) is allowed to do based on the tags that are attached to their IAM user or role.

  • aws:TagKeys: Control whether specific tag keys can be used in a request.

For a complete list of Lambda actions that support ABAC, see Function actions and check the Condition column in the table.

The following steps demonstrate one way to set up permissions using ABAC. In this example scenario, you'll create four IAM permissions policies. Then, you'll attach these policies to a new IAM role. Finally, you'll create an IAM user and give that user permission to assume the new role.

Prerequisites

Make sure that you have a Lambda execution role. You'll use this role when you grant IAM permissions and when you create a Lambda function.

Step 1: Require tags on new functions

When using ABAC with Lambda, it's a best practice to require that all functions have tags. This helps ensure that your ABAC permissions policies work as expected.

Create an IAM policy similar to the following example. This policy uses the aws:RequestTag/tag-key and aws:TagKeys condition keys to require that new functions and the IAM principal creating the functions both have the project tag. The ForAllValues modifier ensures that project is the only allowed tag. If you don't include the ForAllValues modifier, users can add other tags to the function as long as they also pass project.

Example – Require tags on new functions

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": [ "lambda:CreateFunction", "lambda:TagResource" ], "Resource": "arn:aws:lambda:*:*:function:*", "Condition": { "StringEquals": { "aws:RequestTag/project": "${aws:PrincipalTag/project}" }, "ForAllValues:StringEquals": { "aws:TagKeys": "project" } } } }

Step 2: Allow actions based on tags attached to a Lambda function and IAM principal

Create a second IAM policy using the aws:ResourceTag/tag-key condition key to require the principal's tag to match the tag that's attached to the function. The following example policy allows principals with the project tag to invoke functions with the project tag. If a function has any other tags, the action is denied.

Example – Require matching tags on function and IAM principal

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:InvokeFunction", "lambda:GetFunction" ], "Resource": "arn:aws:lambda:*:*:function:*", "Condition": { "StringEquals": { "aws:ResourceTag/project": "${aws:PrincipalTag/project}" } } } ] }

Step 3: Grant list permissions

Create a policy that allows the principal to list Lambda functions and IAM roles. This allows the principal to see all Lambda functions and IAM roles on the console and when calling the API actions.

Example – Grant Lambda and IAM list permissions

{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllResourcesLambdaNoTags", "Effect": "Allow", "Action": [ "lambda:GetAccountSettings", "lambda:ListFunctions", "iam:ListRoles" ], "Resource": "*" } ] }

Step 4: Grant IAM permissions

Create a policy that allows iam:PassRole. This permission is required when you assign an execution role to a function. In the following example policy, replace the example ARN with the ARN of your Lambda execution role.

Note

Do not use the ResourceTag condition key in a policy with the iam:PassRole action. You cannot use the tag on an IAM role to control access to who can pass that role. For more information about permissions required to pass a role to a service, see Granting a user permissions to pass a role to an AWS service.

Example – Grant permission to pass the execution role

{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "iam:PassRole" ], "Resource": "arn:aws:iam::111122223333:role/lambda-ex" } ] }

Step 5: Create the IAM role

It's a best practice to use roles to delegate permissions. Create an IAM role called abac-project-role:

  • On Step 1: Select trusted entity: Choose AWS account and then choose This account.

  • On Step 2: Add permissions: Attach the four IAM policies that you created in the previous steps.

  • On Step 3: Name, review, and create: Choose Add tag. For Key, enter project. Don't enter a Value.

Step 6: Create the IAM user

Create an IAM user called abac-test-user. In the Set permissions section, choose Attach existing policies directly and then choose Create policy. Enter the following policy definition. Replace 111122223333 with your AWS account ID. This policy allows abac-test-user to assume abac-project-role.

Example – Allow IAM user to assume ABAC role

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::111122223333:role/abac-project-role" } }

Step 7: Test the permissions

  1. Sign in to the AWS console as abac-test-user. For more information, see Sign in as an IAM user.

  2. Switch to the abac-project-role role. For more information, see Switching to a role (console).

  3. Create a Lambda function:

    • Under Permissions, choose Change default execution role, and then for Execution role, choose Use an existing role. Choose the same execution role that you used in Step 4: Grant IAM permissions.

    • Under Advanced settings, choose Enable tags and then choose Add new tag. For Key, enter project. Don't enter a Value.

  4. Test the function.

  5. Create a second Lambda function and add a different tag, such as environment. This operation should fail because the ABAC policy that you created in Step 1: Require tags on new functions only allows the principal to create functions with the project tag.

  6. Create a third function without tags. This operation should fail because the ABAC policy that you created in Step 1: Require tags on new functions doesn't allow the principal to create functions without tags.

This authorization strategy allows you to control access without creating new policies for each new user. To grant access to new users, simply give them permission to assume the role that corresponds to their assigned project.