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:
Michael Johnson 2017-06-20 14:35:01 -07:00
parent 7fa12cee40
commit aea4f266ee
5 changed files with 476 additions and 8 deletions

View File

@ -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(

View File

@ -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)

View File

@ -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(),

View File

@ -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

View File

@ -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()),