During August 2022 we published a blog discussing AWS Security Trends of 2022 , one of which was ABAC in Lambda. AWS allows administrators to use tags to designate attributes for both IAM and AWS resources. Attribute Based Access Control, or ABAC, is a strategy to allow permissions assignment based on the value of such tags. In July 2022, AWS expanded support for the use of the following condition keys to enforce ABAC with Lambda: → aws:TagKeys, aws:ResourceTag/tag-key, aws:RequestTag/tag-key, and aws:PrincipalTag/tag-key. This support opens a variety of infrastructure design and management options, all of which have the potential to introduce high-risk attack vectors to an organization’s cloud presence.

Users can successfully incorporate ABAC in a Lambda-based workflow, as we will discuss using example use-cases for ABAC. We also will analyze security issues in the context of an example misconfigured setup. Finally, we will emphasize necessary considerations that users need to take into account before incorporating ABAC in their cloud environment.

The Use of ABAC in Lambda Workflows

RBAC vs ABAC

In AWS, Role Based Access Control (RBAC) uses policies to define permissions for IAM entities (users, groups, and roles) to allow them to perform necessary actions for their jobs. However, when an organization follows the principle of least privilege, RBAC also requires frequent updates to the policies to accommodate the creation of new resources or IAM entities within the AWS environment. From a security standpoint, the increasing complexity of managing an RBAC scheme at scale becomes a concern.

In contrast, as AWS notes , ABAC allows for a more straightforward process of creating and maintaining IAM policies that are easy to scale with the growth of organizations and their resources. Its tags essentially function as “segregation parameters” that can help define conditions around associativity to those parameters based on which permissions apply. Regardless of how many entities an organization adds, the conditions remain consistent and require less updating than a complex system of policies that define permissions.

When to Introduce ABAC

Organizations can introduce ABAC to their Lambda environment at any point. Those migrating to cloud-based workflows for the first time, or starting afresh in the cloud, may establish their access control strategies to be ABAC-centric based on extrapolated metrics of growth in scale. Conversely, organizations with a well-established infrastructure may benefit from having ABAC co-exist in their environment with RBAC, specifically to allow a slow transition away from specific RBAC policies that increase complexity when scaling infrastructure. This is an especially useful approach when the complexity of managing RBAC controls increases due to the growing scales of business-related workflows.

A Word of Caution

As we have mentioned, ABAC significantly improves permissions management in a cloud environment by requiring very few updates to policies even during infrastructure growth and scale-up. A potential drawback, however–particularly for organizations with established cloud workflows–is that a new ABAC scheme may not be wholly applicable or as easy to implement initially, depending on the type and scale of the environment. Attempting to cobble together an ABAC-esque scheme without actually using ABAC can seem like a tempting solution in this situation, so we want to emphasize that we strongly discourage doing so.

While an organization already using RBAC could attempt to replicate ABAC-based schemes, this would not be a secure solution. It would involve  applying organization-wide naming conventions and wildcards (*) with string matching conditions to ARNs within IAM policies. However, using wildcards is not a security best practice and can introduce lapses within permission configurations. Instead, said organization would be better served by incorporating an ABAC-based scheme.

Uses for ABAC in Lambda

Generally speaking, organizations can use ABAC with Lambda in two ways. First, ABAC can control access “TO” Lambda functions by granting specific entities access to create or invoke specific Lambda functions in specific contexts such as an environment, account, or team. Figure 1 is a graphic representation of controlling access of IAM entities to Lambda functions based on PII or PCI data classification.

Figure 1: Developers across two separate organizational development teams, cleared for PII access through tags, have access to invoke all Lambda functions with the PII tag key set to true.

Additionally, ABAC can control access “OF” Lambda, meaning it can control Lambda functions’ access to specific resources based on the respective tags.

Applicability of ABAC

Organizations may consider the following applicability questions when deciding whether to incorporate the use of ABAC:

  • Do certain resources, such as Lambda functions, common to multiple individuals that may span across multiple teams, require access management? If yes, ABAC can be useful in implementing such a scheme.
  • Are current permissions designed based on a data-classification scheme using RBAC? If yes, and also if the RBAC policies use wildcards, applying ABAC can improve overall permissions management.
  • Does a specific RBAC design increase the difficulty of maintaining policies during an infrastructure scale-up? If yes, ABAC can help consolidate additional resources into existing attributed groups to enforce permissions.

Functions, Teams, and Turnover

Suppose an organization operates hundreds of Lambda functions and has many different teams, all of which are subject to irregular personnel changes. In that case,  ABAC can help regulate permissions so that specific individuals are the only ones permitted to work with the Lambda functions specific to their teams. In such a case, senior team personnel would have the ability to tag functions while globally (using Service Control Policies, or SCPs) denying the execution of functions without tags. This is also useful when a team or organization needs to restrict certain groups of individuals to sandboxes for untethered execution across functions that span several accounts.

Review-based Function Execution Approval

Lambda functions are a prime target for attackers to exploit misconfigured policies because roles can be passed to Lambda functions. Therefore, Lambda functions’ code should be subject to a review process, wherein marking them as approved grants them the ability to run in a particular environment. An example tag key for such a case is “Approved” or “Execute-in-Prod” and the value can be as simple as “true” or “false.” A well-defined tagging system that prevents the execution of rogue Lambda functions acts as a Defense in Depth control.

An approval process can be one of two types (see also Figure 2):

  • Manual: Only team owners or tag administrators are allowed to add the necessary execution approval tags for functions.
  • Automated: This scheme incorporates approvals within a CI/CD pipeline such that when a merge takes place after a review in AWS CodeCommit, it triggers another Lambda function that deploys the code and tags it with the approval attribute.

Figure 2: Manual and automated flows for tagging Lambda functions to allow their execution within production environments.

Placing a service control policy (SCP) within the review-based approval scheme prevents anyone from invoking a non-approved function. Vertical Relevance’s blog   introduces the concept of ‘Compliance Officers’ and describes a similar SCP at play. Tagging approved Lambda functions can prevent unauthorized or rogue Lambda functions from executing in the environment. From a security standpoint, this could prevent an attacker from deploying a function via a foothold within a cloud environment.

Data Classification

Lambda functions may need access to multiple data sets across several AWS services depending on their use-cases. For example, one prevalent use for Lambda functions is  processing information quickly and triggering an AWS action afterward. They also commonly serve single-page web applications and APIs. Tagging under an ABAC scheme can be very useful in regulating access to data in such situations. Additionally, if an organization needs to maintain access according to its data-classification paradigms, then ABAC can complement such designs by dynamically granting access based on attributes. An example of this is an organization that works across PII and PHI intending to restrict access to both sets of information.

Regulate Access to Sensitive Data

Suppose an organization deals with both Personally Identifiable Information (PII) and Personal Health Information (PHI) data. In that case, their Lambda function constructs can access such data based on the attributes of both the data and the functions. It also simplifies the process of adding new functions and configuring access, as cloud architects can set some of the necessary permissions to grant automatically based on tags applied to the IAM entities and the functions.

Similarly, cloud architects can limit access to (or actions on) production databases (or other resources) unless the function has the appropriate tag for both the team and access level. In this use-case, for instance, an HR team’s Lambda function cannot access an ML team’s secrets. We do want to emphasize that tags do need to apply to Lambda execution roles in order to be effective in this access-based use case. This is because the code in a Lambda function uses a role to perform actions, so to limit those actions tags must apply to the role; applying tags to the function only limits the actions on Lambda functions, not Lambda functions’ access.

Resource Decommissions through Lambda

Resource decommissioning is an issue that can cause important services to shut down. Attackers with an environment foothold can trigger it intentionally, and insiders can do so unintentionally due to misconfigured access. Tagging can help improve this process in the following way:

  • An organization grants teams the ability to assign tags to the resources they manage.
  • Each team maintains a decommissioning Lambda function for deleting or terminating resources they manage.
  • A different Lambda function can run as a cron job within the organization to identify resources tagged with the key “Decommission” and value “Proceed.” It would add their ARNs to a decommission SQS queue as well as change the tag value to “Queued.”
  • The decommissioning Lambda function (or a designated IAM principal) can delete/terminate the ARNs in the queue after a delay of 24 hours for reversal. It also can send an SNS notification to appropriate team owners, which tags can further facilitate.

This maintains an attribution-based design to decommission infrastructure so that resource deletion always is non-repudiated and, in the case of any compromise, cannot be conducted by disallowed parties.

Security Considerations

Defining a Misconfigured Example

We previously noted that misconfigured ABAC policies can introduce attack vectors for privilege escalation. Internal threat actors or attackers with an environmental foothold can exploit such issues. Consider the following scenario with an insecure configuration:

An organization has two users, dev1 (belonging to team Alpha) and dev2 (belonging to team Beta). Each of these users has permissions that allow Lambda actions based on the tag value of “Team.” The organization stored two secrets, secret_alpha and secret_beta within Secrets Manager. Both the secrets exist without any resource policies. Figure 3 is a diagrammatic representation of the scenario:

Figure 3: An insecure application of ABAC to control access amongst users, Lambda functions, and secrets across two teams.

See figure 4 for example policies for dev1.

Figure 4: IAM policies associated with the dev1 user.

The dev2 user has identical policies except for the one invoking and updating Lambda functions, which would read “Beta” instead of “Alpha” under the policy condition.

The organization configures a Lambda function to allow the reading of secrets, with an execution role that has the permission set defined in Figure 5.

Figure 5: IAM policy associated with the Lambda execution role read_secret.

The users and the function all have the appropriate tags. In essence, the function role can read all secrets in the account. The user dev1 can invoke a function and update its code if the resource (function) tag is “Alpha.” Although this seems well-done, misconfigurations do exist within this scenario and we definitely can make improvements.

Why It Does Not Work, and How to Fix It

Problem A: Wildcard Secrets

The Lambda execution role policy allows reading wildcard secrets, or all the secrets in the account. This would allow user dev1 on team Alpha to update the function code or create a new function with the same role (using ‘iam:PassRole’) to read secrets meant for team Beta. The inverse loophole exists for dev2 . Therefore, using ABAC does not automatically eliminate the need to review and maintain resource policies.

RBAC Based Solution

One fix, using RBAC, requires ensuring that each Lambda function has unique execution roles and no wildcards exist in the policy. In this example, we would replace the wildcard within “Resource” with the ARN of the secret that only “Alpha” team members should be able to read. For this particular scenario, the RBAC solution is superior to either of the ABAC solutions.

ABAC Based Solutions

Using ABAC, one solution is to match the Lambda execution role’s tag with that of the user such that either a resource policy or an SCP controls access to secrets. In our opinion, this ABAC solution would be best for a scenario that invokes functions as triggers, because SCPs can limit the execution roles. Figure 6 shows an example of this SCP.

Figure 6: An example of an SCP used to enforce global limits on the secretsmanager:GetSecretValue action.

Another ABAC-based solution is to allot a role to users with all the permissions they need and allow them to pass that role to a Lambda function through an inline policy. This role can be tagged at creation. The presence of an SCP, such as the one shown in Figure 6, can effectively prevent the Lambda function created by the user from accessing secrets that the user is not authorized to obtain.

Problem B: Creating Lambda Functions

Lastly, as Figure 3 showed, the two users had access to create Lambda functions as long as the functions had the tag “Team” with a value of “Alpha” or “Beta”. However, the action to tag Lambda functions also follows the same condition. Therefore, the dev1 user tagged with {“Team”:“Alpha”} could create a new Lambda function and tag it with {“Team”:“Beta”}. The inverse would be true for the dev2 user.

An attacker could not exploit this condition on its own because the actions ‘lambda:UpdateFunctionCode’ and ‘lambda:InvokeFunction’ are only allowed on functions with the tag {“Team”:“Alpha”}. Regardless, the loophole is indicative of a vulnerable policy resulting from a failure to account for the possibility that new functions could be created and tagged outside of the defined use-case. Let us say an attacker subjected the functions tagged with {“Team”:“Beta”} to automated execution via cron-jobs or any other trigger. Dev1 then could exploit the misconfigured policy by publishing code during creation that retrieves secrets belonging to team Beta and sends it to dev1 . Dev2 could accomplish the opposite. This part of the misconfigured example emphasizes the nuanced care required to configure ABAC-based policies correctly.

The Solution

To fix this, cloud architects should modify the “StringEquals” condition in the inline policy to read as “${aws:PrincipalTag/Team},” as Figure 6 shows. Doing so would ensure that a user is not able to tag a Lambda function with a value that does not match their own principal tags. We also would like to emphasize that a misconfigured policy such as we have discussed can result from a cloud engineering team trying to make policies more adaptable and applicable to several entities at once. Although doing that is a good optimization step, cloud architects should take utmost care to ensure that their policies satisfy the principle of least privilege and such loopholes do not exist.

Points of Consideration

Using ABAC and RBAC together allows for dynamic modifications of policies and ease of scaling infrastructure, thereby making it a better strategy than an ABAC-only scheme from a security standpoint. That said, cloud architects will want to take the following security-oriented steps when configuring their ABAC scheme in Lambda, regardless of whether RBAC is involved:

  • Understand that you can specify tags across several contexts, such as an AWS Organization (multi-account), a single account, or across non-AWS groups, such as teams and data-classification schemes. To this end, be sure you consider tags as being separate from IAM groups (unlike with RBAC). Tags can span logical groups, even across multiple IAM groups, to support a more dynamic classification of permissions.
  • Decide which individuals you will allow to specify tags. For example, you could grant the ability to team owners of a development group or managers of a business-level workflow. Provide “sts:AssumeRole” permissions to these individuals so they can assume a tagging role to carry out the tagging actions.
  • Consider who you will allow to define the roles that Lambda functions can assume. Note that granting such permissions to a developer could result in an escalation of privileges.
  • Limit what tags individuals with tagging permissions can assign, based on the Principle of Least Privilege. The allowed tags should relate directly to a set of job functions within their team or department. For example, a role “role/hr-tag-manager” for a Human Resources team should only be able to tag resources with {“Team”:”HR”}. This will increase protection against privilege escalation attacks.
  • Ensure that you limit the action of tagging resources within policies for both IAM entities and resources. In particular, try to avoid using wildcards or catch-all conditions within policies whenever possible.
  • Use organization-wide service control policies (SCPs) to prevent users from changing tags of resources that fall outside of their “cloud jurisdiction.” For example, the HR team tag manager role should not be able to tag resources of the Machine Learning team. Consider implementing other similar policies, such as a global denial of activity by untagged resources.
  • Remember that SCPs do not overrule resource-based policies. Standardize a golden path for deploying resources to ensure resources like Lambda functions are well-protected through both SCPs and resource policies (if they exist).

Following these recommendations when deploying ABAC policies for workflows involving resources like Lambda will ensure that your organization always follows best practices.

In conclusion, while AWS’s support for ABAC is an excellent addition to services like Lambda, organizations must keep security considerations in mind while building their ABAC-based cloud solutions. This is the only way to ensure no access-based loopholes exist for attackers to abuse.

Resources

  1. https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html
  2. https://aws.amazon.com/blogs/compute/scaling-aws-lambda-permissions-with-attribute-based-access-control-abac/
  3. https://aws.amazon.com/blogs/security/simplify-granting-access-to-your-aws-resources-by-using-tags-on-aws-iam-users-and-roles/