Writing

command.write_policy

writing.policy

ArnActionGroup

class policy_sentry.writing.policy.ArnActionGroup

This class is critical to the creation of least privilege policies. It uses the SIDs as namespaces. The namespaces follow this format:

{Servicename}{Accesslevel}{Resourcetypename}

So, a resulting statement’s SID might look like ‘S3ListBucket’

add(db_session, arn_list_from_user, access_level)

This just adds the ARN, Service, and Access Level. ARN Format and Actions are not filled out. Example data can be found in the class ArnActionGroupTestCase in the testing folder.

Parameters:
  • db_session – SQLAlchemy database session
  • arn_list_from_user – Just a list of resource ARNs.
  • access_level – “Read”, “List”, “Tagging”, “Write”, or “Permissions management”
add_complete_entry(arn_from_user, service, access_level, raw_arn_format, actions_list)

Add a single entry with all the necessary fields filled out.

Parameters:
  • arn_from_user – The literal ARN that the user wants to put in the policy
  • service – A service prefix, like s3
  • access_level – Access level for the IAM action
  • raw_arn_format – The raw arn that matches format of the arn_from_user
  • actions_list – A list of actions
combine_policy_elements()

Consolidate the policy elements by looking at where ARNs are used

does_action_exist(action)

Get boolean response for whether or not an action exists under any of the ARNs.

Parameters:action – full action name, like s3:GetObject
Returns:True or False
Return type:bool
get_arns()

Getter function for the ARNs object

Returns:ARNs object
Return type:dict
get_policy_elements(db_session)

Return the policy elements to the user.

Parameters:db_session – database session.
Returns:A dictionary that contains the SID namespace, a list of actions, and a list of resource ARNs that fall under this namespace
Return type:dict
process_list_of_actions(supplied_actions, db_session)

Takes a list of actions, queries the database for corresponding arns, adds them to the object.

Parameters:
  • supplied_actions – A list of supplied actions
  • db_session – SQLAlchemy database session object
Returns:

arn_dict: This is the compiled and updated dictionary after all necessary processing. This plugs into create_policy

Return type:

dict

process_resource_specific_acls(cfg, db_session)

Processes the YAML file for the resources per access level, and adds it to the object.

Parameters:
  • cfg – A dictionary loaded from the YAML file
  • db_session – Database session
Returns:

the fully formed dict containing the ARNs and actions

Return type:

dict

remove_actions_duplicated_in_wildcard_resources()

Removes actions from the object that are in a resource-specific ARN, as well as the * resource. For example, if ssm:GetParameter is restricted to a specific parameter path, as well as *, then we want to remove the * option to force least privilege.

remove_actions_not_matching_list(actions_list)
Parameters:actions_list – List of actions to leave. All actions not in this list are removed
remove_sids_with_empty_action_lists()
Now that we’ve removed a bunch of actions, if there are SID groups without any actions,
remove them so we don’t get SIDs with empty action lists
update_actions_for_raw_arn_format(db_session)

Considers the attribute values under each value in self.arns, and fills in the actions lists accordingly.

Parameters:db_session – SQLAlchemy database session
policy_sentry.writing.policy.create_policy_sid_namespace(service, access_level, resource_type_name)

Simply generates the SID name. The SID groups ARN types that share an access level.

For example, S3 objects vs. SSM Parameter have different ARN types - as do S3 objects vs S3 buckets. That’s how we choose to group them.

Parameters:
  • service – “ssm”
  • access_level – “Read”
  • resource_type_name – “parameter”
Returns:

SsmReadParameter

Return type:

str

policy_sentry.writing.policy.remove_actions_that_are_not_wildcard_arn_only(db_session, actions_list)

Given a list of actions, remove the ones that CAN be restricted to ARNs, leaving only the ones that cannot.

Parameters:
  • db_session – SQL Alchemy database session object
  • actions_list – A list of actions
Returns:

An updated list of actions

Return type:

list

writing.roles

Roles is a data holder for sublists. It supports the write-policy actions mode. In the future, this data structure should probably go away, or it should at least be renamed.

class policy_sentry.writing.roles.Roles

This is just a data holder for list of lists - used for running the YAML option. The sublists should all contain these: Indexes: 0 - Name 1 - Description 2 - ARN (string ARN of the role) 3 - Actions (list of AWS API Actions)

add_role(role)

Chain write-policy action mode files together

get_roles()

Get the full data structure of action_list holder.

process_actions_config(cfg)

Given the YAML file used for the list of actions config, process it.

writing.template

Templates for the policy_sentry YML files. These can be used for generating policies

policy_sentry.writing.template.create_actions_template(name)

Generate the Actions YML template with Jinja2

policy_sentry.writing.template.create_crud_template(name)

Generate the CRUD YML Template with Jinja2

policy_sentry.writing.template.get_actions_template_dict()

Get the Actions template in dict format.

policy_sentry.writing.template.get_crud_template_dict()

Generate the CRUD template in dict format

writing.validate

Validation for the Policy Sentry YML Templates.

policy_sentry.writing.validate.check(conf_schema, conf)

Validates a user-supplied JSON vs a defined schema. :param conf_schema: The Schema object that defines the required structure. :param conf: The user-supplied schema to validate against the required structure.

policy_sentry.writing.validate.check_actions_schema(cfg)

Determines whether the user-provided config matches the required schema for Actions mode

policy_sentry.writing.validate.check_crud_schema(cfg)

Determines whether the user-provided config matches the required schema for CRUD mode

writing.minimize

Functions for Minimizing statements, heavily borrowed from policyuniverse. https://github.com/Netflix-Skunkworks/policyuniverse/

IAM Policies have character limits, which apply to individual policies, and there are also limits on the total aggregate policy sizes. As such, it is not possible to use exhaustive list of explicit IAM actions. To have granular control of specific IAM policies, we must use wildcards on IAM Actions, only in a programmatic manner.

This is typically performed by humans by reducing policies to s3:Get*, ec2:Describe*, and other approaches of the sort.

Netflix’s PolicyUniverse has address

https://aws.amazon.com/iam/faqs/ Q: How many policies can I attach to an IAM role? * For inline policies: You can add as many inline policies as you want to a user, role, or group, but

the total aggregate policy size (the sum size of all inline policies) per entity cannot exceed the following limits: - User policy size cannot exceed 2,048 characters. - Role policy size cannot exceed 10,240 characters. - Group policy size cannot exceed 5,120 characters.
  • For managed policies: You can add up to 10 managed policies to a user, role, or group.
  • The size of each managed policy cannot exceed 6,144 characters.
policy_sentry.writing.minimize.check_min_permission_length(permission, minchars=None)

Adapted version of policyuniverse’s _check_permission_length. We are commenting out the skipping prefix message https://github.com/Netflix-Skunkworks/policyuniverse/blob/master/policyuniverse/expander_minimizer.py#L111

policy_sentry.writing.minimize.get_denied_prefixes_from_desired(desired_actions, all_actions)

Adapted version of policyuniverse’s _get_denied_prefixes_from_desired, here: https://github.com/Netflix-Skunkworks/policyuniverse/blob/master/policyuniverse/expander_minimizer.py#L101

policy_sentry.writing.minimize.minimize_statement_actions(desired_actions, all_actions, minchars=None)

This is a condensed version of policyuniverse’s minimize_statement_actions, changed for our purposes. https://github.com/Netflix-Skunkworks/policyuniverse/blob/master/policyuniverse/expander_minimizer.py#L123