Building for Scale and Traceability Using ABAC for Lambda Functions

Home Blog Building for Scale and Traceability Using ABAC for Lambda Functions

The most important thing with building out any application is to think BIG. Build for ten users now and 10,000 users tomorrow. Having infrastructure that scales as your needs do is critical for user adoption—one of the many reasons we love a serverless approach and particularly AWS Lambda.

The other part of any growth journey is managing access to organizational cloud infrastructure, especially with rapidly growing organizational development and DevOps teams. This ensures that the people who build, deploy, and maintain the applications and infrastructure have the right level of access when they need it.

At Lumigo we have been testing some new IAM functionality for Lambda functions that is really cool. The best news is this is now in GA, so we were excited to break it down for you!

Introducing ABAC for Lambda

Attribute Based Access Control (or ABAC) is an approach that defines how a user’s access is granted based on resource attributes. For AWS IAM this is done via defining access based on resource tags and user-based team, or project, roles.

For Lambda Functions this means you can now allocate resource access based on a project or team tag more easily. This allows for access to resources to be dynamically assigned as required, whilst maintaining a wider level of control at a user level.

For rapidly-scaling applications and the organizational teams that handle them, this is a great way to manage projects.

For example:

  • IAM User 1 is working as part of project team Alpha and is assigned the [Alpha] project tag as part of their IAM.
  • IAM User 2 and IAM User 3 are both working as part of project Beta and are assigned the [Beta] project team tag as part of their IAM.

Each project has assigned Lambda functions with associated project tags. All users can then only access Lambda functions with their matching tags.

The Beta project team is ahead of schedule so IAM User 2 is assigned to help out a few days a week on Project Alpha. IAM User 2 profile has the Alpha tag added, so they can now access Lambda Functions on both projects. The best part about using the ABAC method is that this can happen without the need to change the IAM policy.

ABAC for Lambda functions brings with it 4 tag types that can be utilized as parts of IAM controls. Attributes are a key, or a key and a value pair, which creates many more dimensions to how IAM permissions, roles, and users can be defined.

Here’s a look at the new controls being made available to Lambda functions

  • aws:RequestTag/key – Controls the creation of new lambda functions only with associated tags.
  • aws:tagKeys – Controls the specific tag keys that can be used on lambda function in a request.
  • aws:PrincipalTag/key – Controls what the assigned principal making the request is allowed to do.
  • aws:ResourceTag/key – Controls who can access tagged Lambda functions.

If you’re like me and you love getting hands-on with new tech, let’s take those new Lambda Function controls for a spin.

Getting set up

First, we need to set up a policy that has the right permissions to create Lambda functions using team-specific tagging. For this we are going to use team Alpha and team Beta.

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

Next we create another policy to only allow Lambda API actions providing the resource tag is set to team Alpha.

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

Then we need one more policy that gives permissions to `iam:PassRole` and `iam:ListRoles`.

It’s important to note that `iam:PassRole` does not support tag-based authentication, so the role will need permissions to ListRoles in order to create a function with existing execution using the AWS Console. It’s also important to note here that the `Resource` needs to be updated with a role-specific ARN from the setup process.

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Sid":"VisualEditor0",
         "Effect":"Allow",
         "Action":[
            "iam:ListRoles",
            "iam:PassRole"
         ],
         "Resource":[
            "Role specific ARN"
         ]
      }
   ]
}

Now, we need to create an IAM role, attach all 3 of these policies, and then tag the role with “Team: Alpha”. Finally, we can create a user and assign them the newly created role.

Now let’s test it out

Log in to the AWS console as your newly-created user and switch to the role they have been assigned.

Try creating a new Lambda function with the tag key `Team` and a value of `Gamma`. If the policies and IAM roles have been configured correctly, this should fail because the user is not allowed to create a resource using that tag.

If we try to create a Lambda function again using the `Team` key and the tag value of `Alpha` it should allow the resource to be created.

Note: Remember that tags are case sensitive!

The same should also work for invoking ABAC Lambda functions too. Only the associated `Team` -tagged IAM users and resources can appropriately invoke, create, and edit applicable resources.

Now let’s get really fancy.

You can also create the policies dynamically to allow permissions to Lambda API actions only if the resource tag matches the IAM role tag.This is using the `aws:ResourceTag/Team ${aws:PrincipalTag/Team}` condition as part of the policy.

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

Building out end-to-end observability using Lumigo Tag Filtering

Did you know that you can also filter specific resource tags in Lumigo? This can be done in a few different ways once you have created your Lumigo account and connected it to your AWS account

The first way is by using the AWS Tag drop-down menu from the Lumigo Functions tab. This will  contain all of the Lambda Functions tags from your AWS instance, allowing you to select specific tagged Lambda functions to filter within the Functions view.

The second way allows you to trace, observe, and debug Lambda functions utilizing Lumigo projects. You can group Lambda functions into different views by using the Monitored Functions Filtering found in your Lumigo settings.

To do this, head to your Lumigo dashboard and click on the drop down in the top right corner. Then select [+Add New Project].

Next, enter a project name. For this I am going to use “Team Alpha”, and click “Manually” to create the RoleARN. From there you will be whisked away to the AWS console to step through the role creation process. Once complete, switch back to Lumigo and paste the RoleARN to finish the project setup process.

Now we need to filter based on the resource tags so that only the Lambda Functions associated with the Alpha Team are included into the view. Click settings at the bottom of the left main Lumigo menu, then the MONITORING tab.

Now we can use the `tags:` filter to only include the Lambda functions with our ABAC resource tags for Team Alpha.

For this I’m going to use `Team:Alpha`. It’s important to remember here that tags are case sensitive.

The same process can be used for Team Beta which will create different views, by grouping the resources using tags, within your Lumigo instance.

Get signed up and take it for a spin

ABAC controls for Lambda Functions allows for a dynamic way in which teams and IAM users are able to create and access Lambda resources, additionally defining the type of access associated with their accounts.

To look at it another way, ABAC control is similar to placing a small stone to divert the course of a river as required. Allowing IAM users to only access the parts of the river as required by changing their assigned team tag values.

Want to go for a test drive? Get signed up and connected today.