Resource Groups are the mechanism for associating policies with sets of resources. They enable resource-level access control by defining which policy governs access to resources within each group.
See also: Resources
Resource Groups serve as the bridge between resources and policies:
Like identity entities (Roles, Groups, Scopes), resource groups serve a dual purpose: they link to a policy for access evaluation, and they can carry annotations that parameterize policy decisions. Resource group annotations flow into input.resource.annotations, providing default metadata for all resources in the group. Individual Resources can override these defaults with their own annotations (see Parameterizing Policies).
When a request involves a resource:
Resource Groups are defined in the spec.resource-groups section of a PolicyDomain:
spec:
resource-groups:
- mrn: "mrn:iam:resource-group:public"
name: public
description: "Publicly accessible resources"
policy: "mrn:iam:policy:allow-all"
- mrn: "mrn:iam:resource-group:internal"
name: internal
description: "Internal resources requiring authentication"
default: true # Default group for unassigned resources
policy: "mrn:iam:policy:authenticated-only"
- mrn: "mrn:iam:resource-group:sensitive"
name: sensitive
description: "Sensitive resources with strict access controls"
policy: "mrn:iam:policy:clearance-required"
| Field | Type | Required | Description |
|---|---|---|---|
mrn | string | Yes | Unique MRN identifier for the group |
name | string | Yes | Human-readable name |
description | string | No | Description of the group's purpose |
default | boolean | No | Use as default for unassigned resources |
policy | string | Yes | MRN of the policy to apply |
annotations | array | No | List of name/value objects for custom metadata |
One Resource Group can be marked as default: true. This group applies to any resource that doesn't explicitly specify a group:
resource-groups:
- mrn: "mrn:iam:resource-group:default"
name: default
description: "Default access policy for all resources"
default: true
policy: "mrn:iam:policy:authenticated-only"
If no default is specified and a resource doesn't have a group, the request will be denied (fail-closed behavior).
Annotations on Resource Groups provide metadata that:
resource-groups:
- mrn: "mrn:iam:resource-group:pii-data"
name: pii-data
description: "Personally identifiable information"
policy: "mrn:iam:policy:pii-access"
annotations:
- name: "compliance"
value: "\"GDPR\""
- name: "audit_required"
value: "true"
- name: "retention_days"
value: "365"
Use annotations in policies:
package authz
default allow = false
# Require audit for resources in groups marked audit_required
allow {
input.resource.annotations.audit_required == "true"
input.principal.mroles[_] == "mrn:iam:role:auditor"
}
Resources are assigned to groups in two ways:
The calling application specifies the group in the PORC expression:
{
"principal": { ... },
"operation": "data:read",
"resource": {
"id": "mrn:data:document:12345",
"group": "mrn:iam:resource-group:sensitive"
},
"context": { ... }
}
Define patterns in the resources section to automatically route resources to groups based on their MRN:
spec:
resources:
- name: sensitive-data
description: "Route sensitive data to restricted group"
selector:
- "mrn:data:sensitive:.*"
- "mrn:secret:.*"
group: "mrn:iam:resource-group:sensitive"
- name: public-assets
description: "Route public assets to public group"
selector:
- "mrn:assets:public:.*"
group: "mrn:iam:resource-group:public"
When a resource MRN matches a selector pattern, it's automatically assigned to the corresponding group. See Resources for more details on resource routing.
A common pattern is tiered resource groups based on sensitivity:
spec:
# Define policies for each tier
policies:
- mrn: "mrn:iam:policy:public-access"
name: public-access
rego: |
package authz
default allow = true # Anyone can access
- mrn: "mrn:iam:policy:authenticated-access"
name: authenticated-access
rego: |
package authz
default allow = false
allow { input.principal.sub != "" }
- mrn: "mrn:iam:policy:clearance-access"
name: clearance-access
rego: |
package authz
default allow = false
ratings := {"LOW": 1, "MODERATE": 2, "HIGH": 3, "MAXIMUM": 4}
allow {
ratings[input.principal.mclearance] >= ratings[input.resource.classification]
}
# Define resource groups using those policies
resource-groups:
- mrn: "mrn:iam:resource-group:public"
name: public
description: "Public resources - no auth required"
policy: "mrn:iam:policy:public-access"
- mrn: "mrn:iam:resource-group:internal"
name: internal
description: "Internal resources - auth required"
default: true
policy: "mrn:iam:policy:authenticated-access"
- mrn: "mrn:iam:resource-group:classified"
name: classified
description: "Classified resources - clearance required"
policy: "mrn:iam:policy:clearance-access"
It's important to distinguish between Resource Groups and identity Groups:
| Aspect | Resource Groups | Groups (Identity) |
|---|---|---|
| Contains | Resource patterns | Roles |
| Assigned to | Resources | Principals |
| Phase | Phase 3 (Resource) | Phase 2 (Identity) |
| Purpose | What policies apply to resources | What roles apply to an identity |
| PORC field | resource.group | principal.mgroups |
Always define a default group: Ensures fail-closed behavior for resources without explicit group assignment
Use meaningful names: Group names should clearly indicate the access policy (e.g., "public", "internal", "sensitive")
Keep policies focused: Each resource group policy should handle one access pattern
Leverage annotations: Use group-level annotations for shared metadata across resources
Document groups: Use the description field to explain when resources belong in each group
Use resource routing: For large systems, use MRN patterns to automatically assign resources to groups rather than relying on callers to specify groups
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 |