Add RBAC enforcement to health monitors v2 API
This patch adds policies and enforcement to the Octavia v2 API for health monitors. Change-Id: I5bd48b0f451b1543fd9710c949d44d2c159ef91f Partial-Bug: #1690481
This commit is contained in:
parent
7fa12cee40
commit
aea4f266ee
|
@ -58,6 +58,13 @@ class HealthMonitorController(base.BaseController):
|
||||||
"""Gets a single healthmonitor's details."""
|
"""Gets a single healthmonitor's details."""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
db_hm = self._get_db_hm(context.session, id)
|
db_hm = self._get_db_hm(context.session, id)
|
||||||
|
|
||||||
|
# Check that the user is authorized to show this health monitor
|
||||||
|
action = '{rbac_obj}{action}'.format(
|
||||||
|
rbac_obj=constants.RBAC_HEALTHMONITOR, action='get_one')
|
||||||
|
target = {'project_id': db_hm.project_id}
|
||||||
|
context.policy.authorize(action, target)
|
||||||
|
|
||||||
result = self._convert_db_to_type(
|
result = self._convert_db_to_type(
|
||||||
db_hm, hm_types.HealthMonitorResponse)
|
db_hm, hm_types.HealthMonitorResponse)
|
||||||
return hm_types.HealthMonitorRootResponse(healthmonitor=result)
|
return hm_types.HealthMonitorRootResponse(healthmonitor=result)
|
||||||
|
@ -68,17 +75,31 @@ class HealthMonitorController(base.BaseController):
|
||||||
"""Gets all health monitors."""
|
"""Gets all health monitors."""
|
||||||
pcontext = pecan.request.context
|
pcontext = pecan.request.context
|
||||||
context = pcontext.get('octavia_context')
|
context = pcontext.get('octavia_context')
|
||||||
if context.is_admin or CONF.auth_strategy == constants.NOAUTH:
|
|
||||||
if project_id:
|
# Check if user is authorized to list health mons under all projects
|
||||||
project_id = {'project_id': project_id}
|
action = '{rbac_obj}{action}'.format(
|
||||||
else:
|
rbac_obj=constants.RBAC_HEALTHMONITOR, action='get_all-global')
|
||||||
project_id = {}
|
target = {'project_id': project_id}
|
||||||
|
if not context.policy.authorize(action, target, do_raise=False):
|
||||||
|
# Not a global observer or admin
|
||||||
|
if project_id is None:
|
||||||
|
project_id = context.project_id
|
||||||
|
|
||||||
|
# Check that the user is authorized to list lbs under this project
|
||||||
|
action = '{rbac_obj}{action}'.format(
|
||||||
|
rbac_obj=constants.RBAC_HEALTHMONITOR, action='get_all')
|
||||||
|
target = {'project_id': project_id}
|
||||||
|
context.policy.authorize(action, target)
|
||||||
|
|
||||||
|
if project_id is None:
|
||||||
|
query_filter = {}
|
||||||
else:
|
else:
|
||||||
project_id = {'project_id': context.project_id}
|
query_filter = {'project_id': project_id}
|
||||||
|
|
||||||
db_hm, links = self.repositories.health_monitor.get_all(
|
db_hm, links = self.repositories.health_monitor.get_all(
|
||||||
context.session, show_deleted=False,
|
context.session, show_deleted=False,
|
||||||
pagination_helper=pcontext.get(constants.PAGINATION_HELPER),
|
pagination_helper=pcontext.get(constants.PAGINATION_HELPER),
|
||||||
**project_id)
|
**query_filter)
|
||||||
result = self._convert_db_to_type(
|
result = self._convert_db_to_type(
|
||||||
db_hm, [hm_types.HealthMonitorResponse])
|
db_hm, [hm_types.HealthMonitorResponse])
|
||||||
return hm_types.HealthMonitorsRootResponse(
|
return hm_types.HealthMonitorsRootResponse(
|
||||||
|
@ -163,6 +184,12 @@ class HealthMonitorController(base.BaseController):
|
||||||
pool = self._get_db_pool(context.session, health_monitor.pool_id)
|
pool = self._get_db_pool(context.session, health_monitor.pool_id)
|
||||||
health_monitor.project_id = pool.project_id
|
health_monitor.project_id = pool.project_id
|
||||||
|
|
||||||
|
# Check that the user is authorized to create under this project
|
||||||
|
action = '{rbac_obj}{action}'.format(
|
||||||
|
rbac_obj=constants.RBAC_HEALTHMONITOR, action='post')
|
||||||
|
target = {'project_id': health_monitor.project_id}
|
||||||
|
context.policy.authorize(action, target)
|
||||||
|
|
||||||
lock_session = db_api.get_session(autocommit=False)
|
lock_session = db_api.get_session(autocommit=False)
|
||||||
if self.repositories.check_quota_met(
|
if self.repositories.check_quota_met(
|
||||||
context.session,
|
context.session,
|
||||||
|
@ -198,6 +225,13 @@ class HealthMonitorController(base.BaseController):
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
health_monitor = health_monitor_.healthmonitor
|
health_monitor = health_monitor_.healthmonitor
|
||||||
db_hm = self._get_db_hm(context.session, id)
|
db_hm = self._get_db_hm(context.session, id)
|
||||||
|
|
||||||
|
# Check that the user is authorized to update this health monitor
|
||||||
|
action = '{rbac_obj}{action}'.format(
|
||||||
|
rbac_obj=constants.RBAC_HEALTHMONITOR, action='put')
|
||||||
|
target = {'project_id': db_hm.project_id}
|
||||||
|
context.policy.authorize(action, target)
|
||||||
|
|
||||||
self._test_lb_and_listener_and_pool_statuses(context.session, db_hm)
|
self._test_lb_and_listener_and_pool_statuses(context.session, db_hm)
|
||||||
|
|
||||||
self.repositories.health_monitor.update(
|
self.repositories.health_monitor.update(
|
||||||
|
@ -227,6 +261,13 @@ class HealthMonitorController(base.BaseController):
|
||||||
"""Deletes a health monitor."""
|
"""Deletes a health monitor."""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
db_hm = self._get_db_hm(context.session, id)
|
db_hm = self._get_db_hm(context.session, id)
|
||||||
|
|
||||||
|
# Check that the user is authorized to delete this health monitor
|
||||||
|
action = '{rbac_obj}{action}'.format(
|
||||||
|
rbac_obj=constants.RBAC_HEALTHMONITOR, action='delete')
|
||||||
|
target = {'project_id': db_hm.project_id}
|
||||||
|
context.policy.authorize(action, target)
|
||||||
|
|
||||||
self._test_lb_and_listener_and_pool_statuses(context.session, db_hm)
|
self._test_lb_and_listener_and_pool_statuses(context.session, db_hm)
|
||||||
|
|
||||||
self.repositories.health_monitor.update(
|
self.repositories.health_monitor.update(
|
||||||
|
|
|
@ -432,3 +432,4 @@ RBAC_LOADBALANCER = '{}:loadbalancer:'.format(LOADBALANCER_API)
|
||||||
RBAC_LISTENER = '{}:listener:'.format(LOADBALANCER_API)
|
RBAC_LISTENER = '{}:listener:'.format(LOADBALANCER_API)
|
||||||
RBAC_POOL = '{}:pool:'.format(LOADBALANCER_API)
|
RBAC_POOL = '{}:pool:'.format(LOADBALANCER_API)
|
||||||
RBAC_MEMBER = '{}:member:'.format(LOADBALANCER_API)
|
RBAC_MEMBER = '{}:member:'.format(LOADBALANCER_API)
|
||||||
|
RBAC_HEALTHMONITOR = '{}:healthmonitor:'.format(LOADBALANCER_API)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from octavia.policies import base
|
from octavia.policies import base
|
||||||
|
from octavia.policies import healthmonitor
|
||||||
from octavia.policies import listener
|
from octavia.policies import listener
|
||||||
from octavia.policies import loadbalancer
|
from octavia.policies import loadbalancer
|
||||||
from octavia.policies import member
|
from octavia.policies import member
|
||||||
|
@ -23,6 +24,7 @@ from octavia.policies import pool
|
||||||
def list_rules():
|
def list_rules():
|
||||||
return itertools.chain(
|
return itertools.chain(
|
||||||
base.list_rules(),
|
base.list_rules(),
|
||||||
|
healthmonitor.list_rules(),
|
||||||
listener.list_rules(),
|
listener.list_rules(),
|
||||||
loadbalancer.list_rules(),
|
loadbalancer.list_rules(),
|
||||||
member.list_rules(),
|
member.list_rules(),
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Copyright 2017 Rackspace, US Inc.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
rules = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
||||||
|
action='get_all'),
|
||||||
|
constants.RULE_API_READ,
|
||||||
|
"List Health Monitors of a Pool",
|
||||||
|
[{'method': 'GET', 'path': '/v2.0/lbaas/healthmonitors'}]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
||||||
|
action='get_all-global'),
|
||||||
|
constants.RULE_API_READ_GLOBAL,
|
||||||
|
"List Health Monitors including resources owned by others",
|
||||||
|
[{'method': 'GET', 'path': '/v2.0/lbaas/healthmonitors'}]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
||||||
|
action='post'),
|
||||||
|
constants.RULE_API_WRITE,
|
||||||
|
"Create a Health Monitor",
|
||||||
|
[{'method': 'POST', 'path': '/v2.0/lbaas/healthmonitors'}]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
||||||
|
action='get_one'),
|
||||||
|
constants.RULE_API_READ,
|
||||||
|
"Show Health Monitor details",
|
||||||
|
[{'method': 'GET',
|
||||||
|
'path': '/v2.0/lbaas/healthmonitors/{healthmonitor_id}'}]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
||||||
|
action='put'),
|
||||||
|
constants.RULE_API_WRITE,
|
||||||
|
"Update a Health Monitor",
|
||||||
|
[{'method': 'PUT',
|
||||||
|
'path': '/v2.0/lbaas/healthmonitors/{healthmonitor_id}'}]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
||||||
|
action='delete'),
|
||||||
|
constants.RULE_API_WRITE,
|
||||||
|
"Remove a Health Monitor",
|
||||||
|
[{'method': 'DELETE',
|
||||||
|
'path': '/v2.0/lbaas/healthmonitors/{healthmonitor_id}'}]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return rules
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_config import fixture as oslo_fixture
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
from octavia.common import constants
|
from octavia.common import constants
|
||||||
|
@ -33,6 +35,7 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
self.lb = self.create_load_balancer(
|
self.lb = self.create_load_balancer(
|
||||||
uuidutils.generate_uuid()).get('loadbalancer')
|
uuidutils.generate_uuid()).get('loadbalancer')
|
||||||
self.lb_id = self.lb.get('id')
|
self.lb_id = self.lb.get('id')
|
||||||
|
self.project_id = self.lb.get('project_id')
|
||||||
self.set_lb_status(self.lb_id)
|
self.set_lb_status(self.lb_id)
|
||||||
self.listener = self.create_listener(
|
self.listener = self.create_listener(
|
||||||
constants.PROTOCOL_HTTP, 80,
|
constants.PROTOCOL_HTTP, 80,
|
||||||
|
@ -64,6 +67,65 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
response.pop('updated_at')
|
response.pop('updated_at')
|
||||||
self.assertEqual(api_hm, response)
|
self.assertEqual(api_hm, response)
|
||||||
|
|
||||||
|
def test_get_authorized(self):
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_id, constants.HEALTH_MONITOR_HTTP,
|
||||||
|
1, 1, 1, 1).get(self.root_tag)
|
||||||
|
# Set status to ACTIVE/ONLINE because set_lb_status did it in the db
|
||||||
|
api_hm['provisioning_status'] = constants.ACTIVE
|
||||||
|
api_hm['operating_status'] = constants.ONLINE
|
||||||
|
api_hm.pop('updated_at')
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
self.project_id):
|
||||||
|
override_credentials = {
|
||||||
|
'service_user_id': None,
|
||||||
|
'user_domain_id': None,
|
||||||
|
'is_admin_project': True,
|
||||||
|
'service_project_domain_id': None,
|
||||||
|
'service_project_id': None,
|
||||||
|
'roles': ['load-balancer_member'],
|
||||||
|
'user_id': None,
|
||||||
|
'is_admin': False,
|
||||||
|
'service_user_domain_id': None,
|
||||||
|
'project_domain_id': None,
|
||||||
|
'service_roles': [],
|
||||||
|
'project_id': self.project_id}
|
||||||
|
with mock.patch(
|
||||||
|
"oslo_context.context.RequestContext.to_policy_values",
|
||||||
|
return_value=override_credentials):
|
||||||
|
|
||||||
|
response = self.get(self.HM_PATH.format(
|
||||||
|
healthmonitor_id=api_hm.get('id'))).json.get(self.root_tag)
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
|
||||||
|
response.pop('updated_at')
|
||||||
|
self.assertEqual(api_hm, response)
|
||||||
|
|
||||||
|
def test_get_not_authorized(self):
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_id, constants.HEALTH_MONITOR_HTTP,
|
||||||
|
1, 1, 1, 1).get(self.root_tag)
|
||||||
|
# Set status to ACTIVE/ONLINE because set_lb_status did it in the db
|
||||||
|
api_hm['provisioning_status'] = constants.ACTIVE
|
||||||
|
api_hm['operating_status'] = constants.ONLINE
|
||||||
|
api_hm.pop('updated_at')
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
uuidutils.generate_uuid()):
|
||||||
|
response = self.get(self.HM_PATH.format(
|
||||||
|
healthmonitor_id=api_hm.get('id')), status=401)
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assertEqual(self.NOT_AUTHORIZED_BODY, response.json)
|
||||||
|
|
||||||
def test_get_hides_deleted(self):
|
def test_get_hides_deleted(self):
|
||||||
api_hm = self.create_health_monitor(
|
api_hm = self.create_health_monitor(
|
||||||
self.pool_id, constants.HEALTH_MONITOR_HTTP,
|
self.pool_id, constants.HEALTH_MONITOR_HTTP,
|
||||||
|
@ -92,6 +154,21 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
self.assertEqual(1, len(hms))
|
self.assertEqual(1, len(hms))
|
||||||
self.assertEqual(api_hm.get('id'), hms[0].get('id'))
|
self.assertEqual(api_hm.get('id'), hms[0].get('id'))
|
||||||
|
|
||||||
|
def test_get_all_not_authorized(self):
|
||||||
|
self.create_health_monitor(
|
||||||
|
self.pool_id, constants.HEALTH_MONITOR_HTTP,
|
||||||
|
1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
uuidutils.generate_uuid()):
|
||||||
|
hms = self.get(self.HMS_PATH, status=401).json
|
||||||
|
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assertEqual(self.NOT_AUTHORIZED_BODY, hms)
|
||||||
|
|
||||||
def test_get_all_admin(self):
|
def test_get_all_admin(self):
|
||||||
project_id = uuidutils.generate_uuid()
|
project_id = uuidutils.generate_uuid()
|
||||||
lb1 = self.create_load_balancer(uuidutils.generate_uuid(), name='lb1',
|
lb1 = self.create_load_balancer(uuidutils.generate_uuid(), name='lb1',
|
||||||
|
@ -160,13 +237,90 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
self.conf.config(auth_strategy=constants.KEYSTONE)
|
self.conf.config(auth_strategy=constants.KEYSTONE)
|
||||||
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
hm3['project_id']):
|
hm3['project_id']):
|
||||||
hms = self.get(self.HMS_PATH).json.get(self.root_tag_list)
|
override_credentials = {
|
||||||
|
'service_user_id': None,
|
||||||
|
'user_domain_id': None,
|
||||||
|
'is_admin_project': True,
|
||||||
|
'service_project_domain_id': None,
|
||||||
|
'service_project_id': None,
|
||||||
|
'roles': ['load-balancer_member'],
|
||||||
|
'user_id': None,
|
||||||
|
'is_admin': False,
|
||||||
|
'service_user_domain_id': None,
|
||||||
|
'project_domain_id': None,
|
||||||
|
'service_roles': [],
|
||||||
|
'project_id': self.project_id}
|
||||||
|
with mock.patch(
|
||||||
|
"oslo_context.context.RequestContext.to_policy_values",
|
||||||
|
return_value=override_credentials):
|
||||||
|
hms = self.get(self.HMS_PATH).json.get(self.root_tag_list)
|
||||||
self.conf.config(auth_strategy=auth_strategy)
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
|
||||||
self.assertEqual(1, len(hms))
|
self.assertEqual(1, len(hms))
|
||||||
hm_id_protocols = [(hm.get('id'), hm.get('type')) for hm in hms]
|
hm_id_protocols = [(hm.get('id'), hm.get('type')) for hm in hms]
|
||||||
self.assertIn((hm3.get('id'), hm3.get('type')), hm_id_protocols)
|
self.assertIn((hm3.get('id'), hm3.get('type')), hm_id_protocols)
|
||||||
|
|
||||||
|
def test_get_all_non_admin_global_observer(self):
|
||||||
|
project_id = uuidutils.generate_uuid()
|
||||||
|
lb1 = self.create_load_balancer(uuidutils.generate_uuid(), name='lb1',
|
||||||
|
project_id=project_id)
|
||||||
|
lb1_id = lb1.get('loadbalancer').get('id')
|
||||||
|
self.set_lb_status(lb1_id)
|
||||||
|
pool1 = self.create_pool(
|
||||||
|
lb1_id, constants.PROTOCOL_HTTP,
|
||||||
|
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||||
|
self.set_lb_status(lb1_id)
|
||||||
|
pool2 = self.create_pool(
|
||||||
|
lb1_id, constants.PROTOCOL_HTTPS,
|
||||||
|
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||||
|
self.set_lb_status(lb1_id)
|
||||||
|
pool3 = self.create_pool(
|
||||||
|
lb1_id, constants.PROTOCOL_TCP,
|
||||||
|
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||||
|
self.set_lb_status(lb1_id)
|
||||||
|
hm1 = self.create_health_monitor(
|
||||||
|
pool1.get('id'), constants.HEALTH_MONITOR_HTTP,
|
||||||
|
1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(lb1_id)
|
||||||
|
hm2 = self.create_health_monitor(
|
||||||
|
pool2.get('id'), constants.HEALTH_MONITOR_PING,
|
||||||
|
1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(lb1_id)
|
||||||
|
hm3 = self.create_health_monitor(
|
||||||
|
pool3.get('id'), constants.HEALTH_MONITOR_TCP,
|
||||||
|
1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(lb1_id)
|
||||||
|
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.KEYSTONE)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
hm3['project_id']):
|
||||||
|
override_credentials = {
|
||||||
|
'service_user_id': None,
|
||||||
|
'user_domain_id': None,
|
||||||
|
'is_admin_project': True,
|
||||||
|
'service_project_domain_id': None,
|
||||||
|
'service_project_id': None,
|
||||||
|
'roles': ['load-balancer_global_observer'],
|
||||||
|
'user_id': None,
|
||||||
|
'is_admin': False,
|
||||||
|
'service_user_domain_id': None,
|
||||||
|
'project_domain_id': None,
|
||||||
|
'service_roles': [],
|
||||||
|
'project_id': self.project_id}
|
||||||
|
with mock.patch(
|
||||||
|
"oslo_context.context.RequestContext.to_policy_values",
|
||||||
|
return_value=override_credentials):
|
||||||
|
|
||||||
|
hms = self.get(self.HMS_PATH).json.get(self.root_tag_list)
|
||||||
|
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assertEqual(3, len(hms))
|
||||||
|
hm_id_protocols = [(hm.get('id'), hm.get('type')) for hm in hms]
|
||||||
|
self.assertIn((hm1.get('id'), hm1.get('type')), hm_id_protocols)
|
||||||
|
self.assertIn((hm2.get('id'), hm2.get('type')), hm_id_protocols)
|
||||||
|
self.assertIn((hm3.get('id'), hm3.get('type')), hm_id_protocols)
|
||||||
|
|
||||||
def test_get_by_project_id(self):
|
def test_get_by_project_id(self):
|
||||||
project1_id = uuidutils.generate_uuid()
|
project1_id = uuidutils.generate_uuid()
|
||||||
project2_id = uuidutils.generate_uuid()
|
project2_id = uuidutils.generate_uuid()
|
||||||
|
@ -362,6 +516,68 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
self.assertEqual('/', api_hm.get('url_path'))
|
self.assertEqual('/', api_hm.get('url_path'))
|
||||||
self.assertEqual('200', api_hm.get('expected_codes'))
|
self.assertEqual('200', api_hm.get('expected_codes'))
|
||||||
|
|
||||||
|
def test_create_authorized(self):
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
self.project_id):
|
||||||
|
override_credentials = {
|
||||||
|
'service_user_id': None,
|
||||||
|
'user_domain_id': None,
|
||||||
|
'is_admin_project': True,
|
||||||
|
'service_project_domain_id': None,
|
||||||
|
'service_project_id': None,
|
||||||
|
'roles': ['load-balancer_member'],
|
||||||
|
'user_id': None,
|
||||||
|
'is_admin': False,
|
||||||
|
'service_user_domain_id': None,
|
||||||
|
'project_domain_id': None,
|
||||||
|
'service_roles': [],
|
||||||
|
'project_id': self.project_id}
|
||||||
|
with mock.patch(
|
||||||
|
"oslo_context.context.RequestContext.to_policy_values",
|
||||||
|
return_value=override_credentials):
|
||||||
|
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_id, constants.HEALTH_MONITOR_HTTP,
|
||||||
|
1, 1, 1, 1).get(self.root_tag)
|
||||||
|
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assert_correct_status(
|
||||||
|
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||||
|
pool_id=self.pool_id, hm_id=api_hm.get('id'),
|
||||||
|
lb_prov_status=constants.PENDING_UPDATE,
|
||||||
|
listener_prov_status=constants.ACTIVE,
|
||||||
|
pool_prov_status=constants.PENDING_UPDATE,
|
||||||
|
hm_prov_status=constants.PENDING_CREATE,
|
||||||
|
hm_op_status=constants.OFFLINE)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
self.assertEqual(constants.HEALTH_MONITOR_HTTP, api_hm.get('type'))
|
||||||
|
self.assertEqual(1, api_hm.get('delay'))
|
||||||
|
self.assertEqual(1, api_hm.get('timeout'))
|
||||||
|
self.assertEqual(1, api_hm.get('max_retries_down'))
|
||||||
|
self.assertEqual(1, api_hm.get('max_retries'))
|
||||||
|
# Verify optional field defaults
|
||||||
|
self.assertEqual('GET', api_hm.get('http_method'))
|
||||||
|
self.assertEqual('/', api_hm.get('url_path'))
|
||||||
|
self.assertEqual('200', api_hm.get('expected_codes'))
|
||||||
|
|
||||||
|
def test_create_not_authorized(self):
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
uuidutils.generate_uuid()):
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_id, constants.HEALTH_MONITOR_HTTP,
|
||||||
|
1, 1, 1, 1, status=401)
|
||||||
|
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assertEqual(self.NOT_AUTHORIZED_BODY, api_hm)
|
||||||
|
|
||||||
def test_create_with_listener(self):
|
def test_create_with_listener(self):
|
||||||
api_hm = self.create_health_monitor(
|
api_hm = self.create_health_monitor(
|
||||||
self.pool_with_listener_id, constants.HEALTH_MONITOR_HTTP,
|
self.pool_with_listener_id, constants.HEALTH_MONITOR_HTTP,
|
||||||
|
@ -465,6 +681,72 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
pool_prov_status=constants.PENDING_UPDATE,
|
pool_prov_status=constants.PENDING_UPDATE,
|
||||||
hm_prov_status=constants.PENDING_UPDATE)
|
hm_prov_status=constants.PENDING_UPDATE)
|
||||||
|
|
||||||
|
def test_update_authorized(self):
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_with_listener_id,
|
||||||
|
constants.HEALTH_MONITOR_HTTP, 1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
new_hm = {'max_retries': 2}
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
self.project_id):
|
||||||
|
override_credentials = {
|
||||||
|
'service_user_id': None,
|
||||||
|
'user_domain_id': None,
|
||||||
|
'is_admin_project': True,
|
||||||
|
'service_project_domain_id': None,
|
||||||
|
'service_project_id': None,
|
||||||
|
'roles': ['load-balancer_member'],
|
||||||
|
'user_id': None,
|
||||||
|
'is_admin': False,
|
||||||
|
'service_user_domain_id': None,
|
||||||
|
'project_domain_id': None,
|
||||||
|
'service_roles': [],
|
||||||
|
'project_id': self.project_id}
|
||||||
|
with mock.patch(
|
||||||
|
"oslo_context.context.RequestContext.to_policy_values",
|
||||||
|
return_value=override_credentials):
|
||||||
|
|
||||||
|
self.put(
|
||||||
|
self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||||
|
self._build_body(new_hm))
|
||||||
|
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assert_correct_status(
|
||||||
|
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||||
|
pool_id=self.pool_with_listener_id, hm_id=api_hm.get('id'),
|
||||||
|
lb_prov_status=constants.PENDING_UPDATE,
|
||||||
|
listener_prov_status=constants.PENDING_UPDATE,
|
||||||
|
pool_prov_status=constants.PENDING_UPDATE,
|
||||||
|
hm_prov_status=constants.PENDING_UPDATE)
|
||||||
|
|
||||||
|
def test_update_not_authorized(self):
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_with_listener_id,
|
||||||
|
constants.HEALTH_MONITOR_HTTP, 1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
new_hm = {'max_retries': 2}
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
uuidutils.generate_uuid()):
|
||||||
|
response = self.put(
|
||||||
|
self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||||
|
self._build_body(new_hm), status=401)
|
||||||
|
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assertEqual(self.NOT_AUTHORIZED_BODY, response.json)
|
||||||
|
self.assert_correct_status(
|
||||||
|
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||||
|
pool_id=self.pool_with_listener_id, hm_id=api_hm.get('id'),
|
||||||
|
lb_prov_status=constants.ACTIVE,
|
||||||
|
listener_prov_status=constants.ACTIVE,
|
||||||
|
pool_prov_status=constants.ACTIVE,
|
||||||
|
hm_prov_status=constants.ACTIVE)
|
||||||
|
|
||||||
def test_bad_update(self):
|
def test_bad_update(self):
|
||||||
self.skip("This test will need reviewed after a validation layer is "
|
self.skip("This test will need reviewed after a validation layer is "
|
||||||
"built")
|
"built")
|
||||||
|
@ -511,6 +793,81 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
pool_prov_status=constants.PENDING_UPDATE,
|
pool_prov_status=constants.PENDING_UPDATE,
|
||||||
hm_prov_status=constants.PENDING_DELETE)
|
hm_prov_status=constants.PENDING_DELETE)
|
||||||
|
|
||||||
|
def test_delete_authorized(self):
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_with_listener_id,
|
||||||
|
constants.HEALTH_MONITOR_HTTP, 1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
hm = self.get(self.HM_PATH.format(
|
||||||
|
healthmonitor_id=api_hm.get('id'))).json.get(self.root_tag)
|
||||||
|
api_hm['provisioning_status'] = constants.ACTIVE
|
||||||
|
api_hm['operating_status'] = constants.ONLINE
|
||||||
|
self.assertIsNone(api_hm.pop('updated_at'))
|
||||||
|
self.assertIsNotNone(hm.pop('updated_at'))
|
||||||
|
self.assertEqual(api_hm, hm)
|
||||||
|
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
self.project_id):
|
||||||
|
override_credentials = {
|
||||||
|
'service_user_id': None,
|
||||||
|
'user_domain_id': None,
|
||||||
|
'is_admin_project': True,
|
||||||
|
'service_project_domain_id': None,
|
||||||
|
'service_project_id': None,
|
||||||
|
'roles': ['load-balancer_member'],
|
||||||
|
'user_id': None,
|
||||||
|
'is_admin': False,
|
||||||
|
'service_user_domain_id': None,
|
||||||
|
'project_domain_id': None,
|
||||||
|
'service_roles': [],
|
||||||
|
'project_id': self.project_id}
|
||||||
|
with mock.patch(
|
||||||
|
"oslo_context.context.RequestContext.to_policy_values",
|
||||||
|
return_value=override_credentials):
|
||||||
|
self.delete(
|
||||||
|
self.HM_PATH.format(healthmonitor_id=api_hm.get('id')))
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assert_correct_status(
|
||||||
|
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||||
|
pool_id=self.pool_with_listener_id, hm_id=api_hm.get('id'),
|
||||||
|
lb_prov_status=constants.PENDING_UPDATE,
|
||||||
|
listener_prov_status=constants.PENDING_UPDATE,
|
||||||
|
pool_prov_status=constants.PENDING_UPDATE,
|
||||||
|
hm_prov_status=constants.PENDING_DELETE)
|
||||||
|
|
||||||
|
def test_delete_not_authorized(self):
|
||||||
|
api_hm = self.create_health_monitor(
|
||||||
|
self.pool_with_listener_id,
|
||||||
|
constants.HEALTH_MONITOR_HTTP, 1, 1, 1, 1).get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
hm = self.get(self.HM_PATH.format(
|
||||||
|
healthmonitor_id=api_hm.get('id'))).json.get(self.root_tag)
|
||||||
|
api_hm['provisioning_status'] = constants.ACTIVE
|
||||||
|
api_hm['operating_status'] = constants.ONLINE
|
||||||
|
self.assertIsNone(api_hm.pop('updated_at'))
|
||||||
|
self.assertIsNotNone(hm.pop('updated_at'))
|
||||||
|
self.assertEqual(api_hm, hm)
|
||||||
|
|
||||||
|
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||||
|
auth_strategy = self.conf.conf.get('auth_strategy')
|
||||||
|
self.conf.config(auth_strategy=constants.TESTING)
|
||||||
|
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||||
|
uuidutils.generate_uuid()):
|
||||||
|
self.delete(
|
||||||
|
self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||||
|
status=401)
|
||||||
|
self.conf.config(auth_strategy=auth_strategy)
|
||||||
|
self.assert_correct_status(
|
||||||
|
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||||
|
pool_id=self.pool_with_listener_id, hm_id=api_hm.get('id'),
|
||||||
|
lb_prov_status=constants.ACTIVE,
|
||||||
|
listener_prov_status=constants.ACTIVE,
|
||||||
|
pool_prov_status=constants.ACTIVE,
|
||||||
|
hm_prov_status=constants.ACTIVE)
|
||||||
|
|
||||||
def test_bad_delete(self):
|
def test_bad_delete(self):
|
||||||
self.delete(
|
self.delete(
|
||||||
self.HM_PATH.format(healthmonitor_id=uuidutils.generate_uuid()),
|
self.HM_PATH.format(healthmonitor_id=uuidutils.generate_uuid()),
|
||||||
|
|
Loading…
Reference in New Issue