diff --git a/doc/source/admin/secure-rbac.rst b/doc/source/admin/secure-rbac.rst index d80643c66b..639cfcb23f 100644 --- a/doc/source/admin/secure-rbac.rst +++ b/doc/source/admin/secure-rbac.rst @@ -62,6 +62,12 @@ Project Scoped Project scoped authentication is when a request token and associated records indicate an associated ``project_id`` value. +The Secure RBAC model, since the introduction of the base capability has been +extended as a result of an OpenStack community goal to include a ``manager`` +role in the project scope. By default, this access is equivelent to a Project +scoped ``admin`` user, however it may be delineated further as time moves +forward. + Legacy Behavior --------------- diff --git a/ironic/common/policy.py b/ironic/common/policy.py index d613aec064..1bf8d7376c 100644 --- a/ironic/common/policy.py +++ b/ironic/common/policy.py @@ -64,6 +64,13 @@ SYSTEM_READER = 'role:reader and system_scope:all' # default volume type for a project) PROJECT_ADMIN = ('role:admin and ' 'project_id:%(node.owner)s') +# This check string is reserved for an intermediate point between +# a Project Admin and a Project Member. This is an outcome of the +# revised Yoga Secure RBAC community goal. +# The advantage here may be that this rule *does* match against node owners +# and lessees. +PROJECT_MANAGER = ('role:manager and ' + '(project_id:%(node.owner)s or project_id:%(node.lessee)s)') # This check string is the primary use case for typical end-users, who are # working with resources that belong to a project (e.g., creating volumes and # backups). @@ -88,24 +95,30 @@ SYSTEM_OR_PROJECT_READER = ( ) PROJECT_OWNER_ADMIN = ('role:admin and project_id:%(node.owner)s') +PROJECT_OWNER_MANAGER = ('role:manager and project_id:%(node.owner)s') PROJECT_OWNER_MEMBER = ('role:member and project_id:%(node.owner)s') PROJECT_OWNER_READER = ('role:reader and project_id:%(node.owner)s') PROJECT_LESSEE_ADMIN = ('role:admin and project_id:%(node.lessee)s') +PROJECT_LESSEE_MANAGER = ('role:manager and project_id:%(node.lessee)s') +# Not used - Members can create/destroy their allocations. ALLOCATION_OWNER_ADMIN = ('role:admin and project_id:%(allocation.owner)s') +# Not used - Members can create/destroy their allocations. +ALLOCATION_OWNER_MANAGER = ('role:manager and project_id:%(allocation.owner)s') + ALLOCATION_OWNER_MEMBER = ('role:member and project_id:%(allocation.owner)s') ALLOCATION_OWNER_READER = ('role:reader and project_id:%(allocation.owner)s') SYSTEM_OR_OWNER_MEMBER_AND_LESSEE_ADMIN = ( - '(' + SYSTEM_MEMBER + ') or (' + PROJECT_OWNER_MEMBER + ') or (' + PROJECT_LESSEE_ADMIN + ')' # noqa + '(' + SYSTEM_MEMBER + ') or (' + PROJECT_OWNER_MEMBER + ') or (' + PROJECT_LESSEE_ADMIN + ') or (' + PROJECT_LESSEE_MANAGER + ')' # noqa ) SYSTEM_ADMIN_OR_OWNER_ADMIN = ( - '(' + SYSTEM_ADMIN + ') or (' + PROJECT_OWNER_ADMIN + ')' + '(' + SYSTEM_ADMIN + ') or (' + PROJECT_OWNER_ADMIN + ') or (' + PROJECT_OWNER_MANAGER + ')' # noqa ) SYSTEM_MEMBER_OR_OWNER_ADMIN = ( - '(' + SYSTEM_MEMBER + ') or (' + PROJECT_OWNER_ADMIN + ')' + '(' + SYSTEM_MEMBER + ') or (' + PROJECT_OWNER_ADMIN + ') or (' + PROJECT_OWNER_MANAGER + ')' # noqa ) SYSTEM_MEMBER_OR_OWNER_MEMBER = ( @@ -117,7 +130,7 @@ SYSTEM_OR_OWNER_READER = ( ) SYSTEM_MEMBER_OR_OWNER_LESSEE_ADMIN = ( - '(' + SYSTEM_MEMBER + ') or (' + PROJECT_OWNER_ADMIN + ') or (' + PROJECT_LESSEE_ADMIN + ')' # noqa + '(' + SYSTEM_MEMBER + ') or (' + PROJECT_OWNER_ADMIN + ') or (' + PROJECT_OWNER_MANAGER + ') or (' + PROJECT_LESSEE_ADMIN + ') or (' + PROJECT_LESSEE_MANAGER + ')' # noqa ) diff --git a/ironic/tests/unit/api/test_rbac_project_scoped.yaml b/ironic/tests/unit/api/test_rbac_project_scoped.yaml index 212669a620..802600703d 100644 --- a/ironic/tests/unit/api/test_rbac_project_scoped.yaml +++ b/ironic/tests/unit/api/test_rbac_project_scoped.yaml @@ -38,7 +38,11 @@ values: # Project scoped admin token owner_admin_headers: &owner_admin_headers X-Auth-Token: 'owner-admin-token' - X-Roles: admin,member,reader + X-Roles: admin,manager,member,reader + X-Project-Id: 70e5e25a-2ca2-4cb1-8ae8-7d8739cee205 + owner_manager_headers: &owner_manager_headers + X-Auth-Token: 'owner-manager-token' + X-Roles: manager,member,reader X-Project-Id: 70e5e25a-2ca2-4cb1-8ae8-7d8739cee205 # Project scoped other member token. owner_member_headers: &owner_member_headers @@ -53,7 +57,11 @@ values: lessee_admin_headers: &lessee_admin_headers X-Auth-Token: 'lessee-admin-token' X-Project-Id: f11853c7-fa9c-4db3-a477-c9d8e0dbbf13 - X-Roles: admin,member,reader + X-Roles: admin,manager,member,reader + lessee_manager_headers: &lessee_manager_headers + X-Auth-Token: 'lessee-manager-token' + X-Project-Id: f11853c7-fa9c-4db3-a477-c9d8e0dbbf13 + X-Roles: manager,member,reader lessee_member_headers: &lessee_member_headers X-Auth-Token: 'lessee-member-token' X-Project-Id: f11853c7-fa9c-4db3-a477-c9d8e0dbbf13 @@ -65,7 +73,7 @@ values: third_party_admin_headers: &third_party_admin_headers X-Auth-Token: 'third-party-admin-token' X-Project-Id: ae64129e-b188-4662-b014-4127f4366ee6 - X-Roles: admin,member,reader + X-Roles: admin,manager,member,reader owner_project_id: &owner_project_id 70e5e25a-2ca2-4cb1-8ae8-7d8739cee205 lessee_project_id: &lessee_project_id f11853c7-fa9c-4db3-a477-c9d8e0dbbf13 owned_node_ident: &owned_node_ident f11853c7-fa9c-4db3-a477-c9d8e0dbbf13 @@ -83,6 +91,13 @@ owner_admin_cannot_post_nodes: driver: fake-driverz assert_status: 500 +owner_manager_cannot_post_nodes: + path: '/v1/nodes' + method: post + headers: *owner_manager_headers + body: *node_post_body + assert_status: 500 + lessee_admin_cannot_post_nodes: path: '/v1/nodes' method: post @@ -90,6 +105,13 @@ lessee_admin_cannot_post_nodes: body: *node_post_body assert_status: 500 +lessee_manager_cannot_post_nodes: + path: '/v1/nodes' + method: post + headers: *lessee_manager_headers + body: *node_post_body + assert_status: 500 + third_party_admin_cannot_post_nodes: path: '/v1/nodes' method: post @@ -123,6 +145,14 @@ owner_admin_can_get_node: nodes: 2 assert_status: 200 +owner_manager_can_get_node: + path: '/v1/nodes' + method: get + headers: *owner_manager_headers + assert_list_length: + nodes: 2 + assert_status: 200 + owner_member_can_get_node: path: '/v1/nodes' method: get @@ -147,6 +177,14 @@ lessee_admin_can_get_node: nodes: 1 assert_status: 200 +lessee_manager_can_get_node: + path: '/v1/nodes' + method: get + headers: *lessee_manager_headers + assert_list_length: + nodes: 1 + assert_status: 200 + lessee_member_can_get_node: path: '/v1/nodes' method: get @@ -277,6 +315,13 @@ owner_admin_can_patch_node_extra: value: {'test': 'testing'} assert_status: 503 +owner_manager_can_patch_node_extra: + path: '/v1/nodes/{owner_node_ident}' + method: patch + headers: *owner_manager_headers + body: *extra_patch + assert_status: 503 + owner_member_can_patch_node_extra: path: '/v1/nodes/{owner_node_ident}' method: patch @@ -298,6 +343,13 @@ lessee_admin_can_patch_node_extra: body: *extra_patch assert_status: 503 +lessee_manager_can_patch_node_extra: + path: '/v1/nodes/{lessee_node_ident}' + method: patch + headers: *lessee_manager_headers + body: *extra_patch + assert_status: 503 + lessee_member_can_patch_node_extra: path: '/v1/nodes/{lessee_node_ident}' method: patch @@ -332,6 +384,19 @@ owner_admin_can_change_drivers: value: fake assert_status: 503 +owner_manager_can_change_drivers: + path: '/v1/nodes/{owner_node_ident}' + method: patch + headers: *owner_manager_headers + body: + - op: replace + path: /driver + value: fake-hardware + - op: replace + path: /power_interface + value: fake + assert_status: 503 + owner_member_can_patch_all_the_things: path: '/v1/nodes/{owner_node_ident}' method: patch @@ -363,6 +428,7 @@ owner_member_can_patch_all_the_things: value: "43" assert_status: 503 +# FIXME(TheJulia): This should be with member privilges below. owner_member_can_change_lessee: path: '/v1/nodes/{owner_node_ident}' method: patch @@ -383,6 +449,16 @@ lessee_admin_cannot_change_lessee: path: /lessee value: "1234" +lessee_manager_cannot_change_lessee: + path: '/v1/nodes/{lessee_node_ident}' + method: patch + headers: *lessee_manager_headers + assert_status: 403 + body: + - op: replace + path: /lessee + value: "1234" + lessee_admin_cannot_change_owner: path: '/v1/nodes/{lessee_node_ident}' method: patch @@ -393,6 +469,16 @@ lessee_admin_cannot_change_owner: value: "1234" assert_status: 403 +lessee_manager_cannot_change_owner: + path: '/v1/nodes/{lessee_node_ident}' + method: patch + headers: *lessee_manager_headers + body: + - op: replace + path: /owner + value: "1234" + assert_status: 403 + owner_admin_can_change_lessee: path: '/v1/nodes/{owner_node_ident}' method: patch @@ -403,6 +489,16 @@ owner_admin_can_change_lessee: value: "1234" assert_status: 503 +owner_manager_can_change_lessee: + path: '/v1/nodes/{owner_node_ident}' + method: patch + headers: *owner_manager_headers + body: + - op: replace + path: /lessee + value: "1234" + assert_status: 503 + owner_admin_cannot_change_owner: path: '/v1/nodes/{owner_node_ident}' method: patch @@ -413,6 +509,16 @@ owner_admin_cannot_change_owner: value: "1234" assert_status: 403 +owner_manager_cannot_change_owner: + path: '/v1/nodes/{owner_node_ident}' + method: patch + headers: *owner_manager_headers + body: + - op: replace + path: /owner + value: "1234" + assert_status: 403 + # This is not an explicitly restricted item, it falls # to generalized update capability, which oddly makes # a lot of sense in this case. It is a flag to prevent @@ -504,6 +610,13 @@ owner_admin_can_patch_node_instance_info: value: {'test': 'testing'} assert_status: 503 +owner_manager_can_patch_node_instance_info: + path: '/v1/nodes/{owner_node_ident}' + method: patch + headers: *owner_manager_headers + body: *instance_info_patch + assert_status: 503 + owner_member_can_patch_node_instance_info: path: '/v1/nodes/{owner_node_ident}' method: patch @@ -525,6 +638,13 @@ lessee_admin_can_patch_node_instance_info: body: *instance_info_patch assert_status: 503 +lessee_manager_can_patch_node_instance_info: + path: '/v1/nodes/{lessee_node_ident}' + method: patch + headers: *lessee_manager_headers + body: *instance_info_patch + assert_status: 503 + lessee_member_cannot_patch_node_instance_info: path: '/v1/nodes/{lessee_node_ident}' method: patch @@ -552,12 +672,24 @@ owner_admin_cannot_delete_nodes: headers: *owner_admin_headers assert_status: 403 +owner_manager_cannot_delete_nodes: + path: '/v1/nodes/{owner_node_ident}' + method: delete + headers: *owner_manager_headers + assert_status: 403 + lessee_admin_cannot_delete_nodes: path: '/v1/nodes/{lessee_node_ident}' method: delete headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_delete_nodes: + path: '/v1/nodes/{lessee_node_ident}' + method: delete + headers: *lessee_manager_headers + assert_status: 403 + third_party_admin_cannot_delete_nodes: path: '/v1/nodes/{owner_node_ident}' method: delete @@ -579,12 +711,24 @@ owner_admin_can_validate_node: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_validate_node: + path: '/v1/nodes/{owner_node_ident}/validate' + method: get + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_can_validate_node: path: '/v1/nodes/{lessee_node_ident}/validate' method: get headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_validate_node: + path: '/v1/nodes/{lessee_node_ident}/validate' + method: get + headers: *lessee_manager_headers + assert_status: 503 + owner_member_can_validate_node: path: '/v1/nodes/{owner_node_ident}/validate' method: get @@ -609,6 +753,12 @@ owner_admin_can_set_maintenance: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_set_maintenance: + path: '/v1/nodes/{owner_node_ident}/maintenance' + method: put + headers: *owner_manager_headers + assert_status: 503 + # should we really allow this? they could desync with nova if they can do this... lessee_admin_can_set_maintenance: path: '/v1/nodes/{lessee_node_ident}/maintenance' @@ -616,6 +766,12 @@ lessee_admin_can_set_maintenance: headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_set_maintenance: + path: '/v1/nodes/{lessee_node_ident}/maintenance' + method: put + headers: *lessee_manager_headers + assert_status: 503 + owner_member_can_set_maintenance: path: '/v1/nodes/{owner_node_ident}/maintenance' method: put @@ -640,12 +796,24 @@ owner_admin_can_unset_maintenance: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_unset_maintenance: + path: '/v1/nodes/{owner_node_ident}/maintenance' + method: delete + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_can_unset_maintenance: path: '/v1/nodes/{lessee_node_ident}/maintenance' method: delete headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_unset_maintenance: + path: '/v1/nodes/{lessee_node_ident}/maintenance' + method: delete + headers: *lessee_manager_headers + assert_status: 503 + owner_member_can_unset_maintnenance: path: '/v1/nodes/{owner_node_ident}/maintenance' method: delete @@ -674,6 +842,13 @@ owner_admin_can_set_boot_device: boot_device: pxe assert_status: 503 +owner_manager_can_set_boot_device: + path: '/v1/nodes/{owner_node_ident}/management/boot_device' + method: put + headers: *owner_manager_headers + body: *boot_device_body + assert_status: 503 + lessee_admin_cannot_set_boot_device: path: '/v1/nodes/{lessee_node_ident}/management/boot_device' method: put @@ -681,6 +856,13 @@ lessee_admin_cannot_set_boot_device: body: *boot_device_body assert_status: 403 +lessee_manager_cannot_set_boot_device: + path: '/v1/nodes/{lessee_node_ident}/management/boot_device' + method: put + headers: *lessee_manager_headers + body: *boot_device_body + assert_status: 403 + owner_member_cannot_set_boot_device: path: '/v1/nodes/{owner_node_ident}/management/boot_device' method: put @@ -708,6 +890,13 @@ owner_admin_can_get_boot_device: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_get_boot_device: + path: '/v1/nodes/{owner_node_ident}/management/boot_device' + method: get + headers: *owner_manager_headers + assert_status: 503 + +# FIXME(TheJulia): This should be lessee admin headers below. lessee_admin_cannot_get_boot_device: path: '/v1/nodes/{lessee_node_ident}/management/boot_device' method: get @@ -750,6 +939,12 @@ owner_admin_can_get_supported_boot_devices: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_get_supported_boot_devices: + path: '/v1/nodes/{owner_node_ident}/management/boot_device/supported' + method: get + headers: *owner_manager_headers + assert_status: 503 + owner_member_cannot_get_supported_boot_devices: path: '/v1/nodes/{owner_node_ident}/management/boot_device/supported' method: get @@ -762,6 +957,12 @@ lessee_admin_cannot_get_supported_boot_devices: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_get_supported_boot_devices: + path: '/v1/nodes/{lessee_node_ident}/management/boot_device/supported' + method: get + headers: *lessee_manager_headers + assert_status: 403 + third_party_admin_cannot_get_supported_boot_devices: path: '/v1/nodes/{owner_node_ident}/management/boot_device/supported' method: get @@ -777,6 +978,13 @@ owner_admin_can_send_non_masking_interrupt: body: {} assert_status: 503 +owner_manager_can_send_non_masking_interrupt: + path: '/v1/nodes/{owner_node_ident}/management/inject_nmi' + method: put + headers: *owner_manager_headers + body: {} + assert_status: 503 + lessee_admin_cannot_send_non_masking_interrupt: path: '/v1/nodes/{lessee_node_ident}/management/inject_nmi' method: put @@ -784,6 +992,13 @@ lessee_admin_cannot_send_non_masking_interrupt: body: {} assert_status: 403 +lessee_manager_cannot_send_non_masking_interrupt: + path: '/v1/nodes/{lessee_node_ident}/management/inject_nmi' + method: put + headers: *lessee_manager_headers + body: {} + assert_status: 403 + third_party_admin_cannot_send_non_masking_interrupt: path: '/v1/nodes/{node_ident}/management/inject_nmi' method: put @@ -821,6 +1036,13 @@ owner_admin_can_put_power_state_change: target: "power on" assert_status: 503 +owner_manager_can_put_power_state_change: + path: '/v1/nodes/{owner_node_ident}/states/power' + method: put + headers: *owner_manager_headers + body: *power_body + assert_status: 503 + lessee_admin_can_put_power_state_change: path: '/v1/nodes/{lessee_node_ident}/states/power' method: put @@ -828,6 +1050,13 @@ lessee_admin_can_put_power_state_change: body: *power_body assert_status: 503 +lessee_manager_can_put_power_state_change: + path: '/v1/nodes/{lessee_node_ident}/states/power' + method: put + headers: *lessee_manager_headers + body: *power_body + assert_status: 503 + owner_member_can_put_power_state_change: path: '/v1/nodes/{owner_node_ident}/states/power' method: put @@ -873,6 +1102,13 @@ owner_admin_can_put_boot_mode_state_change: target: "uefi" assert_status: 503 +owner_manager_can_put_boot_mode_state_change: + path: '/v1/nodes/{owner_node_ident}/states/boot_mode' + method: put + headers: *owner_manager_headers + body: *boot_mode_body + assert_status: 503 + lessee_admin_can_put_boot_mode_state_change: path: '/v1/nodes/{lessee_node_ident}/states/boot_mode' method: put @@ -880,6 +1116,13 @@ lessee_admin_can_put_boot_mode_state_change: body: *boot_mode_body assert_status: 503 +lessee_manager_can_put_boot_mode_state_change: + path: '/v1/nodes/{lessee_node_ident}/states/boot_mode' + method: put + headers: *lessee_manager_headers + body: *boot_mode_body + assert_status: 503 + owner_member_can_put_boot_mode_state_change: path: '/v1/nodes/{owner_node_ident}/states/boot_mode' method: put @@ -925,6 +1168,13 @@ owner_admin_can_put_secure_boot_state_change: target: "true" assert_status: 503 +owner_manager_can_put_secure_boot_state_change: + path: '/v1/nodes/{owner_node_ident}/states/secure_boot' + method: put + headers: *owner_manager_headers + body: *secure_boot_body + assert_status: 503 + lessee_admin_can_put_secure_boot_state_change: path: '/v1/nodes/{lessee_node_ident}/states/secure_boot' method: put @@ -932,6 +1182,13 @@ lessee_admin_can_put_secure_boot_state_change: body: *secure_boot_body assert_status: 503 +lessee_manager_can_put_secure_boot_state_change: + path: '/v1/nodes/{lessee_node_ident}/states/secure_boot' + method: put + headers: *lessee_manager_headers + body: *secure_boot_body + assert_status: 503 + owner_member_can_put_secure_boot_state_change: path: '/v1/nodes/{owner_node_ident}/states/secure_boot' method: put @@ -977,6 +1234,13 @@ owner_admin_can_change_provision_state: target: deploy assert_status: 503 +owner_manager_can_change_provision_state: + path: '/v1/nodes/{owner_node_ident}/states/provision' + method: put + headers: *owner_manager_headers + body: *provision_body + assert_status: 503 + owner_member_can_change_provision_state: path: '/v1/nodes/{owner_node_ident}/states/provision' method: put @@ -991,6 +1255,14 @@ lessee_admin_can_change_provision_state: body: *provision_body assert_status: 503 +lessee_manager_can_change_provision_state: + path: '/v1/nodes/{lessee_node_ident}/states/provision' + method: put + headers: *lessee_manager_headers + body: *provision_body + assert_status: 503 + + lessee_member_cannot_change_provision_state: path: '/v1/nodes/{lessee_node_ident}/states/provision' method: put @@ -1019,6 +1291,13 @@ owner_admin_can_set_raid_config: raid_level: 1 assert_status: 503 +owner_manager_can_set_raid_config: + path: '/v1/nodes/{owner_node_ident}/states/raid' + method: put + headers: *owner_manager_headers + body: *raid_body + assert_status: 503 + lessee_admin_cannot_set_raid_config: path: '/v1/nodes/{lessee_node_ident}/states/raid' method: put @@ -1026,6 +1305,13 @@ lessee_admin_cannot_set_raid_config: body: *raid_body assert_status: 403 +lessee_manager_cannot_set_raid_config: + path: '/v1/nodes/{lessee_node_ident}/states/raid' + method: put + headers: *lessee_manager_headers + body: *raid_body + assert_status: 403 + owner_member_can_set_raid_config: path: '/v1/nodes/{lessee_node_ident}/states/raid' method: put @@ -1055,12 +1341,24 @@ owner_admin_can_get_console: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_get_console: + path: '/v1/nodes/{owner_node_ident}/states/console' + method: get + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_cannot_get_console: path: '/v1/nodes/{lessee_node_ident}/states/console' method: get headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_get_console: + path: '/v1/nodes/{lessee_node_ident}/states/console' + method: get + headers: *lessee_manager_headers + assert_status: 403 + owner_member_can_get_console: path: '/v1/nodes/{owner_node_ident}/states/console' method: get @@ -1099,6 +1397,13 @@ owner_admin_can_set_console: enabled: true assert_status: 503 +owner_manager_can_set_console: + path: '/v1/nodes/{owner_node_ident}/states/console' + method: put + headers: *owner_manager_headers + body: *console_body_put + assert_status: 503 + lessee_admin_cannot_set_console: path: '/v1/nodes/{lessee_node_ident}/states/console' method: put @@ -1106,6 +1411,13 @@ lessee_admin_cannot_set_console: body: *console_body_put assert_status: 403 +lessee_manager_cannot_set_console: + path: '/v1/nodes/{lessee_node_ident}/states/console' + method: put + headers: *lessee_manager_headers + body: *console_body_put + assert_status: 403 + owner_member_can_set_console: path: '/v1/nodes/{owner_node_ident}/states/console' method: put @@ -1132,6 +1444,12 @@ owner_admin_cannot_get_vendor_passthru_methods: headers: *owner_admin_headers assert_status: 403 +owner_manager_cannot_get_vendor_passthru_methods: + path: '/v1/nodes/{owner_node_ident}/vendor_passthru/methods' + method: get + headers: *owner_manager_headers + assert_status: 403 + owner_member_cannot_get_vendor_passthru_methods: path: '/v1/nodes/{owner_node_ident}/vendor_passthru/methods' method: get @@ -1150,6 +1468,12 @@ lessee_admin_cannot_get_vendor_passthru_methods: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_get_vendor_passthru_methods: + path: '/v1/nodes/{lessee_node_ident}/vendor_passthru/methods' + method: get + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_get_vendor_passthru_methods: path: '/v1/nodes/{lessee_node_ident}/vendor_passthru/methods' method: get @@ -1169,6 +1493,12 @@ owner_admin_cannot_get_vendor_passthru: headers: *owner_admin_headers assert_status: 403 +owner_manager_cannot_get_vendor_passthru: + path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' + method: get + headers: *owner_manager_headers + assert_status: 403 + owner_member_cannot_get_vendor_passthru: path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' method: get @@ -1187,6 +1517,12 @@ lessee_admin_cannot_get_vendor_passthru: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_get_vendor_passthru: + path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' + method: get + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_get_vendor_passthru: path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' method: get @@ -1207,6 +1543,12 @@ owner_admin_cannot_post_vendor_passthru: headers: *owner_admin_headers assert_status: 403 +owner_manager_cannot_post_vendor_passthru: + path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' + method: post + headers: *owner_manager_headers + assert_status: 403 + owner_member_cannot_post_vendor_passthru: path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' method: post @@ -1225,6 +1567,12 @@ lessee_admin_cannot_post_vendor_passthru: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_post_vendor_passthru: + path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' + method: post + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_post_vendor_passthru: path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' method: post @@ -1245,6 +1593,12 @@ owner_admin_cannot_put_vendor_passthru: headers: *owner_admin_headers assert_status: 403 +owner_manager_cannot_put_vendor_passthru: + path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' + method: put + headers: *owner_manager_headers + assert_status: 403 + owner_member_cannot_put_vendor_passthru: path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' method: put @@ -1263,6 +1617,12 @@ lessee_admin_cannot_put_vendor_passthru: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_put_vendor_passthru: + path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' + method: put + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_put_vendor_passthru: path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' method: put @@ -1283,6 +1643,12 @@ owner_admin_cannot_delete_vendor_passthru: headers: *owner_admin_headers assert_status: 403 +owner_manager_cannot_delete_vendor_passthru: + path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' + method: delete + headers: *owner_manager_headers + assert_status: 403 + owner_member_cannot_delete_vendor_passthru: path: '/v1/nodes/{owner_node_ident}/vendor_passthru?method=test' method: delete @@ -1301,6 +1667,12 @@ lessee_admin_cannot_delete_vendor_passthru: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_delete_vendor_passthru: + path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' + method: delete + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_delete_vendor_passthru: path: '/v1/nodes/{lessee_node_ident}/vendor_passthru?method=test' method: delete @@ -1343,6 +1715,13 @@ owner_admin_can_put_traits: - CUSTOM_TRAIT1 - HW_CPU_X86_VMX +owner_manager_can_put_traits: + path: '/v1/nodes/{owner_node_ident}/traits' + method: put + headers: *owner_manager_headers + assert_status: 503 + body: *traits_body + owner_member_cannot_put_traits: path: '/v1/nodes/{owner_node_ident}/traits' method: put @@ -1357,6 +1736,13 @@ lessee_admin_cannot_put_traits: assert_status: 403 body: *traits_body +lessee_manager_cannot_put_traits: + path: '/v1/nodes/{lessee_node_ident}/traits' + method: put + headers: *lessee_manager_headers + assert_status: 403 + body: *traits_body + lessee_member_cannot_put_traits: path: '/v1/nodes/{lessee_node_ident}/traits' method: put @@ -1377,6 +1763,12 @@ owner_admin_can_delete_traits: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_delete_traits: + path: '/v1/nodes/{owner_node_ident}/traits/{trait}' + method: delete + headers: *owner_manager_headers + assert_status: 503 + owner_member_cannot_delete_traits: path: '/v1/nodes/{owner_node_ident}/traits/{trait}' method: delete @@ -1389,6 +1781,12 @@ lessee_admin_cannot_delete_traits: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_delete_traits: + path: '/v1/nodes/{lessee_node_ident}/traits/{trait}' + method: delete + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_delete_traits: path: '/v1/nodes/{lessee_node_ident}/traits/{trait}' method: delete @@ -1407,6 +1805,12 @@ owner_admin_can_put_custom_traits: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_put_custom_traits: + path: '/v1/nodes/{owner_node_ident}/traits/CUSTOM_TRAIT2' + method: put + headers: *owner_manager_headers + assert_status: 503 + owner_member_cannot_put_custom_traits: path: '/v1/nodes/{owner_node_ident}/traits/CUSTOM_TRAIT2' method: put @@ -1419,6 +1823,12 @@ lessee_admin_cannot_put_custom_traits: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_put_custom_traits: + path: '/v1/nodes/{lessee_node_ident}/traits/CUSTOM_TRAIT2' + method: put + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_put_custom_traits: path: '/v1/nodes/{lessee_node_ident}/traits/CUSTOM_TRAIT2' method: put @@ -1463,6 +1873,13 @@ owner_admin_can_post_vifs: body: &vif_body id: ee21d58f-5de2-4956-85ff-33935ea1ca00 +owner_manager_can_post_vifs: + path: '/v1/nodes/{owner_node_ident}/vifs' + method: post + headers: *owner_manager_headers + assert_status: 503 + body: *vif_body + lessee_admin_can_post_vifs: path: '/v1/nodes/{lessee_node_ident}/vifs' method: post @@ -1470,6 +1887,13 @@ lessee_admin_can_post_vifs: assert_status: 503 body: *vif_body +lessee_manager_can_post_vifs: + path: '/v1/nodes/{lessee_node_ident}/vifs' + method: post + headers: *lessee_manager_headers + assert_status: 503 + body: *vif_body + owner_member_can_post_vifs: path: '/v1/nodes/{owner_node_ident}/vifs' method: post @@ -1511,12 +1935,24 @@ owner_admin_delete_vifs: headers: *owner_admin_headers assert_status: 503 +owner_manager_delete_vifs: + path: '/v1/nodes/{owner_node_ident}/vifs/{vif_ident}' + method: delete + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_can_delete_vifs: path: '/v1/nodes/{lessee_node_ident}/vifs/{vif_ident}' method: delete headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_delete_vifs: + path: '/v1/nodes/{lessee_node_ident}/vifs/{vif_ident}' + method: delete + headers: *lessee_manager_headers + assert_status: 503 + owner_member_can_delete_vifs: path: '/v1/nodes/{owner_node_ident}/vifs/{vif_ident}' method: delete @@ -1642,6 +2078,13 @@ owner_admin_can_add_portgroup: node_uuid: 1ab63b9e-66d7-4cd7-8618-dddd0f9f7881 assert_status: 201 +owner_manager_can_add_portgroup: + path: '/v1/portgroups' + method: post + headers: *owner_manager_headers + body: *owner_portgroup_body + assert_status: 201 + owner_member_cannot_add_portgroup: path: '/v1/portgroups' method: post @@ -1657,6 +2100,13 @@ lessee_admin_cannot_add_portgroup: node_uuid: 38d5abed-c585-4fce-a57e-a2ffc2a2ec6f assert_status: 403 +lessee_manager_cannot_add_portgroup: + path: '/v1/portgroups' + method: post + headers: *lessee_manager_headers + body: *lessee_portgroup_body + assert_status: 403 + # TODO, likely will need separate port/port groups established for the tests lessee_member_cannot_add_portgroup: @@ -1683,6 +2133,13 @@ owner_admin_can_modify_portgroup: value: {'test': 'testing'} assert_status: 503 +owner_manager_can_modify_portgroup: + path: '/v1/portgroups/{owner_portgroup_ident}' + method: patch + headers: *owner_manager_headers + body: *portgroup_patch_body + assert_status: 503 + owner_member_cannot_modify_portgroup: path: '/v1/portgroups/{owner_portgroup_ident}' method: patch @@ -1697,6 +2154,13 @@ lessee_admin_cannot_modify_portgroup: body: *portgroup_patch_body assert_status: 403 +lessee_manager_cannot_modify_portgroup: + path: '/v1/portgroups/{lessee_portgroup_ident}' + method: patch + headers: *lessee_manager_headers + body: *portgroup_patch_body + assert_status: 403 + lessee_member_cannot_modify_portgroup: path: '/v1/portgroups/{lessee_portgroup_ident}' method: patch @@ -1717,6 +2181,12 @@ owner_admin_can_delete_portgroup: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_delete_portgroup: + path: '/v1/portgroups/{owner_portgroup_ident}' + method: delete + headers: *owner_manager_headers + assert_status: 503 + owner_member_cannot_delete_portgroup: path: '/v1/portgroups/{owner_portgroup_ident}' method: delete @@ -1729,6 +2199,12 @@ lessee_admin_cannot_delete_portgroup: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_delete_portgroup: + path: '/v1/portgroups/{lessee_portgroup_ident}' + method: delete + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_delete_portgroup: path: '/v1/portgroups/{lessee_portgroup_ident}' method: delete @@ -1819,15 +2295,29 @@ owner_admin_can_add_ports: address: 00:01:02:03:04:05 assert_status: 503 +owner_manager_can_add_ports: + path: '/v1/ports' + method: post + headers: *owner_manager_headers + body: *owner_port_body + assert_status: 503 + owner_admin_cannot_add_ports_to_other_nodes: path: '/v1/ports' method: post headers: *owner_admin_headers - body: + body: &other_node_add_port_body node_uuid: 573208e5-cd41-4e26-8f06-ef44022b3793 address: 09:01:02:03:04:09 assert_status: 403 +owner_manager_cannot_add_ports_to_other_nodes: + path: '/v1/ports' + method: post + headers: *owner_manager_headers + body: *other_node_add_port_body + assert_status: 403 + owner_member_cannot_add_port: path: '/v1/ports' method: post @@ -1844,6 +2334,13 @@ lessee_admin_cannot_add_port: address: 00:01:02:03:04:05 assert_status: 403 +lessee_manager_cannot_add_port: + path: '/v1/ports' + method: post + headers: *lessee_manager_headers + body: *lessee_port_body + assert_status: 403 + lessee_member_cannot_add_port: path: '/v1/ports' method: post @@ -1868,6 +2365,13 @@ owner_admin_can_modify_port: value: {'test': 'testing'} assert_status: 503 +owner_manager_can_modify_port: + path: '/v1/ports/{owner_port_ident}' + method: patch + headers: *owner_manager_headers + body: *port_patch_body + assert_status: 503 + owner_member_cannot_modify_port: path: '/v1/ports/{owner_port_ident}' method: patch @@ -1882,6 +2386,13 @@ lessee_admin_cannot_modify_port: body: *port_patch_body assert_status: 403 +lessee_manager_cannot_modify_port: + path: '/v1/ports/{lessee_port_ident}' + method: patch + headers: *lessee_manager_headers + body: *port_patch_body + assert_status: 403 + lessee_member_cannot_modify_port: path: '/v1/ports/{lessee_port_ident}' method: patch @@ -1902,6 +2413,12 @@ owner_admin_can_delete_port: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_delete_port: + path: '/v1/ports/{owner_port_ident}' + method: delete + headers: *owner_manager_headers + assert_status: 503 + owner_member_cannot_delete_port: path: '/v1/ports/{owner_port_ident}' method: delete @@ -1914,6 +2431,12 @@ lessee_admin_cannot_delete_port: headers: *lessee_admin_headers assert_status: 403 +lessee_manager_cannot_delete_port: + path: '/v1/ports/{lessee_port_ident}' + method: delete + headers: *lessee_manager_headers + assert_status: 403 + lessee_member_cannot_delete_port: path: '/v1/ports/{lessee_port_ident}' method: delete @@ -2013,6 +2536,13 @@ owner_admin_can_post_volume_connector: type: ip connector_id: 192.168.1.100 +owner_manager_can_post_volume_connector: + path: '/v1/volume/connectors' + method: post + headers: *owner_manager_headers + assert_status: 201 + body: *volume_connector_body + lessee_admin_cannot_post_volume_connector: path: '/v1/volume/connectors' method: post @@ -2020,6 +2550,13 @@ lessee_admin_cannot_post_volume_connector: assert_status: 403 body: *volume_connector_body +lessee_manager_cannot_post_volume_connector: + path: '/v1/volume/connectors' + method: post + headers: *lessee_manager_headers + assert_status: 403 + body: *volume_connector_body + third_party_admin_cannot_post_volume_connector: path: '/v1/volume/connectors' method: post @@ -2062,6 +2599,14 @@ owner_admin_can_patch_volume_connectors: body: *connector_patch_body assert_status: 503 +owner_manager_can_patch_volume_connectors: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: patch + headers: *owner_manager_headers + body: *connector_patch_body + assert_status: 503 + +# FIXME This test is wrong, name is updated lessee_admin_cannot_patch_volume_connectors: path: '/v1/volume/connectors/{volume_connector_ident}' method: patch @@ -2069,6 +2614,13 @@ lessee_admin_cannot_patch_volume_connectors: body: *connector_patch_body assert_status: 503 +lessee_manager_can_patch_volume_connectors: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: patch + headers: *owner_manager_headers + body: *connector_patch_body + assert_status: 503 + owner_member_can_patch_volume_connectors: path: '/v1/volume/connectors/{volume_connector_ident}' method: patch @@ -2096,12 +2648,24 @@ owner_admin_can_delete_volume_connectors: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_delete_volume_connectors: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: delete + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_can_delete_volume_connectors: path: '/v1/volume/connectors/{volume_connector_ident}' method: delete headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_delete_volume_connectors: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: delete + headers: *lessee_manager_headers + assert_status: 503 + third_party_admin_cannot_delete_volume_connector: path: '/v1/volume/connectors/{volume_connector_ident}' method: delete @@ -2168,6 +2732,17 @@ owner_admin_create_volume_target: boot_index: 2 volume_id: 'test-id' +owner_manager_create_volume_target: + path: '/v1/volume/targets' + method: post + headers: *owner_manager_headers + assert_status: 201 + body: + node_uuid: 1ab63b9e-66d7-4cd7-8618-dddd0f9f7881 + volume_type: iscsi + boot_index: 3 + volume_id: 'test-id' + lessee_admin_create_volume_target: path: '/v1/volume/targets' method: post @@ -2179,6 +2754,17 @@ lessee_admin_create_volume_target: boot_index: 2 volume_id: 'test-id2' +lessee_manager_create_volume_target: + path: '/v1/volume/targets' + method: post + headers: *owner_manager_headers + assert_status: 201 + body: + node_uuid: 38d5abed-c585-4fce-a57e-a2ffc2a2ec6f + volume_type: iscsi + boot_index: 2 + volume_id: 'test-id3' + third_party_admin_cannot_create_volume_target: path: '/v1/volume/targets' method: post @@ -2203,6 +2789,13 @@ lessee_admin_can_patch_volume_target: headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_patch_volume_target: + path: '/v1/volume/targets/{volume_target_ident}' + method: patch + body: *volume_target_patch + headers: *lessee_manager_headers + assert_status: 503 + lessee_member_cannot_patch_volume_target: path: '/v1/volume/targets/{volume_target_ident}' method: patch @@ -2223,12 +2816,24 @@ owner_admin_can_delete_volume_target: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_delete_volume_target: + path: '/v1/volume/targets/{volume_target_ident}' + method: delete + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_can_delete_volume_target: path: '/v1/volume/targets/{volume_target_ident}' method: delete headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_delete_volume_target: + path: '/v1/volume/targets/{volume_target_ident}' + method: delete + headers: *lessee_manager_headers + assert_status: 503 + owner_member_cannot_delete_volume_target: path: '/v1/volume/targets/{volume_target_ident}' method: delete @@ -2413,12 +3018,24 @@ owner_admin_can_delete_their_allocation: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_delete_their_allocation: + path: '/v1/allocations/{owner_allocation}' + method: delete + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_can_delete_their_allocation: path: '/v1/allocations/{lessee_allocation}' method: delete headers: *lessee_admin_headers assert_status: 503 +lessee_manager_can_delete_their_allocation: + path: '/v1/allocations/{lessee_allocation}' + method: delete + headers: *lessee_manager_headers + assert_status: 503 + owner_member_can_delete_their_allocation: path: '/v1/allocations/{owner_allocation}' method: delete @@ -2503,6 +3120,15 @@ owner_admin_can_create_allocation_with_their_uuid: node: 1ab63b9e-66d7-4cd7-8618-dddd0f9f7881 assert_status: 503 +owner_manager_can_create_allocation_with_their_uuid: + path: '/v1/allocations' + method: post + headers: *owner_manager_headers + body: + resource_class: CUSTOM_TEST + node: 1ab63b9e-66d7-4cd7-8618-dddd0f9f7881 + assert_status: 503 + third_party_admin_cannot_read_an_allocation: path: '/v1/allocations/{lessee_allocation}' method: get @@ -2551,12 +3177,24 @@ owner_admin_can_delete_allocation: headers: *owner_admin_headers assert_status: 503 +owner_manager_can_delete_allocation: + path: '/v1/nodes/{owner_node_ident}/allocation' + method: delete + headers: *owner_manager_headers + assert_status: 503 + lessee_admin_can_delete_allocation: path: '/v1/nodes/{allocated_node_ident}/allocation' method: delete headers: *lessee_admin_headers assert_status: 503 +lessee_manager_not_delete_allocation: + path: '/v1/nodes/{allocated_node_ident}/allocation' + method: delete + headers: *lessee_manager_headers + assert_status: 503 + third_party_admin_cannot_delete_allocation: path: '/v1/nodes/{allocated_node_ident}/allocation' method: delete diff --git a/releasenotes/notes/add-rbac-project-manager-role-7ffc52f78ff93432.yaml b/releasenotes/notes/add-rbac-project-manager-role-7ffc52f78ff93432.yaml new file mode 100644 index 0000000000..708aa6c993 --- /dev/null +++ b/releasenotes/notes/add-rbac-project-manager-role-7ffc52f78ff93432.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Adds a default ``project`` scoped ``manager`` role to the RBAC model. + In the ironic model, access is generally explicitly delegated, and such + the ``manager`` role is presently equivelent to project scoped ``admin`` + role, however future delineation may occur as the new features and + capabilities are added.