During policy testing using Patrole with the new multi-policy support, it became apparent
that the Neutron policy enforcement code is using the new value of an attribute (on a PUT
request) to validate access to that same attribute. Here are two scenarios that expose this problem, using devstack:
Scenario 1:
1. Set up Patrole as a Tempest plugin and set the [patrole] parameters in tempest.conf.
2. Set the rbac_test_role to "Member".
3. Change /etc/neutron/policy.json so that "update_network" and "update_network:shared" are defined as "rule:admin_only" (the "Member"
role is not allowed to update the network)
4. Change /etc/neutron/policy.json so that "get_network" is defined as "rule:shared", so that a "Member" is allowed to view only a shared
network, but not a non-shared network.
5. Run the patrole_tempest_plugin.tests.api.network.test_networks_rbac. NetworksRbacTest.test_update_network_shared test case. This test has
recently been modified to test the multi-policy nature of Neutron's
policy enforcement algorithm.
- The test case expects a 404 NotFound exception to be raised if the
role being tested ("Member" in this case) is not allowed to perform "get_network". A 403 Forbidden exception is expected if the role is
not allowed to perform either of the "update_network" or "update_network:shared" actions.
Result:
With the current Neutron code in master, this test fails with the given
policy because a 403 Forbidden is thrown instead of the expected 404 NotFound exception.
The reason it does not throw the expected 404 is because the "Member"
role IS allowed to perform "get_network". That is because the Neutron
policy enforcement code uses the NEW value of the network's "shared" attribute in order to check if the rule "get_network" is allowed
instead of the original value. The original value is shared=False as
set by the test case, and the test case is modifying it to True. So "get_network" should not have been allowed for the Member role here.
Scenario 2:
(setup is similar to scenario 1)
The same problem occurs by running the following test case against the
"Member" role:
patrole_tempest_plugin.tests.api.network.test_networks_rbac. NetworksRbacTest.test_update_network_router_external
using this set of policy rules:
- "update_network" and "update_network:router:external" defined as "rule:admin_only"
- "get_network" is defined as "rule:external", so that a "Member" is allowed to view only external networks.
Result:
Although 404 is expected to be thrown by Neutron due to the "get_network" rule, Neutron actually throws a 403 exception, so the
test case fails. That is because the Neutron policy enforcement code
uses the NEW value of the network's "external" attribute in order to
check if the rule "get_network" is allowed instead of the original
value. The original value is external=False as set by the test case,
and the test case is modifying it to True. So "get_network" should
not have been allowed for the Member role here.
During policy testing using Patrole with the new multi-policy support, it became apparent
that the Neutron policy enforcement code is using the new value of an attribute (on a PUT
request) to validate access to that same attribute. Here are two scenarios that expose this problem, using devstack:
Scenario 1:
tempest. conf. policy. json so that "update_network" and
"update_ network: shared" are defined as "rule:admin_only" (the "Member" policy. json so that "get_network" is defined as
"rule: shared" , so that a "Member" is allowed to view only a shared tempest_ plugin. tests.api. network. test_networks_ rbac.
NetworksRba cTest.test_ update_ network_ shared test case. This test has
"get_network" . A 403 Forbidden exception is expected if the role is
"update_ network: shared" actions.
NotFound exception.
1. Set up Patrole as a Tempest plugin and set the [patrole] parameters in
2. Set the rbac_test_role to "Member".
3. Change /etc/neutron/
role is not allowed to update the network)
4. Change /etc/neutron/
network, but not a non-shared network.
5. Run the patrole_
recently been modified to test the multi-policy nature of Neutron's
policy enforcement algorithm.
- The test case expects a 404 NotFound exception to be raised if the
role being tested ("Member" in this case) is not allowed to perform
not allowed to perform either of the "update_network" or
Result:
With the current Neutron code in master, this test fails with the given
policy because a 403 Forbidden is thrown instead of the expected 404
The reason it does not throw the expected 404 is because the "Member"
attribute in order to check if the rule "get_network" is allowed
"get_ network" should not have been allowed for the Member role here.
role IS allowed to perform "get_network". That is because the Neutron
policy enforcement code uses the NEW value of the network's "shared"
instead of the original value. The original value is shared=False as
set by the test case, and the test case is modifying it to True. So
See code snippet: https:/ /github. com/openstack/ neutron/ blob/
9cb68ce777 7f3016f6affe0ab bc7ebe3b859f7c3 /neutron/ pecan_wsgi/ hooks/
policy_ enforcement. py#L123
Scenario 2: tempest_ plugin. tests.api. network. test_networks_ rbac.
NetworksRbacT est.test_ update_ network_ router_ external network: router: external" defined as
"rule:admin_ only"
allowed to view only external networks.
"get_ network" rule, Neutron actually throws a 403 exception, so the
(setup is similar to scenario 1)
The same problem occurs by running the following test case against the
"Member" role:
patrole_
using this set of policy rules:
- "update_network" and "update_
- "get_network" is defined as "rule:external", so that a "Member" is
Result:
Although 404 is expected to be thrown by Neutron due to the
test case fails. That is because the Neutron policy enforcement code
uses the NEW value of the network's "external" attribute in order to
check if the rule "get_network" is allowed instead of the original
value. The original value is external=False as set by the test case,
and the test case is modifying it to True. So "get_network" should
not have been allowed for the Member role here.