I want to implement complex validation but I don't have enough knowledge. This is how I imagine the rule to work in python:
input_data = {
"attributes": {
"request": {
"http": {
"headers": {
"claims": {
"realm_access": {
"roles": [
"[DATAFLOW] Delete Group",
"[CAPEX] Get All Kpis"
]
}
},
"method": "DELETE",
"path": "/pets/dogs"
}
},
},
"parsed_path": [
"api",
"dataflow",
"v100500",
"groups",
"123"
]
}
}
data = {
"endpoints": {
"delete": {
"[DATAFLOW] Delete Group": [
{
"parsed_path": [
"api",
"dataflow",
"v100500",
"groups"
],
"path_length": 5,
"rule": "[DATAFLOW] Delete Group"
}
],
"[DATAFLOW] Delete Source": [
{
"parsed_path": [
"api",
"dataflow",
"v3",
"sources",
"source"
],
"path_length": 6,
"rule": "[DATAFLOW] Delete Source"
}
]
}
}
}
def is_allowed():
input_roles = input_data['attributes']['request']['http']['headers']['claims']['realm_access']['roles']
input_method = input_data['attributes']['request']['http']['headers']['method'].lower()
parsed_path = set(input_data['attributes']['parsed_path'])
parsed_path_len = len(parsed_path)
endpoints_by_rules = data['endpoints'][input_method]
for input_role in input_roles:
if input_role in endpoints_by_rules:
rules = endpoints_by_rules[input_role]
for rule in rules:
rule_parsed_path = set(rule['parsed_path'])
if parsed_path.intersection(rule_parsed_path) == rule_parsed_path \
and parsed_path_len == rule['path_length']:
return True
return False
allow = True if is_allowed() else False
And here is what I was able to write, but this rule does not work correctly
package example
default allow = false
# Rule that checks access permission based on role and pathallow {
is_allowed(input.attributes)
}
# Helper function to check access permission
is_allowed(attributes) {
input_roles := attributes.request.http.headers.claims.realm_access.roles
input_method := lower(attributes.request.http.headers.method)
parsed_path := to_set(attributes.parsed_path)
parsed_path_len := count(parsed_path)
endpoints_by_rules := data.endpoints[input_method]
# Checking that at least one user role has access
some input_role
input_role = input_roles[_]
rules := endpoints_by_rules[input_role]
# Checking that at least one rule for the current role allows access
some rule
rule = rules[_]
rule_parsed_path := to_set(rule.parsed_path)
# Checking that parsed_path contains all elements of rule_parsed_path
rule_parsed_path & parsed_path == rule_parsed_path
# Checking that the parsed_path length is equal to the path_length in the rule
parsed_path_len == rule.path_length
}
# Helper function to convert list to set
to_set(l) = {x | x = l[_]}
Function execution stops at line with parsed_path Is it possible to debug the rules? Tell me what am I doing wrong
Is data.endpoints
referred to in the policy provided during evaluation? If I cook one up, I can get your policy to evaluate to a result on the playground: https://play.openpolicyagent.org/p/WNzXqB2NDT