Rules
Rules are pylicy's way of associating resources to policies. They support wildcard matching and exclusion, and implement a weight system to allow for overrides and specificity. pylicy supports definition of these rules either in configuration (yaml or json) or in code.
Rule Types
User Rules
User rules implement a interface with sensible defaults to allow users to easily write rules. YAML and JSON rule defintions only
support user rules and pylicy exports the pylicy.UserRule model to allow for user rules to be defined in code.
Schema
name: A short string identifying the rule. (required)description: A longer description and summary of the rule. (optional: defaults toname)weight: A weight for the rule. Rules with higher weights are prioritized. (optional: defaults to 100)resources: A wildcard pattern or list of such patterns used to match resource names. (required)policies: A wildcard pattern or list of such patterns used to match policy names. (required)context: Any additional context to pass to policy checkers. This is useful for resource-specific configurations (optional)
Example
version: 1
rules:
- name: my_barebones_rule
resources: '*'
policies: '*'
- name: my_cool_rule
description: My cool rule!
weight: 200
resources: 'wildcard_*_pattern'
policies:
- 'a_list_of_*'
- 'policy_names_?'
- '!not_this'
context:
cool: true
{
"version": 1,
"rules": [
{
"name": "my_barebones_rule",
"resources": "*",
"policies": "*"
},
{
"name": "my_cool_rule",
"description": "My cool rule!",
"weight": 200,
"resources": "wildcard_*_pattern",
"policies": [
"a_list_of_*",
"policy_names_?",
"!not_this"
],
"context": {
"cool": true
}
}
]
}
[
pylicy.UserRule(
name="my_barebones_rule",
resources="*",
policies="*"
),
pylicy.UserRule(
name="my_cool_rule",
description="My cool rule!",
weight=200,
resources="wildcard_*_pattern",
policies=[
"a_list_of_*",
"policy_names_?",
"!not_this"
],
context={
"cool": true
}
)
]
"Concrete" Rules
Concrete Rules (or just Rule) are pylicy's internal representation of a rule and are what is passed to your policy checkers.
pylicy will happily accept these from code. They largely follow the same schema as user rules but disallow any optional types or fields.
Schema
name: Same as user rule. (required)description: Same as user rule. (required)weight: Same as user rule. (required)resource_patterns: A list of wildcard patterns used to match resource names. (required)policy_patterns: A list of wildcard patterns used to match policy names. (required)context: Same as user rule.
Example
pylicy.Rule(
name='my_concrete_rule',
description='Nothing is optional',
weight=100,
resource_patterns=['*'],
policy_petterns=['*'],
context=None,
)
Rule Semantics
Patterns
pylicy internally uses python's fnmatch module with some extension
to perform matching and hence supports all patterns used by that module. In addition to fnmatch's patterns pylicy
also supports a leading ! for negation.
Example
[ij] is a good variable namematches bothi is a good variable nameandj is a good variable namehello *matcheshello worldbut notworld hello?phonematchesiphoneandjphonebut notapple phone!*scriptmatchespythonbut notjavascriptortypescript
When a list of patterns is specified they are resolved first to last (from low indexes to high indexes). pylicy will reduce the matches for every pattern and only apply a new pattern to the this list of reduced matches .This has implications on what is matched by a list of patterns containing negations.
Example
Assuming we have the set [iphone, ipad, iwatch, apple watch].
i*, !*watch, apple watchwill matchiphone, ipad, apple watchi*, apple watch, !*watchwill match onlyiphone, ipad
Conflicts
Rules are designed to permit conflicts (e.g. one rule may match my_policy whilst another may match !my_policy).
This is perfectly legal and even desirable to introduce special cases for certain resources. pylicy will perform the
following actions to decide what rules to match.
- Rules of higher weight are preferred over lower weights.
- Policies excluded by a rule of higher weight will override policies included by rules of lower weight.
- Rules defined later in order (of a higher index) will be preferred over rules of lower index within the same weight class.
- Contexts will be populated by only the first matching rule.
Example
For the rules
version: 1
rules:
- name: enforce_all
description: Enforce all policies for all resources
weight: 1
resources: '*'
policies: '*'
- name: allow_admin_wildcards
description: Allow admins to have wildcards
resources: admin_*
policies:
- '!token_no_wildcard'
- name: frank_extend_time
description: Frank can have longer times betwen token rotation
resources: frank_*
policies:
- token_age
context:
max_rotation_time: 365
- For the resource
dummy_tokenonly theenforce_allrule would apply. - For the resource
frank_tokenthetoken_agepolicy and context would come fromfrank_extend_timeand all other policies fromenforce_all. - For the resource
admin_tokenthetoken_no_wildcardpolicy would not apply, all other policies would come fromenforce_all.