Analyzing IAM Policies at Scale with Parliament

Dustin Whited
ScaleSec
Published in
7 min readJul 21, 2020
Analyzing IAM Policies at Scale with Parliament

For even the most seasoned AWS engineer, configuring Identity and Access Management (IAM) with least privilege can become an endeavor in complex environments. During a breach, an overly permissive policy can result in not only the application’s data being leaked, but it could also allow an attacker horizontal movement into another application, or even an entirely different environment.

IAM policies and roles are a foundational part of every AWS cloud deployment. Eliminating misconfigurations in the environment will help reduce blast radius and decrease attacker effectiveness in the event of a breach. The most efficient and repeatable method for finding these misconfigurations is to automate the detection process using existing libraries. This blog will explore how the Parliament library can be run ad-hoc on a single policy, upon an entire role with multiple attached policies, and leverage a custom detector.

What is Parliament?

Parliament is a tool written in python that lints IAM policies and returns detailed findings based upon misconfigurations in the policy content. It will detect if a policy is malformed, identify unknown permissions that do not exist within the platform, and callout resource mismatches when resources and permissions do not apply to each other.

If you have company-specific security controls and requirements for IAM policies, custom detectors (Private Auditors) can be created to extend Parliament.

Let’s explore an example policy: this policy grants the full EC2 service and a single RDS action, ModifyDBInstance on any resource. It’s also scoped down S3 calls to a specific bucket.

This policy has a few problems, one of which is easy to spot. ec2:* grants 399 different permissions. This includes access to DeleteVPC and DeleteNetworkAclEntry.

Sometimes the problems aren’t this obvious, but coming to the table informed about overly-permissive policies and misconfigurations will help implement more secure policies.

This is where Parliament can help.

Parliament as a CLI Tool

First, install Parliament with pip:

pip install parliament

Save the overly permissive policy to a file called policy.json and run it through Parliament with the --file argument:

parliament --file policy.json

The results should look like this:

Raw Parliament Output

Parliament globs wildcard permissions, such as ec2:* into every possible permission included in the wildcard. Each permission is included in the Actions array of the Resource Star finding.

Using a slightly more condensed version of the output, there are two instances of unnecessary usage of Resource: “*”.

This finding is created when an action is not restricted to any resource, but could be restricted according to the IAM documentation. Parliament retrieves this information from an internal IAM actions json file that is scraped from the various AWS Service’s IAM documentation pages.

Resource mismatch is created when the permission cannot take action on a resource restriction. In this example, s3:GetObject and s3:ListBucket were restricted to a bucket, but the s3:GetObject permission can only act upon object resource types.

The full list of finding types Parliament can generate out of the box is located in the config file.

Parliament as a Python Library

Running Parliament in the command line interface (CLI) gives users the ability to identify issues with IAM policies before creation, and you can scan all policies in an account with the --auth-details-file flag, but what if you wanted to look at specific roles?

Parliament is packaged as a CLI tool, but can also be leveraged as a Python library.

First, create a boto3 connection to get all the policies for a role. The profile and role used will be specific to your environment, but for the sake of example, here it is called ‘dev’ and the role being investigated is ‘test-role’.

Instantiate an empty variable named all_policies to store the policy data. All policy names and content will be stored in this dictionary for analysis.

There are two different types of IAM policies that could be attached to the role: inline and managed. Each type has a unique boto3 call to list and retrieve the policy name (inline) and ARN (managed). Inline policies use list_role_policies. Managed policies use list_attached_role_policies. The policy identifier is stored in the key PolicyNames for inline policies, and AttachedPolicies for managed policies.

Stored within the inline_policies variable is the list of inline policy names attached to the role, e.g. ['inline-policy', 'instance-policy']

Within the attached_policies variable is the list of PolicyNames and PolicyArns for each managed policy, e.g.[{'PolicyName': 'SecurityAudit', 'PolicyArn': 'arn:aws:iam::aws:policy/SecurityAudit'}]

Now that the policies attached to the role have been identified, the next step is to iterate through the lists and pull the policy documents.

Inline policies are retrieved with get_role_policy. The policy content is stored within the PolicyDocument key.

Managed policies can have different versions. The default version of the policy document is retrieved with get_policy. After retrieving the policy version number, it will be specified in the get_policy_version call.

Finally, each policy document is added to the all_policies dictionary and the function returns that content.

The example above shows the structure of the all_policies dictionary. Policy content is stored under each policy’s name. This will make it easier to report which policy has each finding.

Now that policy documents can be retrieved, let’s create a function to run them through Parliament. At its core, Parliament has a Policy Python class. From this class, policies can be generated and findings identified. Import this class into the script, convert each policy document to the Policy class, and then invoke the analyze() function.

When running this function, you will notice that there is no output from analyze(). The analyze() function stores findings in the Policy class. Formatting will be added based off of the built in Parliament function print_finding. When running this function across many policies at once, adding a field in the finding dictionary called policy_name will identify the location of the finding.

After creating the findings, a loop deduplicates the findings and only adds it to the new array if the finding does not already exist. Finally, the deduplicated findings are returned to be printed or parsed.

Tie this all together with a check_role function that invokes get_policies_for_role, runs each policy through the run_parliament function, and prints the findings.

Run this with check_role(rolename) and it can now parse multiple policies on a single role, and have similar output as the CLI.

Take it to the next level with custom detectors

With the basic framework created for retrieving and analyzing all policy data for a role, it can be extended to detect misconfigurations that are unique to the environment and company standards. Perhaps there is a control that states IAM policies should not have wildcards in the action. Requiring policies specifically enumerate permissions in IAM policies can prevent unexpected permissions being granted to the application.

Reflecting upon ec2:* with its 399 permissions, when AWS introduces a new EC2 permission, it would automatically be granted to the role. The role likely only needs to use a few APIs, but using a wildcard has the potential to allow the role’s permissions to grow exponentially over time.

These wildcards can be detected with a Private Auditor, a separate python file that is integrated into the existing policy analysis. The Private Auditor file can also be used in the CLI version of Parliament.

Create a file called “action_wildcard.py” and then define a function called check_for_wildcard. Raw policy content is retrieved in json format from the Policy class with policy_json.

Ensure the Statement is a list of SID(s), and that the Action contained within is also a list. Iterate through the actions and detect if * is in the action and if so, add a finding called Action_Wildcard, and denote the offending action.

Import the private auditor file and invoke check_wildcard(policy) after analyze(). ec2:* has a wildcard in the action; the private auditor found it, and created a finding.

Detection and Prevention:

Wildcards on action permissions is but one example; private auditors can be extended to find other patterns that may exist in IAM policies. Detection using Parliament private auditors can fit a variety of IAM policy control requirements — explicit resource restriction, ABAC, and even which conditionals exist in a policy. If placed in an IAM deploy pipeline, Parliament could be an effective preventative control, ensuring policies with undesirable content are not created, and providing feedback to developers on how they can be fixed.

A more operationally ready version of the script, which parameterizes role name and profile, can be found here.

Thank you to Scott Piper for providing additional info on Parliament functionality and to @Sarah Gori, @Steven_Adegbenle, and @Eric_Evans for their editor contributions.

About Us

ScaleSec is a service-disabled, veteran-owned small business (SDVOSB) for cloud security and compliance that helps innovators meet the requirements of their most scrutinizing customers. We specialize in cloud security engineering and cloud compliance. Our team of experts guides customers through complex cloud security challenges, from foundations to implementation, audit preparation and beyond. Learn more at https://scalesec.com.

We are hiring!

The information presented in this article is accurate as of 7/21/2020. Follow the ScaleSec blog for new articles and updates.

Connect with ScaleSec for AWS business

ScaleSec is an Advanced Consulting Partner guiding AWS customers through security and compliance challenges. ScaleSec’s compliance advisory and implementation services help teams leverage cloud-native services on AWS. We are hiring!

Connect with ScaleSec for AWS business.

--

--