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?
It looks like barbican is denying the access. I will move this bug there.
Also, I'm not sure this should be an RFE, I will remove that tag.
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.
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"} }