Skip to content

Getting Started

The pylicy workflow consists of writing policies, declaring rules, and then processing resources.

Writing Policies

Policies are simple callables which take in a resource and rule and evaluate the to form some sort of decision. This is documented further in the Policies page.

The following example policy will check if a given token resource is older than 30 days. If its too old the checker will produce a DENY action, otherwise it will ALLOW it.

import pylicy

@pylicy.policy_checker('token_rotation')
async def token_rotation_policy(resource, rule):
    if resource.data['age'] > 30:
        return pylicy.PolicyDecision(
            action=pylicy.PolicyDecisionAction.DENY,
            reason="too old",
        )
    else:
        return pylicy.PolicyDecision(
            action=pylicy.PolicyDecisionAction.ALLOW,
        )

Declaring rules

Rules are then used to associate resources and policies. Resources are identified by their id and policies by their name. Rules can be structured to overwrite amend prior rules for particular use-cases.

The following example ruleset will apply the token_rotation_policy to all resources except for longlived_* and alices_token.

# rules.yml
version: 1

rules:
  - name: token_rotation_all
    description: Enforce the token rotation policy for all resources
    resources: '*'
    policies: token_rotation
  - name: special_longlived_tokens
    description: Exclude certain tokens from this rule
    resources:
      - longlived_*
      - alices_token
    policies: '!token_rotation'

Fetching resources

Fetching resources is largely left up to the user, pylicy only requires some sort if identifier than can be used to match the resource. Resources fetched should then be converted to pylicy.Resource objects which will then be passed to each policy.

import pylicy

def get_all_token_metadata():
    return [
        {'name': 'my_token',     'token': {'age': 10}},
        {'name': 'my_old_token', 'token': {'age': 60}},
        {'name': 'longlived_a',  'token': {'age': 60}},
        {'name': 'longlived_b',  'token': {'age': 60}},
        {'name': 'alices_token', 'token': {'age': 60}},
    ]

pylicy_resources = [
    pylicy.Resource(id=token['name'], data=token['token'])
    for token in get_all_token_metadata()
]

Applying policies

Now that everything ready all thats left is to load our rules into pylicy and apply then to our resources!

In this case we will load our rules from before, and apply them to our pylicy_resources created above.

import pylicy

policies = pylicy.Pylicy.from_yaml('./rules.yml')
decisions = await policies.apply_all(pylicy_resources)

Decisions will contain all the PolicyDecisions as produced by our policy checker functions grouped by resource then policy.

As you can see below the excluded rules were not run at all, whilst the two that did run had the policy applied successfully.

decisions == {
    'alices_token': {},
    'longlived_a': {},
    'longlived_b': {},
    'my_old_token': {
        'token_rotation': PolicyDecision(
            action=PolicyDecisionAction.DENY, reason='too old', detail=None
        )
    },
    'my_token': {
        'token_rotation': PolicyDecision(
            action=PolicyDecisionAction.ALLOW, reason=None, detail=None
        )
    }
}