Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if an IAM access key has specific permissions?

Is it possible to check if a particular AWS IAM key has permissions for a set of specific commands?

Essentially, is there an API for AWS's privacy simulator?

So far I've been using hacks, such as executing a command with incorrect parameters that utilizes the permission in question, and watching what response I get back.

Example:

# needed resource: 'elasticloadbalancer:SetLoadBalancerListenerSSLCertificate'

# Check:
try:
    elb.set_listener_SSL_certificate(443, 'fake')
except BotoServerError as e:
    if e.error_code == 'AccessDenied':
        print ("You don't have access to "
               "elasticloadbalancer:SetLoadBalancerListenerSSLCertificate")

This is obviously hacky. Ideally I'd have some function call like iam.check_against(resource) or something. Any suggestions?

like image 309
Mikhail Avatar asked Jan 08 '15 00:01

Mikhail


2 Answers

See boto3's simulate_principal_policy.

I've made this function to test for permissions (you'll need to modify it slightly, as it's not completely self-contained):

from typing import Dict, List, Optional

def blocked(
    actions: List[str],
    resources: Optional[List[str]] = None,
    context: Optional[Dict[str, List]] = None
) -> List[str]:
    """test whether IAM user is able to use specified AWS action(s)

    Args:
        actions (list): AWS action(s) to validate IAM user can use.
        resources (list): Check if action(s) can be used on resource(s).
            If None, action(s) must be usable on all resources ("*").
        context (dict): Check if action(s) can be used with context(s).
            If None, it is expected that no context restrictions were set.

    Returns:
        list: Actions denied by IAM due to insufficient permissions.
    """
    if not actions:
        return []
    actions = list(set(actions))

    if resources is None:
        resources = ["*"]

    _context: List[Dict] = [{}]
    if context is not None:
        # Convert context dict to list[dict] expected by ContextEntries.
        _context = [{
            'ContextKeyName': context_key,
            'ContextKeyValues': [str(val) for val in context_values],
            'ContextKeyType': "string"
        } for context_key, context_values in context.items()]

    # You'll need to create an IAM client here
    results = aws.iam_client().simulate_principal_policy(
        PolicySourceArn=consts.IAM_ARN,  # Your IAM user's ARN goes here
        ActionNames=actions,
        ResourceArns=resources,
        ContextEntries=_context
    )['EvaluationResults']

    return sorted([result['EvalActionName'] for result in results
        if result['EvalDecision'] != "allowed"])

You need to pass the permission's original action names to actions, like so:

blocked_actions = verify_perms.blocked(actions=[
    "iam:ListUsers",
    "iam:ListAccessKeys",
    "iam:DeleteAccessKey",
    "iam:ListGroupsForUser",
    "iam:RemoveUserFromGroup",
    "iam:DeleteUser"
])

Here's an example that uses the resources and context arguments as well:

def validate_type_and_size_allowed(instance_type, volume_size):
    """validate user is allowed to create instance with type and size"""
    if validate_perms.blocked(actions=["ec2:RunInstances"],
            resources=["arn:aws:ec2:*:*:instance/*"],
            context={'ec2:InstanceType': [instance_type]}):
        halt.err(f"Instance type {instance_type} not permitted.")
    if validate_perms.blocked(actions=["ec2:RunInstances"],
            resources=["arn:aws:ec2:*:*:volume/*"],
            context={'ec2:VolumeSize': [volume_size]}):
        halt.err(f"Volume size {volume_size}GiB is too large.")
like image 84
TakingItCasual Avatar answered Oct 30 '22 20:10

TakingItCasual


The IAM Policy Simulator provides an excellent UI for determining which users have access to particular API calls.

If you wish to test this programmatically, use the DryRun parameter to make an API call. The function will not actually execute, but you will be informed whether it has sufficient permissions to execute. It will not, however, check whether the call itself would have succeeded (eg having an incorrect certificate name).

like image 39
John Rotenstein Avatar answered Oct 30 '22 19:10

John Rotenstein