Bug 1853507 - Elevate project level users access to complete tasks in Horizon causing issues for other users
Summary: Elevate project level users access to complete tasks in Horizon causing issue...
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat OpenStack
Classification: Red Hat
Component: openstack-barbican
Version: 13.0 (Queens)
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
: ---
Assignee: Ade Lee
QA Contact: Jeremy Agee
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2020-07-02 20:38 UTC by ldenny
Modified: 2023-10-06 20:58 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2020-07-27 22:30:35 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)

Description ldenny 2020-07-02 20:38:58 UTC
Description of problem:

We currently have a number of operations that require admin level access, but should be possible for project level users to perform.

A couple of examples:
- creating secrets (requires the ability to get the Octavia UUID to grant access a role)
- deleting a router

We are currently using admin credentials to complete these operations. 

After adding the new user using the below heat templates:
~~~
parameter_defaults:
  ControllerExtraConfig:
    octavia::roles::role_names: ['load-balancer_observer', 'load-balancer_global_observer', 'load-balancer_member', 'load-balancer_quota_admin', 'admin', 'project_load-balancer_admin' ]
~~~

~~~
[root@overcloud-controller-2 ~]# cat /etc/puppet/hieradata/controller_extraconfig.json | jq .
{
  "octavia::roles::role_names": [
    "load-balancer_observer",
    "load-balancer_global_observer",
    "load-balancer_member",
    "load-balancer_quota_admin",
    "admin",
    "project_load-balancer_admin"
  ]
}
~~~

Updated policy.yaml:
~~~
OctaviaApiPolicies: {
    "octavia-context_is_admin": {"key":"context_is_admin", "value":"role:admin or role:load-balancer_admin or role:project_load-balancer_admin"},
    "octavia-load-balancer:owner": {"key":"load-balancer:owner", "value":"project_id:%(project_id)s"},
    "octavia-load-balancer:admin": {"key":"load-balancer:admin", "value":"is_admin:True or role:admin or role:load-balancer_admin or role:project_load-balancer_admin"},
    "octavia-load-balancer:observer_and_owner": {"key":"load-balancer:observer_and_owner", "value":"role:load-balancer_observer and rule:load-balancer:owner"},
    "octavia-load-balancer:global_observer": {"key":"load-balancer:global_observer", "value":"role:load-balancer_global_observer"},
    "octavia-load-balancer:member_and_owner": {"key":"load-balancer:member_and_owner", "value":"role:load-balancer_member and rule:load-balancer:owner"},
    "octavia-load-balancer:read": {"key":"load-balancer:read", "value":"rule:load-balancer:observer_and_owner or rule:load-balancer:global_observer or rule:load-balancer:member_and_owner or rule:load-balancer:admin"},
    "octavia-load-balancer:read-global": {"key":"load-balancer:read-global", "value":"rule:load-balancer:global_observer or rule:load-balancer:admin"},
    "octavia-load-balancer:write": {"key":"load-balancer:write", "value":"rule:load-balancer:member_and_owner or rule:load-balancer:admin"},
    "octavia-load-balancer:read-quota": {"key":"load-balancer:read-quota", "value":"rule:load-balancer:observer_and_owner or rule:load-balancer:global_observer or rule:load-balancer:member_and_owner or role:load-balancer_quota_admin or rule:load-balancer:admin"},
    "octavia-load-balancer:read-quota-global": {"key":"load-balancer:read-quota-global", "value":"rule:load-balancer:global_observer or role:load-balancer_quota_admin or rule:load-balancer:admin"},
    "octavia-load-balancer:write-quota": {"key":"load-balancer:write-quota", "value":"role:load-balancer_quota_admin or rule:load-balancer:admin"},
    "octavia-os_load-balancer_api:healthmonitor:get_all": {"key":"os_load-balancer_api:healthmonitor:get_all", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:healthmonitor:get_all-global": {"key":"os_load-balancer_api:healthmonitor:get_all-global", "value":"rule:load-balancer:read-global"},
    "octavia-os_load-balancer_api:healthmonitor:post": {"key":"os_load-balancer_api:healthmonitor:post", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:healthmonitor:get_one": {"key":"os_load-balancer_api:healthmonitor:get_one", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:healthmonitor:put": {"key":"os_load-balancer_api:healthmonitor:put", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:healthmonitor:delete": {"key":"os_load-balancer_api:healthmonitor:delete", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:l7policy:get_all": {"key":"os_load-balancer_api:l7policy:get_all", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:l7policy:get_all-global": {"key":"os_load-balancer_api:l7policy:get_all-global", "value":"rule:load-balancer:read-global"},
    "octavia-os_load-balancer_api:l7policy:post": {"key":"os_load-balancer_api:l7policy:post", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:l7policy:get_one": {"key":"os_load-balancer_api:l7policy:get_one", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:l7policy:put": {"key":"os_load-balancer_api:l7policy:put", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:l7policy:delete": {"key":"os_load-balancer_api:l7policy:delete", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:l7rule:get_all": {"key":"os_load-balancer_api:l7rule:get_all", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:l7rule:post": {"key":"os_load-balancer_api:l7rule:post", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:l7rule:get_one": {"key":"os_load-balancer_api:l7rule:get_one", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:l7rule:put": {"key":"os_load-balancer_api:l7rule:put", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:l7rule:delete": {"key":"os_load-balancer_api:l7rule:delete", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:listener:get_all": {"key":"os_load-balancer_api:listener:get_all", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:listener:get_all-global": {"key":"os_load-balancer_api:listener:get_all-global", "value":"rule:load-balancer:read-global"},
    "octavia-os_load-balancer_api:listener:post": {"key":"os_load-balancer_api:listener:post", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:listener:get_one": {"key":"os_load-balancer_api:listener:get_one", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:listener:put": {"key":"os_load-balancer_api:listener:put", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:listener:delete": {"key":"os_load-balancer_api:listener:delete", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:listener:get_stats": {"key":"os_load-balancer_api:listener:get_stats", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:loadbalancer:get_all": {"key":"os_load-balancer_api:loadbalancer:get_all", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:loadbalancer:get_all-global": {"key":"os_load-balancer_api:loadbalancer:get_all-global", "value":"rule:load-balancer:read-global"},
    "octavia-os_load-balancer_api:loadbalancer:post": {"key":"os_load-balancer_api:loadbalancer:post", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:loadbalancer:get_one": {"key":"os_load-balancer_api:loadbalancer:get_one", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:loadbalancer:put": {"key":"os_load-balancer_api:loadbalancer:put", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:loadbalancer:delete": {"key":"os_load-balancer_api:loadbalancer:delete", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:loadbalancer:get_stats": {"key":"os_load-balancer_api:loadbalancer:get_stats", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:loadbalancer:get_status": {"key":"os_load-balancer_api:loadbalancer:get_status", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:loadbalancer:put_failover": {"key":"os_load-balancer_api:loadbalancer:put_failover", "value":"rule:load-balancer:admin"},
    "octavia-os_load-balancer_api:member:get_all": {"key":"os_load-balancer_api:member:get_all", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:member:post": {"key":"os_load-balancer_api:member:post", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:member:get_one": {"key":"os_load-balancer_api:member:get_one", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:member:put": {"key":"os_load-balancer_api:member:put", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:member:delete": {"key":"os_load-balancer_api:member:delete", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:pool:get_all": {"key":"os_load-balancer_api:pool:get_all", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:pool:get_all-global": {"key":"os_load-balancer_api:pool:get_all-global", "value":"rule:load-balancer:read-global"},
    "octavia-os_load-balancer_api:pool:post": {"key":"os_load-balancer_api:pool:post", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:pool:get_one": {"key":"os_load-balancer_api:pool:get_one", "value":"rule:load-balancer:read"},
    "octavia-os_load-balancer_api:pool:put": {"key":"os_load-balancer_api:pool:put", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:pool:delete": {"key":"os_load-balancer_api:pool:delete", "value":"rule:load-balancer:write"},
    "octavia-os_load-balancer_api:quota:get_all": {"key":"os_load-balancer_api:quota:get_all", "value":"rule:load-balancer:read-quota"},
    "octavia-os_load-balancer_api:quota:get_all-global": {"key":"os_load-balancer_api:quota:get_all-global", "value":"rule:load-balancer:read-quota-global"},
    "octavia-os_load-balancer_api:quota:get_one": {"key":"os_load-balancer_api:quota:get_one", "value":"rule:load-balancer:read-quota"},
    "octavia-os_load-balancer_api:quota:put": {"key":"os_load-balancer_api:quota:put", "value":"rule:load-balancer:write-quota"},
    "octavia-os_load-balancer_api:quota:delete": {"key":"os_load-balancer_api:quota:delete", "value":"rule:load-balancer:write-quota"},
    "octavia-os_load-balancer_api:quota:get_defaults": {"key":"os_load-balancer_api:quota:get_defaults", "value":"rule:load-balancer:read-quota"},
    "octavia-os_load-balancer_api:amphora:get_all": {"key":"os_load-balancer_api:amphora:get_all", "value":"rule:load-balancer:admin"},
    "octavia-os_load-balancer_api:amphora:get_one": {"key":"os_load-balancer_api:amphora:get_one", "value":"rule:load-balancer:admin"},
    "octavia-os_load-balancer_api:amphora:put_failover": {"key":"os_load-balancer_api:amphora:put_failover", "value":"rule:load-balancer:admin"}
  }
~~~




We can see that the new role makes an appearance there as well after this change:
~~~
And the policy.json file has also been updated:
[root@overcloud-controller-2 octavia]# cat policy.json | jq . | grep 'project_load-balancer_admin'
  "context_is_admin": "role:admin or role:load-balancer_admin or role:project_load-balancer_admin",
  "load-balancer:admin": "is_admin:True or role:admin or role:load-balancer_admin or role:project_load-balancer_admin",
~~~


However once this change is in place we get errors like this when accessing Network -> Load Balancers using a user without the new project_load-balancer_admin role:
~~~
2020-01-16 11:33:46,429 58 ERROR openstack_dashboard.api.rest.utils error invoking apiclient
Traceback (most recent call last):
  File "/usr/share/openstack-dashboard/openstack_dashboard/api/rest/utils.py", line 127, in _wrapped
    data = function(self, request, *args, **kw)
  File "/usr/lib/python2.7/site-packages/octavia_dashboard/api/rest/barbican.py", line 86, in get
    result = secrets._api.get('secrets', params=params)
  File "/usr/lib/python2.7/site-packages/barbicanclient/client.py", line 70, in get
    return super(_HTTPClient, self).get(*args, **kwargs).json()
  File "/usr/lib/python2.7/site-packages/keystoneauth1/adapter.py", line 304, in get
    return self.request(url, 'GET', **kwargs)
  File "/usr/lib/python2.7/site-packages/barbicanclient/client.py", line 63, in request
    self._check_status_code(resp)
  File "/usr/lib/python2.7/site-packages/barbicanclient/client.py", line 107, in _check_status_code
    status
HTTPClientError: Forbidden: Secret(s) retrieval attempt not allowed - please review your user/project privileges
2020-01-16 11:57:58,470 58 INFO openstack_auth.views Logging out user "<userid>".
~~~

This is in addition to a red "Forbidden" notification towards the top-right-hand corner of Horizon.  This seems a bit harsh.  Where do you suggest we look, please, to try and address this?

Comment 1 Radomir Dopieralski 2020-07-08 13:39:07 UTC
It looks like barbican is denying the access. I will move this bug there.

Comment 2 Radomir Dopieralski 2020-07-08 13:39:51 UTC
Also, I'm not sure this should be an RFE, I will remove that tag.

Comment 3 Douglas Mendizábal 2020-07-23 21:22:22 UTC
Barbican and Octavia each use their own respective policy files, so changes to Octavia policy do not affect Barbican policy at all.

The Octavia Dashboard forwards the user's context to Barbican when listing the secrets, so the user must have an appropriate role assigned to them to be able to list secrets from Barbican.  Using the default Barbican policy, a user needs to have any one of these roles to be able to list secrets:

- admin
- creator
- observer

Evidently the user(s) for which this issue is happening do not have any one of those roles assigned to them, so Barbican is correctly denying access.  To fix this issue, the user(s) may be granted any one of those roles, or a new role can be created in a similar fashion as the custom "project_load-balancer_admin" role being created for Octavia.

Comment 5 Douglas Mendizábal 2020-07-23 21:54:43 UTC
Another option would be to create a custom Barbican policy by adding the custom role "project_load-balancer_admin" to allow users with this role to list secrets:

---
BarbicanPolicies: {
    "barbican-secrets:get": {"key": "secrets:get", "value": "rule:all_but_audit or role:project_load-balancer_admin"}
}


Note You need to log in before you can comment on or make changes to this bug.