Merge "Implement secure RBAC for resource providers"
This commit is contained in:
commit
b45e3b8a43
|
@ -28,7 +28,10 @@ class Middleware(object):
|
|||
self.application = application
|
||||
|
||||
|
||||
# NOTE(cdent): Only to be used in tests where auth is being faked.
|
||||
# NOTE(cdent): Only to be used in tests where auth is being faked. This
|
||||
# middleware can be used to mimic keystonemiddleware auth_token middleware,
|
||||
# which is important for building API protection tests without an external
|
||||
# dependency on keystone.
|
||||
class NoAuthMiddleware(Middleware):
|
||||
"""Require a token if one isn't present."""
|
||||
|
||||
|
@ -46,12 +49,15 @@ class NoAuthMiddleware(Middleware):
|
|||
token = req.headers['X-Auth-Token']
|
||||
user_id, _sep, project_id = token.partition(':')
|
||||
project_id = project_id or user_id
|
||||
if user_id == 'admin':
|
||||
if 'HTTP_X_ROLES' in req.environ.keys():
|
||||
roles = req.headers['X_ROLES'].split(',')
|
||||
elif user_id == 'admin':
|
||||
roles = ['admin']
|
||||
else:
|
||||
roles = []
|
||||
req.headers['X_USER_ID'] = user_id
|
||||
req.headers['X_TENANT_ID'] = project_id
|
||||
if not req.headers.get('OPENSTACK_SYSTEM_SCOPE'):
|
||||
req.headers['X_TENANT_ID'] = project_id
|
||||
req.headers['X_ROLES'] = ','.join(roles)
|
||||
return self.application
|
||||
|
||||
|
|
|
@ -13,6 +13,12 @@
|
|||
from oslo_policy import policy
|
||||
|
||||
RULE_ADMIN_API = 'rule:admin_api'
|
||||
# NOTE(lbragstad): We might consider converting these generic checks into
|
||||
# RuleDefaults or DocumentedRuleDefaults, but we need to thoroughly vet the
|
||||
# approach in oslo.policy and consume a new version. Until we have that done,
|
||||
# let's continue using generic check strings.
|
||||
SYSTEM_ADMIN = 'role:admin and system_scope:all'
|
||||
SYSTEM_READER = 'role:reader and system_scope:all'
|
||||
|
||||
rules = [
|
||||
# "placement" is the default rule (action) used for all routes that do
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
|
||||
from oslo_log import versionutils
|
||||
from oslo_policy import policy
|
||||
|
||||
from placement.policies import base
|
||||
|
@ -23,62 +24,103 @@ SHOW = PREFIX % 'show'
|
|||
UPDATE = PREFIX % 'update'
|
||||
DELETE = PREFIX % 'delete'
|
||||
|
||||
DEPRECATED_REASON = """
|
||||
The resource provider API now supports a read-only role by default.
|
||||
"""
|
||||
|
||||
deprecated_list_resource_providers = policy.DeprecatedRule(
|
||||
name=LIST,
|
||||
check_str=base.RULE_ADMIN_API
|
||||
)
|
||||
deprecated_show_resource_provider = policy.DeprecatedRule(
|
||||
name=SHOW,
|
||||
check_str=base.RULE_ADMIN_API
|
||||
)
|
||||
deprecated_create_resource_provider = policy.DeprecatedRule(
|
||||
name=CREATE,
|
||||
check_str=base.RULE_ADMIN_API
|
||||
)
|
||||
deprecated_update_resource_provider = policy.DeprecatedRule(
|
||||
name=UPDATE,
|
||||
check_str=base.RULE_ADMIN_API
|
||||
)
|
||||
deprecated_delete_resource_provider = policy.DeprecatedRule(
|
||||
name=DELETE,
|
||||
check_str=base.RULE_ADMIN_API
|
||||
)
|
||||
|
||||
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
LIST,
|
||||
base.RULE_ADMIN_API,
|
||||
"List resource providers.",
|
||||
[
|
||||
name=LIST,
|
||||
check_str=base.SYSTEM_READER,
|
||||
description="List resource providers.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/resource_providers'
|
||||
}
|
||||
],
|
||||
scope_types=['system']),
|
||||
scope_types=['system'],
|
||||
deprecated_rule=deprecated_list_resource_providers,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY),
|
||||
policy.DocumentedRuleDefault(
|
||||
CREATE,
|
||||
base.RULE_ADMIN_API,
|
||||
"Create resource provider.",
|
||||
[
|
||||
name=CREATE,
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
description="Create resource provider.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/resource_providers'
|
||||
}
|
||||
],
|
||||
scope_types=['system']),
|
||||
scope_types=['system'],
|
||||
deprecated_rule=deprecated_create_resource_provider,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY),
|
||||
policy.DocumentedRuleDefault(
|
||||
SHOW,
|
||||
base.RULE_ADMIN_API,
|
||||
"Show resource provider.",
|
||||
[
|
||||
name=SHOW,
|
||||
check_str=base.SYSTEM_READER,
|
||||
description="Show resource provider.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/resource_providers/{uuid}'
|
||||
}
|
||||
],
|
||||
scope_types=['system']),
|
||||
scope_types=['system'],
|
||||
deprecated_rule=deprecated_show_resource_provider,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY),
|
||||
policy.DocumentedRuleDefault(
|
||||
UPDATE,
|
||||
base.RULE_ADMIN_API,
|
||||
"Update resource provider.",
|
||||
[
|
||||
name=UPDATE,
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
description="Update resource provider.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/resource_providers/{uuid}'
|
||||
}
|
||||
],
|
||||
scope_types=['system']),
|
||||
scope_types=['system'],
|
||||
deprecated_rule=deprecated_update_resource_provider,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY),
|
||||
policy.DocumentedRuleDefault(
|
||||
DELETE,
|
||||
base.RULE_ADMIN_API,
|
||||
"Delete resource provider.",
|
||||
[
|
||||
name=DELETE,
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
description="Delete resource provider.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/resource_providers/{uuid}'
|
||||
}
|
||||
],
|
||||
scope_types=['system']),
|
||||
scope_types=['system'],
|
||||
deprecated_rule=deprecated_delete_resource_provider,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -107,6 +107,8 @@ def authorize(context, action, target, do_raise=True):
|
|||
except policy.PolicyNotRegistered:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception('Policy not registered')
|
||||
except policy.InvalidScope:
|
||||
raise exception.PolicyNotAuthorized(action)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
credentials = context.to_policy_values()
|
||||
|
|
|
@ -50,6 +50,9 @@ def setup_app():
|
|||
class APIFixture(fixture.GabbiFixture):
|
||||
"""Setup the required backend fixtures for a basic placement service."""
|
||||
|
||||
# TODO(stephenfin): Remove this once we drop the deprecated policy rules
|
||||
_secure_rbac = False
|
||||
|
||||
def start_fixture(self):
|
||||
global CONF
|
||||
# Set up stderr and stdout captures by directly driving the
|
||||
|
@ -72,6 +75,11 @@ class APIFixture(fixture.GabbiFixture):
|
|||
self.conf_fixture.setUp()
|
||||
conf.register_opts(self.conf_fixture.conf)
|
||||
self.conf_fixture.config(group='api', auth_strategy='noauth2')
|
||||
self.conf_fixture.config(
|
||||
group='oslo_policy',
|
||||
enforce_scope=self._secure_rbac,
|
||||
enforce_new_defaults=self._secure_rbac,
|
||||
)
|
||||
|
||||
self.placement_db_fixture = fixtures.Database(
|
||||
self.conf_fixture, set_config=True)
|
||||
|
@ -748,3 +756,19 @@ class OpenPolicyFixture(APIFixture):
|
|||
|
||||
def stop_fixture(self):
|
||||
super(OpenPolicyFixture, self).stop_fixture()
|
||||
|
||||
|
||||
class SecureRBACPolicyFixture(APIFixture):
|
||||
"""An APIFixture that enforce secure default policies and scope."""
|
||||
|
||||
_secure_rbac = True
|
||||
|
||||
|
||||
# Even though this just configures the defaults for enforce_scope and
|
||||
# enforce_new_default, it's useful because it's explicit in saying we're
|
||||
# testing old policy behavior. We can remove this once placement removes its
|
||||
# deprecated policies.
|
||||
class LegacyRBACPolicyFixture(APIFixture):
|
||||
"""An APIFixture that enforce deprecated policies."""
|
||||
|
||||
_secure_rbac = False
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
---
|
||||
fixtures:
|
||||
- LegacyRBACPolicyFixture
|
||||
|
||||
vars:
|
||||
- &project_id $ENVIRON['PROJECT_ID']
|
||||
- &system_admin_headers
|
||||
x-auth-token: user
|
||||
x-roles: admin,member,reader
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
openstack-system-scope: all
|
||||
- &system_reader_headers
|
||||
x-auth-token: user
|
||||
x-roles: reader
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
openstack-system-scope: all
|
||||
- &project_admin_headers
|
||||
x-auth-token: user
|
||||
x-roles: admin,member,reader
|
||||
x-project-id: *project_id
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
- &project_member_headers
|
||||
x-auth-token: user
|
||||
x-roles: member,reader
|
||||
x-project-id: *project_id
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
- &project_reader_headers
|
||||
x-auth-token: user
|
||||
x-roles: reader
|
||||
x-project-id: *project_id
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
|
||||
tests:
|
||||
|
||||
- name: system admin can list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *system_admin_headers
|
||||
response_json_paths:
|
||||
$.resource_providers: []
|
||||
|
||||
- name: system reader can list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *system_reader_headers
|
||||
response_json_paths:
|
||||
$.resource_providers: []
|
||||
|
||||
- name: project admin can list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *project_admin_headers
|
||||
response_json_paths:
|
||||
$.resource_providers: []
|
||||
|
||||
- name: project member cannot list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *project_member_headers
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *project_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: system admin can create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *system_admin_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 200
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: system reader cannot create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *system_reader_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 403
|
||||
|
||||
- name: system admin can delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_admin_headers
|
||||
status: 204
|
||||
|
||||
- name: project admin can create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *project_admin_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: project member cannot create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *project_member_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *project_reader_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 403
|
||||
|
||||
- name: system admin can show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_admin_headers
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: system reader can show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_reader_headers
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: project admin can show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_admin_headers
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: project member cannot show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_member_headers
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: system admin can update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_admin_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 200
|
||||
response_json_paths:
|
||||
$.name: new name
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: system reader cannot update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_reader_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 403
|
||||
|
||||
- name: project admin can update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_admin_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 200
|
||||
response_json_paths:
|
||||
$.name: new name
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: project member cannot update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_member_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_reader_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 403
|
||||
|
||||
- name: system reader cannot delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: project member cannot delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_member_headers
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: project admin can delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_admin_headers
|
||||
status: 204
|
||||
|
||||
# We tested that system admins can delete resource providers above
|
|
@ -0,0 +1,202 @@
|
|||
---
|
||||
fixtures:
|
||||
- SecureRBACPolicyFixture
|
||||
|
||||
vars:
|
||||
- &project_id $ENVIRON['PROJECT_ID']
|
||||
- &system_admin_headers
|
||||
x-auth-token: user
|
||||
x-roles: admin,member,reader
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
openstack-system-scope: all
|
||||
- &system_reader_headers
|
||||
x-auth-token: user
|
||||
x-roles: reader
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
openstack-system-scope: all
|
||||
- &project_admin_headers
|
||||
x-auth-token: user
|
||||
x-roles: admin,member,reader
|
||||
x-project-id: *project_id
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
- &project_member_headers
|
||||
x-auth-token: user
|
||||
x-roles: member,reader
|
||||
x-project-id: *project_id
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
- &project_reader_headers
|
||||
x-auth-token: user
|
||||
x-roles: reader
|
||||
x-project-id: *project_id
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
|
||||
tests:
|
||||
|
||||
- name: system admin can list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *system_admin_headers
|
||||
response_json_paths:
|
||||
$.resource_providers: []
|
||||
|
||||
- name: system reader can list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *system_reader_headers
|
||||
response_json_paths:
|
||||
$.resource_providers: []
|
||||
|
||||
- name: project admin cannot list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *project_admin_headers
|
||||
status: 403
|
||||
|
||||
- name: project member cannot list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *project_member_headers
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot list resource providers
|
||||
GET: /resource_providers
|
||||
request_headers: *project_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: system admin can create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *system_admin_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 200
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: system reader cannot create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *system_reader_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 403
|
||||
|
||||
- name: project admin cannot create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *project_admin_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 403
|
||||
|
||||
- name: project member cannot create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *project_member_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot create resource providers
|
||||
POST: /resource_providers
|
||||
request_headers: *project_reader_headers
|
||||
data:
|
||||
name: $ENVIRON['RP_NAME']
|
||||
uuid: $ENVIRON['RP_UUID']
|
||||
status: 403
|
||||
|
||||
- name: system admin can show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_admin_headers
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: system reader can show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_reader_headers
|
||||
response_json_paths:
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: project admin cannot show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_admin_headers
|
||||
status: 403
|
||||
|
||||
- name: project member cannot show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_member_headers
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot show resource provider
|
||||
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: system admin can update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_admin_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 200
|
||||
response_json_paths:
|
||||
$.name: new name
|
||||
$.uuid: $ENVIRON['RP_UUID']
|
||||
|
||||
- name: system reader cannot update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_reader_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 403
|
||||
|
||||
- name: project admin cannot update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_admin_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 403
|
||||
|
||||
- name: project member cannot update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_member_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot update resource provider
|
||||
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_reader_headers
|
||||
data:
|
||||
name: new name
|
||||
status: 403
|
||||
|
||||
- name: system reader cannot delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: project admin cannot delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_admin_headers
|
||||
status: 403
|
||||
|
||||
- name: project member cannot delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_member_headers
|
||||
status: 403
|
||||
|
||||
- name: project reader cannot delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *project_reader_headers
|
||||
status: 403
|
||||
|
||||
- name: system admin can delete resource provider
|
||||
DELETE: /resource_providers/$ENVIRON['RP_UUID']
|
||||
request_headers: *system_admin_headers
|
||||
status: 204
|
Loading…
Reference in New Issue