Skip to content

CLI Reference

ncc-erik-steringer edited this page Mar 31, 2021 · 3 revisions

Principal Mapper provides a command-line interface to all of its core functions. This page details all the different operations and parameters you can use.

Credentials

You can pass credentials to PMapper the same as you do when using the AWS CLI. If you call aws --profile <profile> configure and provide access keys for an IAM User, you can then use that profile in PMapper as in pmapper --profile <profile> .... If you don't specify a profile, PMapper looks for a default profile, AWS_* environment variables, the EC2 instance metadata service, etc. to try to locate and use credentials the same as the AWS CLI does.

Credentials are necessary for the operations that go query the AWS API to gather information on an account/organization (graph and orgs subcommands) but you can instead use --account for other operations (argquery, query, analysis, visualize). This saves time, because otherwise PMapper will call the AWS STS API to figure out which account the credentials it's using belongs to.

graph

All operations for creating, listing, and displaying information about Graphs are available with the graph subcommand in the CLI. For PMapper, a Graph is a model of the different IAM Users and Roles (Principals) and how they are able to access each other.

graph create

The graph subcommand itself has a set of subcommands for its different operations. The create subcommand does the work of creating a Graph. This requires access to an IAM User/Role that is authorized to read data in the account (the ReadOnlyAccess managed policy works for this). There are additional parameters you can specify that affect the creation process:

  • --ignore-orgs: PMapper checks to see if the account that it is creating a Graph for is a member of an AWS organization. Note that the organization has to be stored first (see the orgs subcommand). If so, it will apply SCPs during the edge identification process (avoids things like EC2-related edges when the account has an SCP that blocks all EC2 access). When this flag is specified, SCPs will not apply to edge identification.
  • --include-regions | --exclude-regions: PMapper allows one or the other of these arguments to list regions to include or exclude when pulling data from the AWS API. If you know all the account's resources are in a set of regions, then --include-regions can help reduce the time that creating a Graph takes. If you know that some regions are disabled but need a thorough check, --exclude-regions lets you ignore those extra regions.
  • --include-services | --exclude-services: PMapper pulls data from several services when creating a Graph. You can specify one or the other of the arguments to include/exclude which services are looked at for creating Edges (does not apply to resource-policy gathering).

Here's an example:

$ pmapper graph create --exclude-regions af-south-1 ap-east-1 eu-south-1 me-south-1

graph list

The list subcommand prints the different AWS account IDs that PMapper has a Graph for.

graph display

The display subcommand lists out high-level statistics about the Graph that PMapper stored for the given AWS account. Note that the --account global parameter will work here.

query

The query subcommand lets you create "plain-English" queries to run against Graph data. You can see if a given IAM User/Role is able to make a given AWS API call, or if that user can pivot its way into another IAM User/Role that can make the API call. There is another wiki page that has a reference for the syntax of those queries.

There are additional arguments you can use:

  • -s | --skip-admin: When running a query on multiple principals in an account, this flag skips the IAM Users/Roles that are marked as admins. Note that non-admins that can pivot to admins are still included.
  • -u | --include-unauthorized: This flag will include output saying if a principal is not authorized or able to make a given API call. By default, PMapper just reports the principals that can.
  • --with-resource-policy | --resource-policy-text: These parameters, of which only one can be specified at a time, set the resource policy to include as part of the authorization check. --with-resource-policy will automatically identify the resource in the query and load that policy (has to be one of the cached policies, PMapper currently supports IAM, KMS, S3, SNS, and SQS). The other arg, --resource-policy-text, lets you type out a resource policy to include in the authorization check (should support all AWS).
  • --resource-owner: For queries where the resource ARN does not specify an account (i.e. for S3 buckets/objects), this argument takes the account ID of the owner of the resource.
  • --session-policy: This parameter lets you include a session policy (from the AWS STS APIs) as part of the authorization check. Note that it only applies to the initial principal and is not passed along to other principals reached via Edges.
  • --scps: This flag will cause the authorization check to include any Service Control Policies (SCPs), assuming the account is part of an organization and the organization's data has been obtained (orgs subcommand).

When calling the query subcommand, you have to specify the additional arguments and then finally the actual query. The query should be enclosed in a string that will not expand wildcards (*) or instances of dollar-signs ($) in your shell. For example, when I use Bash to work with PMapper, I enclose the query in single-quotes/apostrophes ('<query>'). Here's an example:

$ pmapper --account 000000000000 query -s 'who can do lambda:UpdateFunctionCode with arn:aws:lambda:us-west-2:000000000000:function:*'

argquery

The argquery subcommand creates parameterized queries to run against Graph data. It operates the same as the query subcommand, but takes arguments to specify action/resource/condition rather than interpreting a query. The parameters are:

  • --principal: This should be a string to match one or more IAM Users/Roles in the given account. Note that it takes the "searchable name" of the users/roles so arn:aws:iam::000000000000:user/admins/Mary needs to be referred to as user/Mary. By default this value is set to *, which runs the query against all principals in the account, so you can exclude this argument altogether to just query all principals.
  • --action: This argument specifies the action to do authorization checks against. For example, to launch an EC2 instance, you want ec2:RunInstances.
  • --resource: This argument specifies the resource to do authorization checks against, which should be an ARN for a specific resource. This defaults to a wildcard * value, and the argument can be excluded to default to that value.
  • --condition: This specifies a key-value pair, separated with an equals-sign (=), for a condition context key and its value. This parameter can be invoked multiple times for as many conditions as necessary.
  • --preset: This specifies a preset query to run rather than an authorization check.
  • -s | --skip-admin: When running a query on multiple principals in an account, this flag skips the IAM Users/Roles that are marked as admins. Note that non-admins that can pivot to admins are still included.
  • -u | --include-unauthorized: This flag will include output saying if a principal is not authorized or able to make a given API call. By default, PMapper just reports the principals that can.
  • --with-resource-policy | --resource-policy-text: These parameters, of which only one can be specified at a time, set the resource policy to include as part of the authorization check. --with-resource-policy will automatically identify the resource in the query and load that policy (has to be one of the cached policies, PMapper currently supports IAM, KMS, S3, SNS, and SQS). The other arg, --resource-policy-text, lets you type out a resource policy to include in the authorization check (should support all AWS).
  • --resource-owner: For queries where the resource ARN does not specify an account (i.e. for S3 buckets/objects), this argument takes the account ID of the owner of the resource.
  • --session-policy: This parameter lets you include a session policy (from the AWS STS APIs) as part of the authorization check. Note that it only applies to the initial principal and is not passed along to other principals reached via Edges.
  • --scps: This flag will cause the authorization check to include any Service Control Policies (SCPs), assuming the account is part of an organization and the organization's data has been obtained (orgs subcommand).

Here's an example:

$ pmapper --account 000000000000 argquery \
    --principal 'user/only_launch_with_mfa'
    --action 'ec2:RunInstances' \
    --condition 'aws:MultiFactorAuthAge=1' \
    --condition 'aws:MultiFactorAuthPresent=true'

repl

PMapper includes a read-evaluate-print-loop (REPL) feature for running multiple queries against a single account, keeping that account's Graph and relevant caches in-memory. It comes with its own help-output to explain how to use it.

analysis

The analysis subcommand generates either a Markdown-formatted report or a JSON object with findings derived by analyzing the Graph. Note that this writes to stdout, so redirect to save it as a file. The parameter controlling the output type is --output-type which takes either text or json as a value.

visualize

PMapper's visualize subcommand creates visualizations of Graph data and creates files (naming convention includes account ID, file extension, and visualization type). This supports creating SVGs, PNGs, DOTs, and GraphML files. The arguments are:

  • --filetype: This specifies which file type to output, and accepts the values: svg, png, dot, and graphml.
  • --only-privesc: This flag makes PMapper generate an image that only includes admin Nodes and the Nodes that can escalate privileges by accessing admin Nodes.

orgs

Much like the graph subcommand, PMapper has an orgs subcommand that itself has subcommands for creating/listing/displaying/updating organizations data.

orgs create

The create subcommand pulls data from AWS Organizations to create a local OrganizationTree object that represents an organization. This operation has to be run from the management account (formerly referred to as the master account) of the organization, and the user/role being used to call the AWS API has to be authorized for read-access to AWS Organizations. This operation takes no additional arguments.

orgs list

The list subcommand prints a list of all the organizations that PMapper has stored, by their organization ID.

orgs display

The display subcommand prints out all data stored on an given organization. It takes an argument, --org, that should be the organization ID of the organization to display.

orgs update

The update subcommand goes to all the stored Graphs and adds organizations metadata to them. This is necessary for running argquery/query to include SCPs during authorization checks. It takes the same --org argument as the display subcommand, the organization ID to update graphs for. Note that if you pull organizations data first, then pull a Graph, the Graph will have that association without needing to run orgs update.