octavia 15.0.0__py3-none-any.whl → 16.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. octavia/amphorae/backends/agent/api_server/keepalivedlvs.py +9 -0
  2. octavia/amphorae/backends/agent/api_server/loadbalancer.py +6 -6
  3. octavia/amphorae/backends/agent/api_server/plug.py +1 -1
  4. octavia/amphorae/backends/agent/api_server/util.py +35 -2
  5. octavia/amphorae/backends/health_daemon/status_message.py +1 -2
  6. octavia/amphorae/drivers/haproxy/rest_api_driver.py +12 -7
  7. octavia/api/drivers/amphora_driver/flavor_schema.py +5 -0
  8. octavia/api/drivers/noop_driver/driver.py +2 -1
  9. octavia/api/drivers/utils.py +12 -0
  10. octavia/api/root_controller.py +8 -2
  11. octavia/api/v2/controllers/base.py +8 -4
  12. octavia/api/v2/controllers/listener.py +12 -2
  13. octavia/api/v2/controllers/load_balancer.py +33 -1
  14. octavia/api/v2/controllers/member.py +58 -4
  15. octavia/api/v2/types/load_balancer.py +7 -1
  16. octavia/api/v2/types/member.py +3 -0
  17. octavia/common/base_taskflow.py +19 -10
  18. octavia/common/clients.py +8 -2
  19. octavia/common/config.py +17 -2
  20. octavia/common/constants.py +6 -0
  21. octavia/common/data_models.py +32 -2
  22. octavia/common/exceptions.py +5 -0
  23. octavia/common/utils.py +4 -1
  24. octavia/common/validate.py +16 -0
  25. octavia/compute/drivers/noop_driver/driver.py +30 -1
  26. octavia/controller/healthmanager/health_manager.py +7 -0
  27. octavia/controller/worker/v2/flows/amphora_flows.py +3 -5
  28. octavia/controller/worker/v2/flows/listener_flows.py +2 -1
  29. octavia/controller/worker/v2/flows/load_balancer_flows.py +38 -0
  30. octavia/controller/worker/v2/taskflow_jobboard_driver.py +34 -6
  31. octavia/controller/worker/v2/tasks/compute_tasks.py +9 -5
  32. octavia/controller/worker/v2/tasks/database_tasks.py +26 -6
  33. octavia/controller/worker/v2/tasks/network_tasks.py +118 -70
  34. octavia/db/base_models.py +29 -5
  35. octavia/db/migration/alembic_migrations/versions/3097e55493ae_add_sg_id_to_vip_table.py +39 -0
  36. octavia/db/migration/alembic_migrations/versions/8db7a6443785_add_member_vnic_type.py +36 -0
  37. octavia/db/migration/alembic_migrations/versions/fabf4983846b_add_member_port_table.py +40 -0
  38. octavia/db/models.py +43 -1
  39. octavia/db/repositories.py +88 -9
  40. octavia/network/base.py +29 -12
  41. octavia/network/data_models.py +2 -1
  42. octavia/network/drivers/neutron/allowed_address_pairs.py +55 -46
  43. octavia/network/drivers/neutron/base.py +28 -16
  44. octavia/network/drivers/neutron/utils.py +2 -2
  45. octavia/network/drivers/noop_driver/driver.py +150 -29
  46. octavia/policies/__init__.py +4 -0
  47. octavia/policies/advanced_rbac.py +95 -0
  48. octavia/policies/base.py +5 -101
  49. octavia/policies/keystone_default_roles.py +81 -0
  50. octavia/policies/loadbalancer.py +13 -0
  51. octavia/tests/common/constants.py +2 -1
  52. octavia/tests/common/sample_data_models.py +27 -14
  53. octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +5 -4
  54. octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py +2 -1
  55. octavia/tests/functional/api/v2/test_health_monitor.py +1 -1
  56. octavia/tests/functional/api/v2/test_l7policy.py +1 -1
  57. octavia/tests/functional/api/v2/test_listener.py +1 -1
  58. octavia/tests/functional/api/v2/test_load_balancer.py +150 -4
  59. octavia/tests/functional/api/v2/test_member.py +50 -0
  60. octavia/tests/functional/api/v2/test_pool.py +1 -1
  61. octavia/tests/functional/api/v2/test_quotas.py +5 -8
  62. octavia/tests/functional/db/base.py +6 -6
  63. octavia/tests/functional/db/test_models.py +124 -1
  64. octavia/tests/functional/db/test_repositories.py +237 -19
  65. octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +89 -1
  66. octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +10 -7
  67. octavia/tests/unit/api/drivers/test_utils.py +6 -1
  68. octavia/tests/unit/certificates/generator/test_local.py +1 -1
  69. octavia/tests/unit/common/test_base_taskflow.py +4 -3
  70. octavia/tests/unit/compute/drivers/noop_driver/test_driver.py +28 -2
  71. octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +27 -1
  72. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +28 -6
  73. octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +100 -79
  74. octavia/tests/unit/controller/worker/v2/test_taskflow_jobboard_driver.py +8 -0
  75. octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +62 -45
  76. octavia/tests/unit/network/drivers/neutron/test_base.py +7 -7
  77. octavia/tests/unit/network/drivers/noop_driver/test_driver.py +55 -42
  78. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/tox.ini +0 -1
  79. {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/AUTHORS +3 -0
  80. octavia-16.0.0.dist-info/METADATA +156 -0
  81. {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/RECORD +95 -90
  82. {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/WHEEL +1 -1
  83. {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/entry_points.txt +1 -1
  84. octavia-16.0.0.dist-info/pbr.json +1 -0
  85. octavia-15.0.0.dist-info/METADATA +0 -156
  86. octavia-15.0.0.dist-info/pbr.json +0 -1
  87. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/LICENSE +0 -0
  88. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/README.rst +0 -0
  89. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/README.rst +0 -0
  90. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
  91. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
  92. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
  93. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
  94. {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/version.txt +0 -0
  95. {octavia-15.0.0.data → octavia-16.0.0.data}/scripts/octavia-wsgi +0 -0
  96. {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/LICENSE +0 -0
  97. {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/top_level.txt +0 -0
@@ -12,14 +12,28 @@
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
14
 
15
+ import typing
16
+
15
17
  from oslo_log import log as logging
16
18
  from oslo_utils import uuidutils
19
+ from sqlalchemy import Column
20
+ from sqlalchemy import create_engine
21
+ from sqlalchemy import delete
22
+ from sqlalchemy import event
23
+ from sqlalchemy import insert
24
+ from sqlalchemy import MetaData
25
+ from sqlalchemy import select
26
+ from sqlalchemy import String
27
+ from sqlalchemy import Table
17
28
 
18
29
  from octavia.common import constants
19
30
  from octavia.common import data_models
20
31
  from octavia.network import base as driver_base
21
32
  from octavia.network import data_models as network_models
22
33
 
34
+ if typing.TYPE_CHECKING:
35
+ from octavia.common import context
36
+
23
37
  LOG = logging.getLogger(__name__)
24
38
 
25
39
  _NOOP_MANAGER_VARS = {
@@ -38,6 +52,39 @@ class NoopManager:
38
52
  self.networkconfigconfig = {}
39
53
  self._qos_extension_enabled = True
40
54
 
55
+ # The controller worker can run with multiple processes, so we
56
+ # need to have a persistent and shared store for the no-op driver.
57
+ self.engine = create_engine('sqlite:////tmp/octavia-network-noop.db')
58
+
59
+ # TODO(johnsom) work around pysqlite locking issues per:
60
+ # https://github.com/sqlalchemy/sqlalchemy/discussions/12330
61
+ @event.listens_for(self.engine, "connect")
62
+ def do_connect(dbapi_connection, connection_record):
63
+ # disable pysqlite's emitting of the BEGIN statement entirely.
64
+ # also stops it from emitting COMMIT before any DDL.
65
+ dbapi_connection.isolation_level = None
66
+
67
+ @event.listens_for(self.engine, "begin")
68
+ def do_begin(conn):
69
+ conn.exec_driver_sql("BEGIN EXCLUSIVE")
70
+
71
+ metadata_obj = MetaData()
72
+
73
+ self.interfaces_table = Table(
74
+ 'interfaces',
75
+ metadata_obj,
76
+ Column('port_id', String(36)),
77
+ Column('network_id', String(36)),
78
+ Column('compute_id', String(36)),
79
+ Column('vnic_type', String(6)))
80
+ self.fixed_ips_table = Table(
81
+ 'fixed_ips',
82
+ metadata_obj,
83
+ Column('port_id', String(36)),
84
+ Column('subnet_id', String(36)),
85
+ Column('ip_address', String(64)))
86
+ metadata_obj.create_all(self.engine)
87
+
41
88
  def allocate_vip(self, loadbalancer):
42
89
  LOG.debug("Network %s no-op, allocate_vip loadbalancer %s",
43
90
  self.__class__.__name__, loadbalancer)
@@ -82,6 +129,18 @@ class NoopManager:
82
129
  vip.ip_address)] = (load_balancer, vip,
83
130
  'update_vip_sg')
84
131
 
132
+ def update_aap_port_sg(self,
133
+ load_balancer: data_models.LoadBalancer,
134
+ amphora: data_models.Amphora,
135
+ vip: data_models.Vip):
136
+ LOG.debug("Network %s no-op, update_aap_port_sg load_balancer %s, "
137
+ " vip %s, amphora %s", self.__class__.__name__,
138
+ load_balancer.id, vip.ip_address, amphora)
139
+ self.networkconfigconfig[(amphora.id,
140
+ vip.ip_address)] = (load_balancer, vip,
141
+ amphora,
142
+ 'update_aap_port_sg')
143
+
85
144
  def plug_aap_port(self, load_balancer, vip, amphora, subnet):
86
145
  LOG.debug("Network %s no-op, plug_aap_port loadbalancer %s, vip %s,"
87
146
  " amphora %s, subnet %s",
@@ -91,12 +150,34 @@ class NoopManager:
91
150
  vip.ip_address)] = (
92
151
  load_balancer, vip, amphora, subnet,
93
152
  'plug_aap_port')
153
+
154
+ fixed_ips = [network_models.FixedIP(subnet_id=subnet.id,
155
+ ip_address=vip.ip_address)]
156
+
157
+ port_id = uuidutils.generate_uuid()
158
+ LOG.debug("Network %s no-op, plug_aap_port loadbalancer %s is using "
159
+ "base port ID %s",
160
+ self.__class__.__name__,
161
+ load_balancer.id, port_id)
162
+
163
+ # Store the interface information in the no-op DB
164
+ with self.engine.connect() as connection:
165
+ connection.execute(insert(self.interfaces_table).values(
166
+ port_id=port_id, network_id=vip.network_id,
167
+ compute_id=amphora.compute_id,
168
+ vnic_type=constants.VNIC_TYPE_NORMAL))
169
+ for fixed_ip in fixed_ips:
170
+ connection.execute(insert(self.fixed_ips_table).values(
171
+ port_id=port_id, subnet_id=fixed_ip.subnet_id,
172
+ ip_address=fixed_ip.ip_address))
173
+ connection.commit()
174
+
94
175
  return data_models.Amphora(
95
176
  id=amphora.id,
96
177
  compute_id=amphora.compute_id,
97
178
  vrrp_ip='198.51.100.1',
98
179
  ha_ip='198.51.100.1',
99
- vrrp_port_id=uuidutils.generate_uuid(),
180
+ vrrp_port_id=port_id,
100
181
  ha_port_id=uuidutils.generate_uuid()
101
182
  )
102
183
 
@@ -117,42 +198,45 @@ class NoopManager:
117
198
  vip.ip_address)] = (vip, amphora, subnet,
118
199
  'unplug_aap_port')
119
200
 
120
- def plug_network(self, compute_id, network_id):
121
- LOG.debug("Network %s no-op, plug_network compute_id %s, network_id "
122
- "%s", self.__class__.__name__, compute_id,
123
- network_id)
124
- self.networkconfigconfig[(compute_id, network_id)] = (
125
- compute_id, network_id, 'plug_network')
126
- interface = network_models.Interface(
127
- id=uuidutils.generate_uuid(),
128
- compute_id=compute_id,
129
- network_id=network_id,
130
- fixed_ips=[],
131
- port_id=uuidutils.generate_uuid()
132
- )
133
- _NOOP_MANAGER_VARS['ports'][interface.port_id] = (
134
- network_models.Port(
135
- id=interface.port_id,
136
- network_id=network_id))
137
- _NOOP_MANAGER_VARS['interfaces'][(network_id, compute_id)] = (
138
- interface)
139
- return interface
140
-
141
201
  def unplug_network(self, compute_id, network_id):
142
202
  LOG.debug("Network %s no-op, unplug_network compute_id %s, "
143
203
  "network_id %s",
144
204
  self.__class__.__name__, compute_id, network_id)
145
205
  self.networkconfigconfig[(compute_id, network_id)] = (
146
206
  compute_id, network_id, 'unplug_network')
147
- _NOOP_MANAGER_VARS['interfaces'].pop((network_id, compute_id), None)
148
207
 
149
208
  def get_plugged_networks(self, compute_id):
150
- LOG.debug("Network %s no-op, get_plugged_networks amphora_id %s",
209
+ LOG.debug("Network %s no-op, get_plugged_networks compute_id %s",
151
210
  self.__class__.__name__, compute_id)
152
211
  self.networkconfigconfig[compute_id] = (
153
212
  compute_id, 'get_plugged_networks')
154
- return [pn for pn in _NOOP_MANAGER_VARS['interfaces'].values()
155
- if pn.compute_id == compute_id]
213
+
214
+ # Retrieve the interfaces from the no-op DB for this compute_id
215
+ interfaces = []
216
+ with self.engine.connect() as connection:
217
+ int_results = connection.execute(
218
+ select(self.interfaces_table)
219
+ .where(self.interfaces_table.c.compute_id == compute_id))
220
+ # Walk through the matching interfaces
221
+ for interface in int_results:
222
+ fixed_ips = []
223
+ # Get the fixed IPs on each interface
224
+ fixed_ip_results = connection.execute(
225
+ select(self.fixed_ips_table)
226
+ .where(
227
+ self.fixed_ips_table.c.port_id == interface.port_id))
228
+ # Build the FixedIP objects for the interface
229
+ for fixed_ip in fixed_ip_results:
230
+ fixed_ips.append(network_models.FixedIP(
231
+ subnet_id=fixed_ip.subnet_id,
232
+ ip_address=fixed_ip.ip_address))
233
+ # Add the interface object to the list
234
+ interfaces.append(network_models.Interface(
235
+ compute_id=interface.compute_id,
236
+ network_id=interface.network_id,
237
+ port_id=interface.port_id, fixed_ips=fixed_ips,
238
+ vnic_type=interface.vnic_type))
239
+ return interfaces
156
240
 
157
241
  def update_vip(self, loadbalancer, for_delete=False):
158
242
  LOG.debug("Network %s no-op, update_vip loadbalancer %s "
@@ -228,6 +312,14 @@ class NoopManager:
228
312
  _NOOP_MANAGER_VARS['ports'][port_id] = port
229
313
  return port
230
314
 
315
+ def get_security_group_by_id(self, sg_id: str,
316
+ context: 'context.RequestContext' = None) -> (
317
+ 'network_models.SecurityGroup'):
318
+ LOG.debug("Network %s no-op, get_security_group_by_id %s",
319
+ self.__class__.__name__, sg_id)
320
+ self.networkconfigconfig[sg_id] = (sg_id, 'get_security_group_by_id')
321
+ return network_models.SecurityGroup(id=sg_id)
322
+
231
323
  def get_network_by_name(self, network_name):
232
324
  LOG.debug("Network %s no-op, get_network_by_name network_name %s",
233
325
  self.__class__.__name__, network_name)
@@ -374,6 +466,16 @@ class NoopManager:
374
466
  self.__class__.__name__, port_id)
375
467
  self.networkconfigconfig[port_id] = (port_id, 'delete_port')
376
468
 
469
+ # Remove the port from the no-op DB
470
+ with self.engine.connect() as connection:
471
+ connection.execute(delete(self.interfaces_table)
472
+ .where(
473
+ self.interfaces_table.c.port_id == port_id))
474
+ connection.execute(delete(self.fixed_ips_table)
475
+ .where(
476
+ self.fixed_ips_table.c.port_id == port_id))
477
+ connection.commit()
478
+
377
479
  def set_port_admin_state_up(self, port_id, state):
378
480
  LOG.debug("Network %s no-op, set_port_admin_state_up port_id %s, "
379
481
  "state %s", self.__class__.__name__, port_id, state)
@@ -410,6 +512,17 @@ class NoopManager:
410
512
  self.networkconfigconfig[(network_id, 'create_port')] = (
411
513
  network_id, name, fixed_ip_obj_list, secondary_ips,
412
514
  security_group_ids, admin_state_up, qos_policy_id, vnic_type)
515
+
516
+ # Store the interface information in the no-op DB
517
+ with self.engine.connect() as connection:
518
+ connection.execute(insert(self.interfaces_table).values(
519
+ port_id=port_id, network_id=network_id, vnic_type=vnic_type))
520
+ for fixed_ip in fixed_ip_obj_list:
521
+ connection.execute(insert(self.fixed_ips_table).values(
522
+ port_id=port_id, subnet_id=fixed_ip.subnet_id,
523
+ ip_address=fixed_ip.ip_address))
524
+ connection.commit()
525
+
413
526
  return network_models.Port(
414
527
  id=port_id, name=name, device_id='no-op-device-id',
415
528
  device_owner='Octavia', mac_address='00:00:5E:00:53:05',
@@ -454,9 +567,6 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
454
567
  def unplug_vip(self, loadbalancer, vip):
455
568
  self.driver.unplug_vip(loadbalancer, vip)
456
569
 
457
- def plug_network(self, compute_id, network_id):
458
- return self.driver.plug_network(compute_id, network_id)
459
-
460
570
  def unplug_network(self, compute_id, network_id):
461
571
  self.driver.unplug_network(compute_id, network_id)
462
572
 
@@ -475,6 +585,11 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
475
585
  def get_port(self, port_id, context=None):
476
586
  return self.driver.get_port(port_id)
477
587
 
588
+ def get_security_group_by_id(self, sg_id: str,
589
+ context: 'context.RequestContext' = None) -> (
590
+ 'network_models.SecurityGroup'):
591
+ return self.driver.get_security_group_by_id(sg_id, context=context)
592
+
478
593
  def get_qos_policy(self, qos_policy_id):
479
594
  return self.driver.get_qos_policy(qos_policy_id)
480
595
 
@@ -508,6 +623,12 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
508
623
  def update_vip_sg(self, load_balancer, vip):
509
624
  self.driver.update_vip_sg(load_balancer, vip)
510
625
 
626
+ def update_aap_port_sg(self,
627
+ load_balancer: data_models.LoadBalancer,
628
+ amphora: data_models.Amphora,
629
+ vip: data_models.Vip):
630
+ self.driver.update_aap_port_sg(load_balancer, amphora, vip)
631
+
511
632
  def plug_aap_port(self, load_balancer, vip, amphora, subnet):
512
633
  return self.driver.plug_aap_port(load_balancer, vip, amphora, subnet)
513
634
 
@@ -13,6 +13,7 @@
13
13
 
14
14
  import itertools
15
15
 
16
+ from octavia.policies import advanced_rbac
16
17
  from octavia.policies import amphora
17
18
  from octavia.policies import availability_zone
18
19
  from octavia.policies import availability_zone_profile
@@ -20,6 +21,7 @@ from octavia.policies import base
20
21
  from octavia.policies import flavor
21
22
  from octavia.policies import flavor_profile
22
23
  from octavia.policies import healthmonitor
24
+ from octavia.policies import keystone_default_roles
23
25
  from octavia.policies import l7policy
24
26
  from octavia.policies import l7rule
25
27
  from octavia.policies import listener
@@ -35,6 +37,8 @@ from octavia.policies import quota
35
37
  def list_rules():
36
38
  return itertools.chain(
37
39
  base.list_rules(),
40
+ keystone_default_roles.list_rules(),
41
+ advanced_rbac.list_rules(),
38
42
  flavor.list_rules(),
39
43
  flavor_profile.list_rules(),
40
44
  availability_zone.list_rules(),
@@ -0,0 +1,95 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+ # not use this file except in compliance with the License. You may obtain
3
+ # a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+ # License for the specific language governing permissions and limitations
11
+ # under the License.
12
+
13
+ from oslo_log import versionutils
14
+ from oslo_policy import policy
15
+
16
+ from octavia.common import constants
17
+
18
+ # Octavia specific Advanced RBAC rules
19
+
20
+ # The default is to not allow access unless the auth_strategy is 'noauth'.
21
+ # Users must be a member of one of the following roles to have access to
22
+ # the load-balancer API:
23
+ #
24
+ # role:load-balancer_observer
25
+ # User has access to load-balancer read-only APIs
26
+ # role:load-balancer_global_observer
27
+ # User has access to load-balancer read-only APIs including resources
28
+ # owned by others.
29
+ # role:load-balancer_member
30
+ # User has access to load-balancer read and write APIs
31
+ # role:load-balancer_admin
32
+ # User is considered an admin for all load-balancer APIs including
33
+ # resources owned by others.
34
+
35
+ deprecated_context_is_admin = policy.DeprecatedRule(
36
+ name='context_is_admin',
37
+ check_str='role:admin or '
38
+ 'role:load-balancer_admin',
39
+ deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
40
+ deprecated_since=versionutils.deprecated.WALLABY,
41
+ )
42
+
43
+ # Note: 'is_admin:True' is a policy rule that takes into account the
44
+ # auth_strategy == noauth configuration setting.
45
+ # It is equivalent to 'rule:context_is_admin or {auth_strategy == noauth}'
46
+
47
+ deprecated_admin = policy.DeprecatedRule(
48
+ name='load-balancer:admin',
49
+ check_str='is_admin:True or '
50
+ 'role:admin or '
51
+ 'role:load-balancer_admin',
52
+ deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
53
+ deprecated_since=versionutils.deprecated.WALLABY,
54
+ )
55
+
56
+ deprecated_global_observer = policy.DeprecatedRule(
57
+ name='load-balancer:global_observer',
58
+ check_str='role:load-balancer_global_observer',
59
+ deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
60
+ deprecated_since=versionutils.deprecated.WALLABY,
61
+ )
62
+
63
+ deprecated_member_and_owner = policy.DeprecatedRule(
64
+ name='load-balancer:member_and_owner',
65
+ check_str='role:load-balancer_member and '
66
+ 'rule:load-balancer:owner',
67
+ deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
68
+ deprecated_since=versionutils.deprecated.WALLABY,
69
+ )
70
+
71
+ deprecated_observer_and_owner = policy.DeprecatedRule(
72
+ name='load-balancer:observer_and_owner',
73
+ check_str='role:load-balancer_observer and '
74
+ 'rule:load-balancer:owner',
75
+ deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
76
+ deprecated_since=versionutils.deprecated.WALLABY,
77
+ )
78
+
79
+ deprecated_quota_admin = policy.DeprecatedRule(
80
+ name='load-balancer:quota-admin',
81
+ check_str='role:load-balancer_quota_admin',
82
+ deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
83
+ deprecated_since=versionutils.deprecated.WALLABY,
84
+ )
85
+
86
+ rules = [
87
+ policy.RuleDefault(
88
+ name='load-balancer:owner',
89
+ check_str='project_id:%(project_id)s',
90
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
91
+ ]
92
+
93
+
94
+ def list_rules():
95
+ return rules
octavia/policies/base.py CHANGED
@@ -10,112 +10,16 @@
10
10
  # License for the specific language governing permissions and limitations
11
11
  # under the License.
12
12
 
13
- from oslo_log import versionutils
14
13
  from oslo_policy import policy
15
14
 
16
15
  from octavia.common import constants
17
16
 
18
- deprecated_context_is_admin = policy.DeprecatedRule(
19
- name='context_is_admin',
20
- check_str='role:admin or '
21
- 'role:load-balancer_admin',
22
- deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
23
- deprecated_since=versionutils.deprecated.WALLABY,
24
- )
25
- deprecated_observer_and_owner = policy.DeprecatedRule(
26
- name='load-balancer:observer_and_owner',
27
- check_str='role:load-balancer_observer and '
28
- 'rule:load-balancer:owner',
29
- deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
30
- deprecated_since=versionutils.deprecated.WALLABY,
31
- )
32
- deprecated_member_and_owner = policy.DeprecatedRule(
33
- name='load-balancer:member_and_owner',
34
- check_str='role:load-balancer_member and '
35
- 'rule:load-balancer:owner',
36
- deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
37
- deprecated_since=versionutils.deprecated.WALLABY,
38
- )
39
17
 
40
18
  rules = [
41
19
 
42
- # OpenStack wide scoped rules
43
-
44
- # Project scoped Member
45
- policy.RuleDefault(
46
- name='project-member',
47
- check_str='role:member and '
48
- 'project_id:%(project_id)s',
49
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
50
-
51
- # Project scoped Reader
52
- policy.RuleDefault(
53
- name='project-reader',
54
- check_str='role:reader and '
55
- 'project_id:%(project_id)s',
56
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
57
-
58
- # Octavia specific Advanced RBAC rules
59
-
60
- # The default is to not allow access unless the auth_strategy is 'noauth'.
61
- # Users must be a member of one of the following roles to have access to
62
- # the load-balancer API:
63
- #
64
- # role:load-balancer_observer
65
- # User has access to load-balancer read-only APIs
66
- # role:load-balancer_global_observer
67
- # User has access to load-balancer read-only APIs including resources
68
- # owned by others.
69
- # role:load-balancer_member
70
- # User has access to load-balancer read and write APIs
71
- # role:load-balancer_admin
72
- # User is considered an admin for all load-balancer APIs including
73
- # resources owned by others.
74
-
75
- policy.RuleDefault(
76
- name='context_is_admin',
77
- check_str='role:load-balancer_admin or '
78
- 'role:admin',
79
- deprecated_rule=deprecated_context_is_admin,
80
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
81
-
82
- # Note: 'is_admin:True' is a policy rule that takes into account the
83
- # auth_strategy == noauth configuration setting.
84
- # It is equivalent to 'rule:context_is_admin or {auth_strategy == noauth}'
85
-
86
- policy.RuleDefault(
87
- name='load-balancer:owner',
88
- check_str='project_id:%(project_id)s',
89
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
90
-
91
- # API access roles
92
- policy.RuleDefault(
93
- name='load-balancer:observer_and_owner',
94
- check_str='role:load-balancer_observer and '
95
- 'rule:project-reader',
96
- deprecated_rule=deprecated_observer_and_owner,
97
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
98
-
99
- policy.RuleDefault(
100
- name='load-balancer:global_observer',
101
- check_str='role:load-balancer_global_observer',
102
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
103
-
104
- policy.RuleDefault(
105
- name='load-balancer:member_and_owner',
106
- check_str='role:load-balancer_member and '
107
- 'rule:project-member',
108
- deprecated_rule=deprecated_member_and_owner,
109
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
110
-
111
20
  # API access methods
112
-
113
- policy.RuleDefault(
114
- name='load-balancer:admin',
115
- check_str='is_admin:True or '
116
- 'role:load-balancer_admin or '
117
- 'role:admin',
118
- scope_types=[constants.RBAC_SCOPE_PROJECT]),
21
+ #
22
+ # These are the only rules that should be applied to API endpoints.
119
23
 
120
24
  policy.RuleDefault(
121
25
  name='load-balancer:read',
@@ -142,20 +46,20 @@ rules = [
142
46
  check_str='rule:load-balancer:observer_and_owner or '
143
47
  'rule:load-balancer:global_observer or '
144
48
  'rule:load-balancer:member_and_owner or '
145
- 'role:load-balancer_quota_admin or '
49
+ 'rule:load-balancer:quota-admin or '
146
50
  'rule:load-balancer:admin',
147
51
  scope_types=[constants.RBAC_SCOPE_PROJECT]),
148
52
 
149
53
  policy.RuleDefault(
150
54
  name='load-balancer:read-quota-global',
151
55
  check_str='rule:load-balancer:global_observer or '
152
- 'role:load-balancer_quota_admin or '
56
+ 'rule:load-balancer:quota-admin or '
153
57
  'rule:load-balancer:admin',
154
58
  scope_types=[constants.RBAC_SCOPE_PROJECT]),
155
59
 
156
60
  policy.RuleDefault(
157
61
  name='load-balancer:write-quota',
158
- check_str='role:load-balancer_quota_admin or '
62
+ check_str='rule:load-balancer:quota-admin or '
159
63
  'rule:load-balancer:admin',
160
64
  scope_types=[constants.RBAC_SCOPE_PROJECT]),
161
65
  ]
@@ -0,0 +1,81 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+ # not use this file except in compliance with the License. You may obtain
3
+ # a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+ # License for the specific language governing permissions and limitations
11
+ # under the License.
12
+
13
+ from oslo_policy import policy
14
+
15
+ from octavia.common import constants
16
+ from octavia.policies import advanced_rbac
17
+
18
+ rules = [
19
+
20
+ # OpenStack keystone default roles
21
+
22
+ # Project scoped Member
23
+ policy.RuleDefault(
24
+ name='project-member',
25
+ check_str='role:member and '
26
+ 'project_id:%(project_id)s',
27
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
28
+
29
+ # Project scoped Reader
30
+ policy.RuleDefault(
31
+ name='project-reader',
32
+ check_str='role:reader and '
33
+ 'project_id:%(project_id)s',
34
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
35
+
36
+ policy.RuleDefault(
37
+ name='context_is_admin',
38
+ check_str='role:admin',
39
+ deprecated_rule=advanced_rbac.deprecated_context_is_admin,
40
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
41
+
42
+ # API access roles
43
+ policy.RuleDefault(
44
+ name='load-balancer:admin',
45
+ check_str='is_admin:True or '
46
+ 'role:admin',
47
+ deprecated_rule=advanced_rbac.deprecated_admin,
48
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
49
+
50
+ # Note: 'is_admin:True' is a policy rule that takes into account the
51
+ # auth_strategy == noauth configuration setting.
52
+ # It is equivalent to 'rule:context_is_admin or {auth_strategy == noauth}'
53
+
54
+ policy.RuleDefault(
55
+ name='load-balancer:global_observer',
56
+ check_str='role:admin',
57
+ deprecated_rule=advanced_rbac.deprecated_global_observer,
58
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
59
+
60
+ policy.RuleDefault(
61
+ name='load-balancer:member_and_owner',
62
+ check_str='rule:project-member',
63
+ deprecated_rule=advanced_rbac.deprecated_member_and_owner,
64
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
65
+
66
+ policy.RuleDefault(
67
+ name='load-balancer:observer_and_owner',
68
+ check_str='rule:project-reader',
69
+ deprecated_rule=advanced_rbac.deprecated_observer_and_owner,
70
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
71
+
72
+ policy.RuleDefault(
73
+ name='load-balancer:quota-admin',
74
+ check_str='role:admin',
75
+ deprecated_rule=advanced_rbac.deprecated_quota_admin,
76
+ scope_types=[constants.RBAC_SCOPE_PROJECT]),
77
+ ]
78
+
79
+
80
+ def list_rules():
81
+ return rules
@@ -34,6 +34,12 @@ rules = [
34
34
  "Create a Load Balancer",
35
35
  [{'method': 'POST', 'path': '/v2/lbaas/loadbalancers'}]
36
36
  ),
37
+ policy.DocumentedRuleDefault(
38
+ f'{constants.RBAC_LOADBALANCER}{constants.RBAC_POST}:vip_sg_ids',
39
+ constants.RULE_API_WRITE,
40
+ "Create a Load Balancer with VIP Security Groups",
41
+ [{'method': 'POST', 'path': '/v2/lbaas/loadbalancers'}]
42
+ ),
37
43
  policy.DocumentedRuleDefault(
38
44
  f'{constants.RBAC_LOADBALANCER}{constants.RBAC_GET_ONE}',
39
45
  constants.RULE_API_READ,
@@ -48,6 +54,13 @@ rules = [
48
54
  [{'method': 'PUT',
49
55
  'path': '/v2/lbaas/loadbalancers/{loadbalancer_id}'}]
50
56
  ),
57
+ policy.DocumentedRuleDefault(
58
+ f'{constants.RBAC_LOADBALANCER}{constants.RBAC_PUT}:vip_sg_ids',
59
+ constants.RULE_API_WRITE,
60
+ "Update the VIP Security Groups of a Load Balancer",
61
+ [{'method': 'PUT',
62
+ 'path': '/v2/lbaas/loadbalancers/{loadbalancer_id}'}]
63
+ ),
51
64
  policy.DocumentedRuleDefault(
52
65
  f'{constants.RBAC_LOADBALANCER}{constants.RBAC_DELETE}',
53
66
  constants.RULE_API_WRITE,
@@ -139,7 +139,8 @@ MOCK_NEUTRON_PORT = Port(**{'network_id': MOCK_NETWORK_ID,
139
139
  'mac_address': MOCK_MAC_ADDR,
140
140
  'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS,
141
141
  'subnet_id': MOCK_SUBNET_ID}],
142
- 'security_groups': [MOCK_SECURITY_GROUP_ID]})
142
+ 'security_groups': [MOCK_SECURITY_GROUP_ID],
143
+ 'binding_vnic_type': constants.VNIC_TYPE_NORMAL})
143
144
  MOCK_NEUTRON_QOS_POLICY_ID = 'mock-qos-id'
144
145
  MOCK_QOS_POLICY_ID1 = 'qos1-id'
145
146
  MOCK_QOS_POLICY_ID2 = 'qos2-id'