Merge "Disable legacy RBAC policy by default."

This commit is contained in:
Zuul 2024-01-23 21:58:26 +00:00 committed by Gerrit Code Review
commit b256551b19
7 changed files with 109 additions and 22 deletions

View File

@ -183,10 +183,8 @@ if [[ "$hostdomain" =~ "rax" ]] || [[ "$hostdomain" =~ "iweb" ]]; then
fi fi
# Oslo Policy, as of Wallaby defaults to not enforcing request scope # Oslo Policy enforcement for Scope and new policy enforcement.
# against requestors. This is anticipated to change in Xena or after IRONIC_ENFORCE_SCOPE=$(trueorfalse True IRONIC_ENFORCE_SCOPE)
# the Xena release of OpenStack.
IRONIC_ENFORCE_SCOPE=$(trueorfalse False IRONIC_ENFORCE_SCOPE)
if [[ "$IRONIC_ENFORCE_SCOPE" == "True" ]]; then if [[ "$IRONIC_ENFORCE_SCOPE" == "True" ]]; then
IRONIC_OS_CLOUD=devstack-system-admin IRONIC_OS_CLOUD=devstack-system-admin
@ -201,6 +199,12 @@ fi
# we need this variable for Xena and possibly Wallaby grenade. # we need this variable for Xena and possibly Wallaby grenade.
OS_CLOUD=${OS_CLOUD:-devstack-admin} OS_CLOUD=${OS_CLOUD:-devstack-admin}
# If the node owner needs to be set on nodes, for example, jobs
# such as metalsmith have hardcoded OS_CLOUD variables which mean
# an ironic in a full system scope enforced mode can't find nodes
# for an allocation as suddenly the owner is applied.
IRONIC_SET_NODE_OWNER=${IRONIC_SET_NODE_OWNER:-}
# Versions and command line for API client # Versions and command line for API client
IRONIC_DEFAULT_API_VERSION=${IRONIC_DEFAULT_API_VERSION:-} IRONIC_DEFAULT_API_VERSION=${IRONIC_DEFAULT_API_VERSION:-}
IRONIC_CMD="openstack --os-cloud $IRONIC_OS_CLOUD baremetal" IRONIC_CMD="openstack --os-cloud $IRONIC_OS_CLOUD baremetal"
@ -1528,9 +1532,9 @@ function configure_ironic {
if [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" == "" ]] || [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" == "keystone" ]]; then if [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" == "" ]] || [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" == "keystone" ]]; then
configure_client_for json_rpc configure_client_for json_rpc
fi fi
if [[ "$IRONIC_ENFORCE_SCOPE" == "True" ]]; then if [[ "$IRONIC_ENFORCE_SCOPE" == "False" ]]; then
iniset $IRONIC_CONF_FILE oslo_policy enforce_scope true iniset $IRONIC_CONF_FILE oslo_policy enforce_scope false
iniset $IRONIC_CONF_FILE oslo_policy enforce_new_defaults true iniset $IRONIC_CONF_FILE oslo_policy enforce_new_defaults false
fi fi
# Set fast track options # Set fast track options
@ -1856,11 +1860,11 @@ function create_ironic_cache_dir {
# create_ironic_accounts() - Set up common required ironic accounts # create_ironic_accounts() - Set up common required ironic accounts
# Project User Roles # Project User Roles
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# service ironic admin # service ironic admin
# service nova baremetal_admin # service nova baremetal_admin # Legacy, Pre-SRBAC effort
# demo demo baremetal_observer # demo demo baremetal_observer # Legacy, Pre-SRBAC effort
function create_ironic_accounts { function create_ironic_accounts {
if [[ "$ENABLED_SERVICES" =~ "ir-api" && "$ENABLED_SERVICES" =~ "key" ]]; then if [[ "$ENABLED_SERVICES" =~ "ir-api" && "$ENABLED_SERVICES" =~ "key" ]]; then
# Define service and endpoints in Keystone # Define service and endpoints in Keystone
@ -1875,6 +1879,7 @@ function create_ironic_accounts {
create_service_user "ironic" "admin" create_service_user "ironic" "admin"
# Create additional bare metal tenant and roles # Create additional bare metal tenant and roles
# TODO(TheJulia): Remove when we remove the legacy RBAC policies.
get_or_create_role baremetal_admin get_or_create_role baremetal_admin
get_or_create_role baremetal_observer get_or_create_role baremetal_observer
if is_service_enabled nova; then if is_service_enabled nova; then
@ -1971,6 +1976,14 @@ function start_ironic_api {
function start_ironic_conductor { function start_ironic_conductor {
run_process ir-cond "$IRONIC_BIN_DIR/ironic-conductor --config-file=$IRONIC_CONF_FILE" run_process ir-cond "$IRONIC_BIN_DIR/ironic-conductor --config-file=$IRONIC_CONF_FILE"
# Unset variables which we shouldn't have... Grenade resets these :\
# in grenade/projects/60_nova/resources.sh as part of the resource
# creation tests.
unset OS_TENANT_NAME
unset OS_USERNAME
unset OS_PROJECT_NAME
unset OS_PASSWORD
# Wait up to 30 seconds for ironic-conductor to start and register itself # Wait up to 30 seconds for ironic-conductor to start and register itself
local attempt local attempt
local max_attempts=7 local max_attempts=7
@ -2280,10 +2293,12 @@ function wait_for_nova_resources {
local resource_class=${IRONIC_DEFAULT_RESOURCE_CLASS^^} local resource_class=${IRONIC_DEFAULT_RESOURCE_CLASS^^}
# TODO(dtantsur): switch to Placement OSC plugin, once it exists # TODO(dtantsur): switch to Placement OSC plugin, once it exists
# Normally, we would want to use IRONIC_OS_CLOUD, but tokens need to be
# scoped. In this case, devstack-admin is the appropriate os-cloud to use.
local token local token
token=$(openstack --os-cloud $IRONIC_OS_CLOUD token issue -f value -c id) token=$(openstack --os-cloud devstack-admin token issue -f value -c id)
local endpoint local endpoint
endpoint=$(openstack --os-cloud $IRONIC_OS_CLOUD endpoint list --service placement --interface public -f value -c URL) endpoint=$(openstack --os-cloud devstack-admin endpoint list --service placement --interface public -f value -c URL)
die_if_not_set $LINENO endpoint "Cannot find Placement API endpoint" die_if_not_set $LINENO endpoint "Cannot find Placement API endpoint"
local i local i
@ -2604,6 +2619,14 @@ function enroll_nodes {
$IRONIC_CMD node add trait $node_id $IRONIC_DEFAULT_TRAITS $IRONIC_CMD node add trait $node_id $IRONIC_DEFAULT_TRAITS
fi fi
if [[ -n "$IRONIC_SET_NODE_OWNER" ]]; then
# If set, apply an owner project project ID to the node,
# to allow tools like metalsmith to be abel to view and
# allocate the node.
owner_project_id=$(openstack project show $IRONIC_SET_NODE_OWNER -f value -c id)
$IRONIC_CMD node set --owner $owner_project_id $node_id
fi
$IRONIC_CMD node manage $node_id --wait $IRONIC_MANAGE_TIMEOUT || \ $IRONIC_CMD node manage $node_id --wait $IRONIC_MANAGE_TIMEOUT || \
die $LINENO "Node did not reach manageable state in $IRONIC_MANAGE_TIMEOUT seconds" die $LINENO "Node did not reach manageable state in $IRONIC_MANAGE_TIMEOUT seconds"

View File

@ -144,7 +144,7 @@ ensure_services_started $ensure_started
# internal tag, that was assigned to network will be the same. As result we need to update # internal tag, that was assigned to network will be the same. As result we need to update
# tag on link between br-int and brbm to new value after restart. # tag on link between br-int and brbm to new value after restart.
if [[ -z "${IRONIC_PROVISION_NETWORK_NAME}" ]]; then if [[ -z "${IRONIC_PROVISION_NETWORK_NAME}" ]]; then
net_id=$(openstack network show ironic_grenade -f value -c id) net_id=$(openstack --os-cloud devstack-admin network show ironic_grenade -f value -c id)
create_ovs_taps $net_id create_ovs_taps $net_id
fi fi

View File

@ -36,7 +36,9 @@ LOG = log.getLogger(__name__)
# once oslo_policy change the default value to 'policy.yaml'. # once oslo_policy change the default value to 'policy.yaml'.
# https://github.com/openstack/oslo.policy/blob/a626ad12fe5a3abd49d70e3e5b95589d279ab578/oslo_policy/opts.py#L49 # https://github.com/openstack/oslo.policy/blob/a626ad12fe5a3abd49d70e3e5b95589d279ab578/oslo_policy/opts.py#L49
DEFAULT_POLICY_FILE = 'policy.yaml' DEFAULT_POLICY_FILE = 'policy.yaml'
opts.set_defaults(cfg.CONF, DEFAULT_POLICY_FILE) opts.set_defaults(cfg.CONF, DEFAULT_POLICY_FILE,
enforce_scope=True,
enforce_new_defaults=True)
# Generic policy check string for system administrators. These are the people # Generic policy check string for system administrators. These are the people
# who need the highest level of authorization to operate the deployment. # who need the highest level of authorization to operate the deployment.

View File

@ -13,13 +13,13 @@ unauthenticated_user_cannot_get_node:
path: &node_path '/v1/nodes/{node_uuid}' path: &node_path '/v1/nodes/{node_uuid}'
assert_status: 404 assert_status: 404
# With new defaults, by default admin rights don't let you see
# everything without rights. Since this is default/basic behavior
# it doesn't make sense to mock it out.
project_admin_can_get_node: project_admin_can_get_node:
path: *node_path path: *node_path
headers: *project_admin_headers headers: *project_admin_headers
assert_dict_contains: assert_status: 404
uuid: '{node_uuid}'
driver: 'fake-hardware'
assert_status: 200
project_member_cannot_get_node: project_member_cannot_get_node:
path: *node_path path: *node_path

View File

@ -174,7 +174,7 @@ class PolicyInCodeTestCase(base.TestCase):
}]), }]),
dict( dict(
rule='baremetal:node:get', rule='baremetal:node:get',
check=True, check=False,
targets=[], targets=[],
creds=[{ creds=[{
'roles': ['baremetal_observer'], 'roles': ['baremetal_observer'],
@ -188,7 +188,7 @@ class PolicyInCodeTestCase(base.TestCase):
creds=[{'roles': ['generic_user'], 'tenant': 'demo'}]), creds=[{'roles': ['generic_user'], 'tenant': 'demo'}]),
dict( dict(
rule='baremetal:node:create', rule='baremetal:node:create',
check=True, check=False,
targets=[], targets=[],
creds=[{ creds=[{
'roles': ['baremetal_admin'], 'roles': ['baremetal_admin'],

View File

@ -0,0 +1,57 @@
---
upgrade:
- |
The Ironic service API Role Based Access Control policy has been updated
to disable the legacy RBAC policy by default. The effect of this is that
deprecated legacy roles of ``baremetal_admin`` and ``baremetal_observer``
are no longer functional by default, and policy checks may prevent actions
such as viewing nodes when access rights do not exist by default.
This change is a result of the new policy which was introduced as part of
`Secure Role Based Access Control`_ effort along with the
`Consistent and Secure RBAC`_ community goal and the underlying
``[oslo_policy] enforce_scope`` and ``[oslo_policy] enforce_new_defaults``
settings being changed to ``True``.
The Ironic project believes most operators will observe no direct impact
from this change, unless they are specifically running legacy access
configurations utilizing the legacy roles for access.
Operators which are suddenly unable to list or deploy nodes may have
a misconfiguration in credentials, or need to allow the user's project
the ability to view and act upon the node through the node ``owner`` or
``lessee`` fields. By default, the `Ironic API policy`_ permits
authenticated requests with a ``system`` scoped token to access
all resources, and applies a finer grained access model across the API
for project scoped users.
Ironic users who have not already changed their ``nova-compute`` service
settings for connecting to Ironic may also have issues scheduling
Bare Metal nodes. Use of a ``system`` scoped user is available, by
setting ``[ironic] system_scope`` to a value of ``all`` in your
nova-compute service configuration, which can be done independently
of other services, as long as the credentials supplied are also valid
with Keystone for system scoped authentication.
Heat users which encounter any issues after this upgrade, should check
their user's roles. Heat's execution and model is entirely project scoped,
which means users will need to have access granted through the ``owner``
or ``lessee`` field to work with a node.
Operators wishing to revert to the old policy configuration may do so
by setting the following values in ``ironic.conf``.::
[oslo_policy]
enforce_new_defaults=False
enforce_scope=False
Operators who revert the configuration are encourated to make the
necessary changes to their configuration, as the legacy RBAC policy
will be removed at some point in the future in alignment with
`2024.1-Release Timeline`_. Failure to do so will
may force operators to craft custom policy override configuration.
.. _`Secure Role Based Access Control`: https://specs.openstack.org/openstack/ironic-specs/specs/17.0/secure-rbac.html
.. _`Ironic API Policy`: https://docs.openstack.org/ironic/latest/configuration/sample-policy.html
.. _`Consistent and Secure RBAC`: https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html
.. _`2024.1-Release Timeline`: https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#id3

View File

@ -380,7 +380,9 @@
IRONIC_TEMPEST_WHOLE_DISK_IMAGE: True IRONIC_TEMPEST_WHOLE_DISK_IMAGE: True
IRONIC_VM_EPHEMERAL_DISK: 0 IRONIC_VM_EPHEMERAL_DISK: 0
IRONIC_AUTOMATED_CLEAN_ENABLED: False IRONIC_AUTOMATED_CLEAN_ENABLED: False
IRONIC_ENFORCE_SCOPE: True # NOTE(TheJulia): Explicitly set scope enforcement to False until we
# remove the legacy policies.
IRONIC_ENFORCE_SCOPE: False
IRONIC_BOOT_MODE: bios IRONIC_BOOT_MODE: bios
Q_AGENT: ovn Q_AGENT: ovn
Q_ML2_TENANT_NETWORK_TYPE: vlan Q_ML2_TENANT_NETWORK_TYPE: vlan
@ -981,6 +983,9 @@
INSTANCE_WAIT: 120 INSTANCE_WAIT: 120
MYSQL_GATHER_PERFORMANCE: False MYSQL_GATHER_PERFORMANCE: False
CIRROS_VERSION: 0.6.1 CIRROS_VERSION: 0.6.1
# Required as different access rights are used by default
# and the classic devstack config which is defaulted doesn't work.
IRONIC_ENFORCE_SCOPE: True
old: old:
IRONIC_VM_LOG_DIR: '{{ devstack_bases.old }}/ironic-bm-logs' IRONIC_VM_LOG_DIR: '{{ devstack_bases.old }}/ironic-bm-logs'
grenade_localrc: grenade_localrc: