Policy Libraries contain reusable Rego code that can be shared across multiple policies within a PolicyDomain.
Libraries help you:
spec:
policy-libraries:
- mrn: "mrn:iam:library:helpers"
name: helpers
description: "Common helper functions"
rego: |
package helpers
# Glob pattern matching
match_any(patterns, value) {
glob.match(patterns[_], [], value)
}
# Check if principal has a specific role
has_role(role) {
input.principal.mroles[_] == role
}
# Check if principal is in a group
in_group(group) {
input.principal.mgroups[_] == group
}
:::warning[Package Name Requirements] Policy Libraries have specific package naming requirements:
Must NOT use package authz — The authz package is reserved for authorization policies (those defined in the policies section that make access decisions). Libraries use their own unique package names (e.g., package helpers, package utils).
Must be unique across all dependencies — When an authorization policy imports multiple libraries, each library must have a distinct package name. If two libraries both declare package utils, a collision will occur.
Best practice: Use descriptive, organization-specific package names to avoid collisions (e.g., package myorg.helpers or package acme.validation). This ensures libraries can be safely combined in any policy.
:::
Declare the library as a dependency and import it:
spec:
policies:
- mrn: "mrn:iam:policy:my-policy"
name: my-policy
dependencies:
- "mrn:iam:library:helpers"
rego: |
package authz
import data.helpers
default allow = false
allow {
helpers.has_role("mrn:iam:role:admin")
}
Libraries can depend on other libraries:
spec:
policy-libraries:
- mrn: &utils "mrn:iam:library:utils"
name: utils
rego: |
package utils
ro_operations := {"*:read", "*:list", "*:get"}
- mrn: "mrn:iam:library:access"
name: access
dependencies:
- *utils
rego: |
package access
import data.utils
is_readonly {
glob.match(utils.ro_operations[_], [], input.operation)
}
A recommended pattern is to create a utils library with common helpers that are used across multiple policies. This eliminates duplication and ensures consistency:
spec:
policy-libraries:
- mrn: &lib-utils "mrn:iam:library:utils"
name: utils
description: "Common utility functions"
rego: |
package utils
import rego.v1
# Check if request has a valid principal (authenticated)
has_principal if {
input.principal != {}
input.principal.sub != ""
}
# Domain-specific library can coexist with utils
- mrn: &lib-domain-helpers "mrn:iam:library:domain-helpers"
name: domain-helpers
description: "Domain-specific helper functions"
rego: |
package domain_helpers
# ... domain-specific helpers
Policies can then use the utils library:
policies:
- mrn: "mrn:iam:policy:require-auth"
name: require-auth
dependencies:
- *lib-utils
rego: |
package authz
import rego.v1
import data.utils
# Tri-level: negative=DENY, 0=GRANT, positive=GRANT Override
# Default deny - only grant if authenticated
default allow = -1
# Grant authenticated requests
allow = 0 if utils.has_principal
This pattern:
has_principal once, use everywherePolicies can depend on multiple libraries simultaneously. This is useful when combining general utilities with domain-specific helpers:
policies:
- mrn: "mrn:iam:policy:mcp-operation"
dependencies:
- *lib-utils # Common utilities
- *lib-mcp-helpers # MCP-specific helpers
rego: |
package authz
import rego.v1
import data.utils
import data.mcp_helpers
default allow = -1
allow = 1 if mcp_helpers.is_health_check
allow = 0 if utils.has_principal
package operations
# Read-only operations
ro_operations := {
"*:read",
"*:list",
"*:get",
"*:head"
}
# Write operations
write_operations := {
"*:create",
"*:update",
"*:write",
"*:delete"
}
is_read_only {
glob.match(ro_operations[_], [], input.operation)
}
is_write {
glob.match(write_operations[_], [], input.operation)
}
package roles
admin_roles := {
"mrn:iam:role:admin",
"mrn:iam:role:superadmin"
}
is_admin {
input.principal.mroles[_] in admin_roles
}
has_any_role(required_roles) {
some role in input.principal.mroles
role in required_roles
}
package resources
is_owner {
input.principal.sub == input.resource.owner
}
clearance_levels := {
"LOW": 1,
"MODERATE": 2,
"HIGH": 3,
"MAXIMUM": 4,
"UNASSIGNED": 5
}
has_clearance {
clearance_levels[input.principal.mclearance] >= clearance_levels[input.resource.classification]
}
package validation
# Check if principal is authenticated
is_authenticated {
input.principal != {}
input.principal.sub != ""
}
# Check if principal has a valid JWT
has_valid_jwt {
input.principal.exp > time.now_ns() / 1000000000
}
Reference libraries from other PolicyDomains:
spec:
policies:
- mrn: "mrn:iam:policy:my-policy"
name: my-policy
dependencies:
- "other-domain/common-utils" # Cross-domain reference
rego: |
package authz
import data.common_utils
# Note: package name uses underscores
default allow = false
allow {
common_utils.is_valid(input)
}
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |