Policy & Roles (oslo.policy)
Default roles and policy rules, and how to override them
Abacá uses oslo.policy to govern every action exposed by the abaca-api service. Each API operation maps to a named policy rule; the conductor enforces those rules server-side using the Keystone token presented by the caller. This page describes the built-in roles Abacá defines, the default rules for every protected operation, and how you override them by supplying a policy.yaml file — following the same pattern used across OpenStack services.
Before reading or modifying Abacá policy:
- Abacá control plane deployed —
abaca-apiandabaca-conductorrunning as pods in theabacaOpenShift namespace on RHOSO 18+. - Keystone ≥ 2023.1 with domain-scoped tokens and trusts enabled — Abacá policy evaluation depends on domain-scoped context for Domain-owner rules.
- oslo.policy ≥ 3.x — installed automatically as a dependency of
abaca; no separate installation is needed. - Operator access to the
abaca-apipod — you needoc exec(or equivalent) to runabaca-manageand to place apolicy.yamlfile where the API process can read it. - Familiarity with OpenStack RBAC concepts — roles, role assignments, scope (project vs. domain vs. system), and how oslo.policy parses rule expressions.
Policy configuration requires no separate package installation. The default policy ships as code inside the abaca package (the same package that provides abaca-api and abaca-manage). The steps below cover generating the default policy file for reference and placing an override file into the running service.
Step 1 — Generate the default policy for reference
Run abaca-manage inside the abaca-api pod to export the compiled default rules as a commented YAML file:
oc exec -n abaca deployment/abaca-api -- \
abaca-manage policy generate-default-policy \
--output-file /tmp/abaca-policy-defaults.yaml
# Copy the file to your workstation
oc cp abaca/$(oc get pod -n abaca -l app=abaca-api -o name | head -1 | cut -d/ -f2):/tmp/abaca-policy-defaults.yaml ./abaca-policy-defaults.yaml
This file is read-only reference material. Do not deploy it unchanged — the service's compiled defaults are already active without any file on disk.
Step 2 — Create your override policy.yaml
Create a file containing only the rules you want to override (not the full set):
# policy.yaml — Abacá policy overrides
# Place only the rules you wish to change.
# Example: restrict on-demand backup creation to users with the
# 'abaca_power_user' role in addition to the default rules.
"backup:create": "role:abaca_power_user or rule:admin_or_owner"
Step 3 — Mount the override file into the API pod
Use a Kubernetes ConfigMap and a volume mount in the abaca-api Deployment manifest (managed via kustomize):
# Create the ConfigMap from your override file
oc create configmap abaca-policy \
--from-file=policy.yaml=./policy.yaml \
-n abaca
Then add the following to your kustomize overlay for the abaca-api Deployment:
# kustomization patch excerpt
patches:
- target:
kind: Deployment
name: abaca-api
patch: |-
- op: add
path: /spec/template/spec/volumes/-
value:
name: abaca-policy
configMap:
name: abaca-policy
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: abaca-policy
mountPath: /etc/abaca/policy.yaml
subPath: policy.yaml
Apply the overlay:
kustomize build deploy/rhoso/overlays/production | oc apply -f -
Step 4 — Point abaca.conf at the policy file
Ensure the [oslo_policy] section of /etc/abaca/abaca.conf references the file (oslo.policy will hot-reload it on change without a pod restart if policy_file is set):
[oslo_policy]
policy_file = /etc/abaca/policy.yaml
policy_dirs =
enforce_scope = true
enforce_new_defaults = true
Step 5 — Verify the policy is loaded
Check the API pod logs for the oslo.policy load event:
oc logs -n abaca deployment/abaca-api | grep -i policy
Expected output includes a line such as:
INFO oslo_policy.policy [-] Loaded policy file: /etc/abaca/policy.yaml
Abacá does not expose dedicated [policy] config keys of its own beyond the standard [oslo_policy] block inherited from the oslo.policy library. The settings below are the ones operators most commonly need to tune.
[oslo_policy] section
| Key | Type | Default | Purpose |
|---|---|---|---|
policy_file | string | policy.yaml | Path (absolute or relative to config_dir) of the operator override file. If the file does not exist the compiled defaults apply. |
policy_dirs | list | policy.d | Additional directories scanned for *.yaml policy fragments, merged in lexicographic order. Set to empty to disable. |
enforce_scope | boolean | false (upstream default) | When true, oslo.policy rejects requests whose token scope does not match the rule's declared scope type (project / domain / system). Strongly recommended true for production. |
enforce_new_defaults | boolean | false (upstream default) | When true, the service uses the new-style defaults (personas) rather than legacy is_admin defaults. Enable alongside enforce_scope. |
Abacá [api] options relevant to policy
| Key | Type | Default | Purpose |
|---|---|---|---|
noauth | boolean | false | Disables Keystone authentication and all policy enforcement entirely. Development/local only (docker-compose dev stack). Never set true in production. |
[DEFAULT] options relevant to service identity
| Key | Type | Default | Purpose |
|---|---|---|---|
catalog_type | string | share-protection | The Keystone service type string registered in the catalog. Affects how python-abacaclient discovers the endpoint. |
endpoint_type | string | publicURL | Which catalog endpoint the client library prefers (publicURL, internalURL, or adminURL). |
[abaca] service-user options
| Key | Type | Default | Purpose |
|---|---|---|---|
service_user_id | string | — | UUID of the Keystone user Abacá uses for service-to-service calls (Nova, Neutron, Manila, Barbican). Must hold admin or a suitable custom role in the relevant projects. |
service_user_name | string | — | Human-readable name of that user, used in log attribution. |
Roles Abacá defines
Abacá registers two custom Keystone roles during deployment (via deploy/rhoso/ install scripts):
| Role | Scope | Who holds it | What it unlocks |
|---|---|---|---|
abaca_domain_owner | Domain-scoped | A designated Domain administrator | Create and manage BackupTargetTemplate objects and register S3 buckets (enroll targets) on behalf of all projects in the Domain. |
abaca_admin | System-scoped or project-scoped (operator) | OpenStack operator / service team | Read fleet state, list all jobs and workers across projects, access admin-panel API routes (/v1/admin/...). |
Tenants with the standard OpenStack member role in a project can create Policies, request on-demand backups, monitor their own jobs, and initiate restores within that project — no additional role assignment is required.
Default policy rules
Abacá's policy rules follow the standard OpenStack persona pattern. The table below shows each protected operation family, its default rule expression, and its scope.
| Operation family | Policy rule name | Default expression | Required scope |
|---|---|---|---|
| List/show backup targets | target:get, target:list | rule:project_member_or_admin | Project |
| Create / update / delete target template | target_template:create, target_template:update, target_template:delete | role:abaca_domain_owner | Domain |
| Enroll a bucket (target registration) | target:create | role:abaca_domain_owner | Domain |
| Create / update / delete a protection policy | policy:create, policy:update, policy:delete | rule:project_member_or_admin | Project |
| Request an on-demand backup | backup:create | rule:project_member_or_admin | Project |
| List / show backups | backup:get, backup:list | rule:project_member_or_admin | Project |
| Delete a backup | backup:delete | rule:project_member_or_admin | Project |
| Request a restore | restore:create | rule:project_member_or_admin | Project |
| List / show restores | restore:get, restore:list | rule:project_member_or_admin | Project |
| List / show jobs | job:get, job:list | rule:project_member_or_admin | Project |
| Admin — list all jobs (fleet-wide) | admin:job:list | role:abaca_admin | System |
| Admin — list / manage worker fleet | admin:worker:list, admin:worker:delete | role:abaca_admin | System |
| Admin — list all targets (fleet-wide) | admin:target:list | role:abaca_admin | System |
| Admin — domain registration | admin:domain:create, admin:domain:delete | role:abaca_admin | System |
| Admin — QoS configuration | admin:domain:qos | role:abaca_admin | System |
Checking effective policy
You can use the openstack CLI with the python-abacaclient plugin to verify that a given user can perform an action by inspecting the HTTP response code. There is no dedicated policy check CLI subcommand — rely on the API directly:
# Attempt to list backup targets as a project member — should return 200
openstack share protection target list
# Attempt a domain-owner-only operation as a plain member — expect 403
openstack share protection target template create \
--name test-template \
--s3-endpoint https://s3.example.com \
--bucket-scheme shared
Granting the abaca_domain_owner role
# Assign the domain-owner role to a user in a specific domain
openstack role add \
--user alice \
--domain MyDomain \
abaca_domain_owner
Granting the abaca_admin role
# Assign the admin role system-wide to an operator account
openstack role add \
--user ops-bot \
--system all \
abaca_admin
Example 1 — Viewing the compiled default policy
Generate the full default policy to understand what rules are in effect before writing any overrides:
oc exec -n abaca deployment/abaca-api -- \
abaca-manage policy generate-default-policy \
--output-file /tmp/defaults.yaml
oc cp abaca/$(oc get pod -n abaca -l app=abaca-api -o name | head -1 | cut -d/ -f2):/tmp/defaults.yaml ./abaca-policy-defaults.yaml
cat ./abaca-policy-defaults.yaml
Expected output (abbreviated):
# (generated by abaca-manage policy generate-default-policy)
# Rule: target_template:create
# Scope: domain
# Default: role:abaca_domain_owner
target_template:create: role:abaca_domain_owner
# Rule: backup:create
# Scope: project
# Default: rule:project_member_or_admin
backup:create: rule:project_member_or_admin
# ... (full rule set follows)
Example 2 — Restricting on-demand backup creation to a custom role
Suppose you want only users with a site-specific abaca_power_user role (in addition to operators) to create on-demand backups, while all members can still list and view them.
policy.yaml override file:
# Only power users and admins can trigger on-demand backups.
# Members retain read access (backup:get and backup:list keep their defaults).
"backup:create": "role:abaca_power_user or role:abaca_admin"
Apply it:
oc create configmap abaca-policy \
--from-file=policy.yaml=./policy.yaml \
-n abaca --dry-run=client -o yaml | oc apply -f -
Test as an unprivileged member (expect 403 Forbidden):
openstack share protection backup create --share <share-id> --policy <policy-id>
# HTTP 403 — Policy does not allow backup:create
Test as a abaca_power_user member (expect 202 Accepted):
# After assigning the role:
openstack role add --user alice --project MyProject abaca_power_user
openstack share protection backup create --share <share-id> --policy <policy-id>
# HTTP 202 — backup job queued
Example 3 — Enabling scope enforcement
Add to /etc/abaca/abaca.conf (via your kustomize ConfigMap for the abaca-api pod):
[oslo_policy]
enforce_scope = true
enforce_new_defaults = true
policy_file = /etc/abaca/policy.yaml
After rolling out the change, a project-scoped token can no longer satisfy a domain-scoped rule. Attempt an admin operation with a project-scoped token:
openstack --os-auth-type password \
--os-project-name MyProject \
share protection target template create \
--name bad-attempt --s3-endpoint https://s3.example.com --bucket-scheme shared
# HTTP 403 — scope mismatch: domain scope required for target_template:create
Example 4 — Granting a user read-only access to the admin fleet panel
Create a read-only operator role assignment (system-scoped abaca_admin controls all admin routes; if you want a narrower grant, write a custom rule override):
# Full admin (all /v1/admin/ routes)
openstack role add --user fleet-reader --system all abaca_admin
To scope down to list-only, add a rule override:
# policy.yaml
# Allow fleet-reader to list workers and jobs but not modify them.
"admin:worker:list": "role:abaca_admin or role:abaca_fleet_reader"
"admin:job:list": "role:abaca_admin or role:abaca_fleet_reader"
"admin:worker:delete": "role:abaca_admin" # explicitly block fleet-reader
Then assign the custom role:
openstack role create abaca_fleet_reader
openstack role add --user fleet-reader --system all abaca_fleet_reader
Issue 1 — All API requests return 403 Forbidden after deploying a policy.yaml
Symptom: Every authenticated request to abaca-api returns HTTP 403, including requests from accounts that worked before.
Likely cause: The policy.yaml override file contains a syntax error, an unknown rule reference, or a rule that inadvertently overrides a base rule (e.g., rule:default) to always deny.
Fix:
- Check
abaca-apipod logs for oslo.policy parse errors:oc logs -n abaca deployment/abaca-api | grep -i 'policy\|oslo_policy\|error' - Validate YAML syntax locally:
python3 -c "import yaml; yaml.safe_load(open('policy.yaml'))" - If the file is invalid, update the ConfigMap with a corrected version and verify the pod reloads:
oc create configmap abaca-policy \ --from-file=policy.yaml=./policy.yaml \ -n abaca --dry-run=client -o yaml | oc apply -f - oc logs -n abaca deployment/abaca-api | grep 'Loaded policy' - If you cannot identify the bad rule, temporarily remove the ConfigMap volume mount (reverting to compiled defaults) to restore access, then debug the file offline.
Issue 2 — A abaca_domain_owner user receives 403 when creating a target template
Symptom: A user with the abaca_domain_owner role assigned in a Domain receives HTTP 403 when calling openstack share protection target template create.
Likely cause: The user's token is project-scoped rather than domain-scoped. Domain-owner rules require a domain-scoped token. This is enforced more strictly when enforce_scope = true.
Fix:
- Confirm the token scope by inspecting the token:
openstack token issue # Check that 'domain' appears in the output, not just 'project' - Re-authenticate with domain scope:
export OS_AUTH_TYPE=password export OS_DOMAIN_NAME=MyDomain unset OS_PROJECT_NAME OS_PROJECT_ID openstack token issue - Retry the target template creation with the domain-scoped token.
Issue 3 — abaca-manage policy generate-default-policy command is not found
Symptom: Running abaca-manage policy generate-default-policy inside the pod produces No such command 'policy' or similar.
Likely cause: The installed version of the abaca package does not yet include the policy subcommand group, or you are running the command outside the correct pod.
Fix:
- Confirm you are exec-ing into the
abaca-apipod (not the conductor):oc exec -n abaca deployment/abaca-api -- abaca-manage --help - Verify the package version:
oc exec -n abaca deployment/abaca-api -- pip show abaca - If the subcommand is absent, export the defaults from a local development environment using the same package version, or read the default policy directly from
abaca/common/policies/in the source tree.
Issue 4 — Policy changes have no effect after updating the ConfigMap
Symptom: You updated the abaca-policy ConfigMap but the old policy is still being applied.
Likely cause: oslo.policy caches the policy file. A ConfigMap update propagates to the pod's mounted file within ~60 seconds (kubelet sync), but the running process may not re-read it until the cache expires or the pod restarts.
Fix:
- Wait up to 60–90 seconds for kubelet to sync the ConfigMap volume, then test again.
- If the file has updated on disk (verify with
oc exec) but the behavior has not changed, restart the pod to force an immediate reload:oc rollout restart deployment/abaca-api -n abaca oc rollout status deployment/abaca-api -n abaca - Confirm the policy reloaded:
oc logs -n abaca deployment/abaca-api | grep 'Loaded policy'
Issue 5 — noauth = true was inadvertently left enabled in production
Symptom: The abaca-api accepts requests with no X-Auth-Token header and applies no policy checks. Audit logs show no Keystone token validation events.
Likely cause: The [api] noauth = true setting intended for the local Docker Compose dev stack was carried into the production abaca.conf.
Fix: This is a critical security misconfiguration. Immediately:
- Set
noauth = falsein the[api]section ofabaca.conf(via your kustomize ConfigMap for the API pod). - Roll out the change:
oc rollout restart deployment/abaca-api -n abaca oc rollout status deployment/abaca-api -n abaca - Audit API access logs for the window during which
noauthwas enabled and report per your organization's incident-response process.