Skip to main content

PolicyDomains

A PolicyDomain is a self-contained bundle that defines all policy-related artifacts for a specific domain or service.

PolicyDomain Model

Overview​

PolicyDomains provide:

  • Modularity: Package related policies together
  • Portability: Deploy policies as a single unit
  • Reusability: Share libraries across policies within a domain
  • Versioning: Track changes to policy bundles

PolicyDomain Structure​

apiVersion: iamlite.manetu.io/v1beta1
kind: PolicyDomain
metadata:
name: my-domain
spec:
policy-libraries: [] # Reusable Rego code
policies: [] # Access control policies
roles: [] # Role-to-policy mappings
groups: [] # Group-to-role mappings
resource-groups: [] # Resource-to-policy mappings
resources: [] # Resource selector routing
scopes: [] # Access-method constraint policies
operations: [] # Operation routing
mappers: [] # Input transformation

API Version and Kind​

Every PolicyDomain document must specify an API version and kind:

apiVersion: iamlite.manetu.io/v1beta1
kind: PolicyDomain # or PolicyDomainReference

Supported API versions: v1alpha3, v1alpha4, v1beta1

Use v1beta1 for New Projects

v1beta1 supports native YAML annotation values, eliminating the need for JSON-encoded strings. This makes PolicyDomains easier to read and write.

Supported kinds:

KindDescription
PolicyDomainDeployment format with inline Rego code
PolicyDomainReferenceDevelopment format that can reference external .rego files

See PolicyDomain vs PolicyDomainReference for detailed guidance on when to use each format.

Metadata​

metadata:
name: my-service-policies

The name uniquely identifies the domain. It's used for:

  • Cross-domain references
  • Logging and debugging
  • Bundle identification

Components Overview​

Policy Libraries​

Reusable Rego code shared across policies:

spec:
policy-libraries:
- mrn: "mrn:iam:library:helpers"
name: helpers
rego: |
package helpers
# Shared functions...

Policies​

The Rego code that makes access decisions:

spec:
policies:
- mrn: "mrn:iam:policy:main"
name: main
dependencies:
- "mrn:iam:library:helpers"
rego: |
package authz
# Policy logic...

Roles, Groups, Resource Groups, Resources, Scopes​

Identity and resource mappings:

spec:
roles:
- mrn: "mrn:iam:role:admin"
name: admin
policy: "mrn:iam:policy:allow-all"

groups:
- mrn: "mrn:iam:group:admins"
name: admins
roles:
- "mrn:iam:role:admin"

resource-groups:
- mrn: "mrn:iam:resource-group:default"
name: default
default: true
policy: "mrn:iam:policy:allow-all"

# v1alpha4+: Route resources to groups by MRN pattern
resources:
- name: sensitive-data
selector:
- "mrn:data:sensitive:.*"
group: "mrn:iam:resource-group:restricted"

scopes:
- mrn: "mrn:iam:scope:api"
name: api
policy: "mrn:iam:policy:allow-all"

Operations and Mappers​

Request routing and transformation:

spec:
operations:
- name: api
selector: [".*"]
policy: "mrn:iam:policy:main"

mappers:
- name: http-mapper
selector: [".*"]
rego: |
package mapper
# Transform input to PORC...

Using YAML Anchors​

YAML anchors increase PolicyDomain maintainability:

spec:
policies:
- mrn: &allow-all "mrn:iam:policy:allow-all"
name: allow-all
rego: |
package authz
default allow = true

roles:
- mrn: "mrn:iam:role:admin"
name: admin
policy: *allow-all # Reference the anchor

PolicyDomain vs PolicyDomainReference​

The PolicyEngine supports two document formats that serve different purposes in the development and deployment workflow.

Key Differences​

AspectPolicyDomainPolicyDomainReference
Rego codeInline rego field onlyEither rego (inline) or rego_filename (external file)
Primary useDeployment, runtime evaluationDevelopment, source control
Kubernetes OperatorSupported (Premium)Must convert with mpe build first
Community toolingFully supportedFully supported

PolicyDomainReference Format​

PolicyDomainReference is a superset of PolicyDomain that allows referencing external .rego files instead of embedding Rego code inline. This is the recommended format for development because:

  • IDE support: Separate .rego files get proper syntax highlighting
  • Easier testing: Test individual Rego files with standard OPA tooling
  • Cleaner diffs: Policy logic changes are isolated from YAML structure
  • Better organization: Keep complex policies in dedicated files
apiVersion: iamlite.manetu.io/v1beta1
kind: PolicyDomainReference
metadata:
name: my-domain
spec:
policy-libraries:
- mrn: "mrn:iam:library:helpers"
name: helpers
rego_filename: lib/helpers.rego # External file

policies:
- mrn: "mrn:iam:policy:main"
name: main
dependencies:
- "mrn:iam:library:helpers"
rego_filename: policies/main.rego # External file

- mrn: "mrn:iam:policy:simple"
name: simple
rego: | # Inline is also allowed
package authz
default allow = true

The rego_filename field is supported on:

  • policies
  • policy-libraries
  • mappers

Converting to PolicyDomain​

Use mpe build to convert PolicyDomainReference to PolicyDomain:

# Convert for deployment
mpe build -f my-domain-ref.yaml -o my-domain.yaml

The build process:

  1. Reads each rego_filename reference
  2. Loads the external .rego file content
  3. Replaces rego_filename with inline rego
  4. Changes kind from PolicyDomainReference to PolicyDomain

Which Format Should I Use?​

Community Users: All tooling (mpe test, mpe serve, Go API) accepts both formats interchangeably. Choose based on your preference:

  • Use PolicyDomainReference if you prefer separate .rego files
  • Use PolicyDomain if you prefer everything in one file

Premium Users: The Kubernetes Operator only accepts PolicyDomain format. You can:

  • Develop using PolicyDomainReference for better IDE support
  • Run mpe build as part of your CI/CD pipeline before deployment
  • Or develop directly in PolicyDomain format if you prefer

Development Workflow Example​

my-policies/
├── domain.yaml # PolicyDomainReference
├── lib/
│ └── helpers.rego # Shared library code
├── policies/
│ ├── identity.rego # Identity phase policy
│ └── resource.rego # Resource phase policy
└── build/
└── domain-built.yaml # Generated PolicyDomain (git-ignored)

Build command in CI/CD:

mpe build -f domain.yaml -o build/domain-built.yaml

Multiple Domains​

You can load multiple PolicyDomains together:

mpe test decision \
-b base-policies.yml \
-b service-policies.yml \
-i input.json

Cross-domain library references use the format:

dependencies:
- "other-domain/library-name"

GitOps-Friendly Design​

PolicyDomains are fundamentally GitOps-friendly because they are plain files—YAML documents that can be version-controlled, reviewed, tested, and deployed through any standard GitOps workflow.

Why Plain Files Matter​

  • Human-readable: Easy to review in pull requests
  • Diff-friendly: Changes are clearly visible in version control
  • Declarative: Describes the desired state, not imperative steps
  • Tooling support: Standard YAML linting, formatting, and validation
  • Portable: Deploy through any file-based workflow

Deployment Patterns​

Because PolicyDomains are just files, they integrate with any GitOps-oriented deployment flow:

GitOps

PatternDescription
Push-basedGit → CI pipeline → kubectl apply to Kubernetes
Pull-basedGitOps operators (Flux, ArgoCD) continuously sync from Git

Delivery by Edition​

ConfigMap-based delivery

Community

In the Community Edition, PolicyDomains are typically delivered as Kubernetes ConfigMaps. Configure your PDP pods (for HTTP API integration) or application pods (for embedded Go) to trigger a rolling restart when the ConfigMap changes:

apiVersion: v1
kind: ConfigMap
metadata:
name: policy-domain
data:
domain.yaml: |
apiVersion: iamlite.manetu.io/v1beta1
kind: PolicyDomain
metadata:
name: my-service
spec:
# ... PolicyDomain content
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mpe-pdp
spec:
template:
metadata:
annotations:
# Trigger rollout when ConfigMap changes
checksum/config: "{{ sha256sum .Values.policyDomain }}"

CRD-based delivery with dynamic updates

Premium

The Premium Edition provides a Kubernetes Custom Resource Definition (CRD) for PolicyDomain resources. When a PolicyDomain CRD instance is created or updated—whether through CI push or a GitOps operator pull—the Policy Administration Point (PAP) automatically distributes the new policies to all PDPs through the cache-coherency mechanism. No pod restarts required.

apiVersion: iamlite.manetu.io/v1beta1
kind: PolicyDomain
metadata:
name: my-service
spec:
# ... PolicyDomain content

Example CI Pipeline​

# .github/workflows/policy-ci.yml
name: Policy CI

on:
push:
paths:
- 'policies/**'
pull_request:
paths:
- 'policies/**'

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install MPE
run: |
curl -L https://github.com/manetu/policyengine/releases/latest/download/mpe-linux-amd64 -o mpe
chmod +x mpe
sudo mv mpe /usr/local/bin/

- name: Lint policies
run: mpe lint -f policies/domain.yaml

- name: Run policy tests
run: |
for test in policies/tests/*.json; do
echo "Running test: $test"
mpe test decision -b policies/domain.yaml -i "$test" | \
jq 'if .decision == "DENY" then "Test failed: access denied" | halt_error(1) else . end'
done

- name: Build for deployment
run: mpe build -f policies/domain.yaml -o dist/domain.yaml

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: policy-bundle
path: dist/domain.yaml

Pull Request Reviews​

Because PolicyDomains are YAML, policy changes follow standard code review practices:

  1. Author creates a branch with policy changes
  2. CI automatically validates syntax and runs tests
  3. Reviewers examine the diff—changes are clear and auditable
  4. Merge triggers deployment to staging/production

This approach provides:

  • Audit trail: Git history shows who changed what and when
  • Rollback: Revert to any previous policy version instantly
  • Collaboration: Multiple team members can work on policies
  • Testing: Automated validation before deployment

Best Practices​

  1. One domain per service: Keep domains focused
  2. Use libraries: Extract common code into libraries
  3. Use anchors: Avoid duplicating MRNs
  4. Use references: Keep Rego in external files for better editing
  5. Validate early: Run mpe lint frequently during development
  6. Version control: Store PolicyDomains in Git with your application code or in a dedicated policy repository
  7. Automate testing: Include policy tests in your CI/CD pipeline
  • Policies: Authorization policies defined in domains
  • Policy Libraries: Reusable Rego code shared across policies
  • Operations: Route requests to operation phase policies
  • Roles: Connect principals to identity phase policies
  • Groups: Bundle roles for easier assignment
  • Resource Groups: Connect resources to resource phase policies
  • Scopes: Define access-method constraints
  • Resources: Define resource routing patterns
  • Mappers: Transform non-PORC inputs

See also: Examples for complete, production ready PolicyDomains for a deeper understanding.