Skip to content

Commit 84e36e5

Browse files
authored
Merge pull request #280 from stackhpc/upstream/2026.1-2026-05-25
Synchronise 2026.1 with upstream
2 parents d9d746b + a5e1a3d commit 84e36e5

7 files changed

Lines changed: 76 additions & 16 deletions

File tree

neutron/conf/policies/floatingip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
deprecated_since=versionutils.deprecated.WALLABY)
171171
),
172172
policy.DocumentedRuleDefault(
173-
name='delete_floatingips:tags',
173+
name='delete_floatingip:tags',
174174
check_str=base.ADMIN_OR_PROJECT_MEMBER,
175175
description='Delete the floating IP tags',
176176
operations=ACTION_DELETE_TAGS,

neutron/extensions/tagging.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,10 @@ def index(self, request, **kwargs):
197197
# GET /v2.0/{obj_resource}/{obj_resource_id}/tags
198198
ctx = request.context
199199
rinfo = self._get_resource_info(ctx, kwargs)
200-
policy.enforce(ctx, f'get_{rinfo.obj_type}_{TAGS}',
201-
rinfo.obj)
200+
policy.enforce(
201+
ctx,
202+
self._get_policy_action("get", rinfo.obj_type),
203+
rinfo.obj)
202204
return self.plugin.get_tags(ctx, rinfo.obj_type, rinfo.obj['id'])
203205

204206
def show(self, request, id, **kwargs):
@@ -207,8 +209,10 @@ def show(self, request, id, **kwargs):
207209
validate_tag(id)
208210
ctx = request.context
209211
rinfo = self._get_resource_info(ctx, kwargs)
210-
policy.enforce(ctx, f'get_{rinfo.obj_type}:{TAGS}',
211-
rinfo.obj)
212+
policy.enforce(
213+
ctx,
214+
self._get_policy_action("get", rinfo.obj_type),
215+
rinfo.obj)
212216
return self.plugin.get_tag(ctx, rinfo.obj_type, rinfo.obj['id'], id)
213217

214218
def create(self, request, body, **kwargs):
@@ -217,8 +221,10 @@ def create(self, request, body, **kwargs):
217221
validate_tags(body)
218222
ctx = request.context
219223
rinfo = self._get_resource_info(ctx, kwargs, tags=body[TAGS])
220-
policy.enforce(ctx, f'create_{rinfo.obj_type}:{TAGS}',
221-
rinfo.obj)
224+
policy.enforce(
225+
ctx,
226+
self._get_policy_action("create", rinfo.obj_type),
227+
rinfo.obj)
222228
validate_tags_limit(rinfo.obj_type, body['tags'])
223229
notify_tag_action(ctx, 'create.start', rinfo.obj_type,
224230
rinfo.obj['id'], body['tags'])
@@ -234,8 +240,10 @@ def update(self, request, id, **kwargs):
234240
validate_tag(id)
235241
ctx = request.context
236242
rinfo = self._get_resource_info(ctx, kwargs, tags=[id])
237-
policy.enforce(ctx, f'update_{rinfo.obj_type}:{TAGS}',
238-
rinfo.obj)
243+
policy.enforce(
244+
ctx,
245+
self._get_policy_action("update", rinfo.obj_type),
246+
rinfo.obj)
239247
current_tags = self.plugin.get_tags(
240248
ctx, rinfo.obj_type, rinfo.obj['id'])['tags']
241249
new_tags = current_tags + [id]

neutron/services/ovn_l3/plugin.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
from neutron._i18n import _
3838
from neutron.api.rpc.agentnotifiers import utils as notifier_utils
39+
from neutron.api import wsgi
3940
from neutron.common.ovn import constants as ovn_const
4041
from neutron.common.ovn import extensions
4142
from neutron.common.ovn import utils
@@ -185,11 +186,15 @@ def _post_fork_initialize(self, resource, event, trigger, payload=None):
185186
if not self._nb_ovn or not self._sb_ovn:
186187
raise ovn_l3_exc.MechanismDriverOVNNotReady()
187188

188-
# Register needed events.
189-
self._nb_ovn.idl.notify_handler.watch_events([
190-
ovsdb_monitor.LogicalRouterPortEvent(self),
191-
ovsdb_monitor.LogicalRouterPortGatewayChassisEvent(self),
192-
])
189+
# Register needed events, only for the Neutron API workers.
190+
# TODO(ralonsoh): once [1] is released and required in Neutron, it
191+
# won't be needed the ``get_method_class`` method.
192+
# [1] https://review.opendev.org/c/openstack/neutron-lib/+/988563
193+
if utils.get_method_class(trigger) == wsgi.WorkerService:
194+
self._nb_ovn.idl.notify_handler.watch_events([
195+
ovsdb_monitor.LogicalRouterPortEvent(self),
196+
ovsdb_monitor.LogicalRouterPortGatewayChassisEvent(self),
197+
])
193198

194199
def _add_neutron_router_interface(self, context, router_id,
195200
interface_info):

neutron/tests/functional/services/ovn_l3/test_ovsdb_monitor.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from neutron_lib.plugins import constants as plugin_constants
1919
from neutron_lib.plugins import directory
2020

21+
from neutron.api import wsgi
2122
from neutron.common.ovn import utils as ovn_utils
2223
from neutron.common import utils as n_utils
2324
from neutron.services.bgp import constants as bgp_constants
@@ -34,7 +35,8 @@ def setUp(self, **kwargs):
3435
super().setUp(**kwargs)
3536
self.chassis = self.add_fake_chassis('ovs-host1')
3637
self.l3_plugin = directory.get_plugin(plugin_constants.L3)
37-
self.l3_plugin._post_fork_initialize(mock.ANY, mock.ANY, mock.ANY)
38+
self.l3_plugin._post_fork_initialize(
39+
mock.ANY, mock.ANY, wsgi.WorkerService)
3840
self.ext_api = test_extensions.setup_extensions_middleware(
3941
test_l3.L3TestExtensionManager())
4042
kwargs = {'arg_list': (external_net.EXTERNAL,),
@@ -201,7 +203,8 @@ def setUp(self, **kwargs):
201203
super().setUp(**kwargs)
202204
self.chassis = self.add_fake_chassis('ovs-host1')
203205
self.l3_plugin = directory.get_plugin(plugin_constants.L3)
204-
self.l3_plugin._post_fork_initialize(mock.ANY, mock.ANY, mock.ANY)
206+
self.l3_plugin._post_fork_initialize(
207+
mock.ANY, mock.ANY, wsgi.WorkerService)
205208
self.ext_api = test_extensions.setup_extensions_middleware(
206209
test_l3.L3TestExtensionManager())
207210
kwargs = {'arg_list': (external_net.EXTERNAL,),

neutron/tests/unit/extensions/test_tagging.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from neutron_lib.utils import net as net_utils
2525
from oslo_utils import uuidutils
2626

27+
from neutron.conf import policies as conf_policies
2728
from neutron.extensions import tagging
2829
from neutron.objects import network as network_obj
2930
from neutron.objects import network_segment_range as network_segment_range_obj
@@ -87,6 +88,22 @@ def test_all_ovo_cls_have_a_reference(self):
8788
ovo_resources = set(tagging.OVO_CLS.keys())
8889
self.assertEqual(tc_supported_resources, ovo_resources)
8990

91+
def test__get_policy_action_all_resources_and_actions(self):
92+
registered_rules = {rule.name for rule in conf_policies.list_rules()}
93+
actions = ('get', 'create', 'update', 'delete')
94+
for collection, member in self.tc.supported_resources.items():
95+
for action in actions:
96+
expected = f'{action}_{member}:tags'
97+
result = self.tc._get_policy_action(action, collection)
98+
self.assertEqual(
99+
expected, result,
100+
f'_get_policy_action("{action}", "{collection}") '
101+
f'returned "{result}" instead of "{expected}"')
102+
self.assertIn(
103+
result, registered_rules,
104+
f'Policy rule "{result}" is not registered in '
105+
f'neutron.conf.policies')
106+
90107
def _check_resource_info(self, obj, obj_type):
91108
id_key = self.tc.supported_resources[obj_type] + '_id'
92109
res = self.tc._get_resource_info(self.ctx, {id_key: obj['id']})
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
security:
3+
- |
4+
Fixed a security issue where the tagging controller's single-tag write
5+
endpoints (``POST /v2.0/{resource}/{id}/tags`` and
6+
``PUT /v2.0/{resource}/{id}/tags/{tag}``) enforced policy action names
7+
using the plural collection key (e.g. ``create_networks:tags``) instead
8+
of the singular member name (e.g. ``create_network:tags``). Because the
9+
plural names did not match any registered policy rule, they fell through
10+
to oslo.policy's default rule, allowing project readers to create and
11+
update tags on same-project resources.
12+
All tag-write endpoints now consistently use the singular policy action
13+
names that match the registered rules.
14+
fixes:
15+
- |
16+
Fixed the ``delete_floatingips:tags`` policy rule name to use the correct
17+
singular form ``delete_floatingip:tags``, consistent with all other
18+
tag-related policy rules.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
fixes:
3+
- |
4+
The ``OVNL3RouterPlugin`` now registers OVN OVSDB events
5+
(``LogicalRouterPortEvent`` and ``RouterHAChassisGroupEvent``) only in
6+
Neutron API workers (``WorkerService`` instances). Previously these events
7+
were registered by every worker type that called
8+
``_post_fork_initialize``, which could lead to unexpected event processing
9+
in maintenance or other non-API workers.

0 commit comments

Comments
 (0)