Prioritize policy validation

This patch makes sure that we validate RBAC compliance before
other validation tasks.

Change-Id: I670087163b265e7098af35063572d6aa9d068bb9
This commit is contained in:
Michael Johnson 2020-06-19 14:17:29 -07:00
parent 3ee9bc0d65
commit 8394633635
5 changed files with 63 additions and 56 deletions

View File

@ -196,16 +196,19 @@ class HealthMonitorController(base.BaseController):
context = pecan_request.context.get('octavia_context')
health_monitor = health_monitor_.healthmonitor
if (not CONF.api_settings.allow_ping_health_monitors and
health_monitor.type == consts.HEALTH_MONITOR_PING):
raise exceptions.DisabledOption(
option='type', value=consts.HEALTH_MONITOR_PING)
pool = self._get_db_pool(context.session, health_monitor.pool_id)
health_monitor.project_id, provider = self._get_lb_project_id_provider(
context.session, pool.load_balancer_id)
self._auth_validate_action(context, health_monitor.project_id,
consts.RBAC_POST)
if (not CONF.api_settings.allow_ping_health_monitors and
health_monitor.type == consts.HEALTH_MONITOR_PING):
raise exceptions.DisabledOption(
option='type', value=consts.HEALTH_MONITOR_PING)
if pool.protocol == consts.PROTOCOL_UDP:
self._validate_healthmonitor_request_for_udp(health_monitor)
else:
@ -215,9 +218,6 @@ class HealthMonitorController(base.BaseController):
"%(protocol)s.") % {'type': health_monitor.type,
'protocol': consts.PROTOCOL_UDP})
self._auth_validate_action(context, health_monitor.project_id,
consts.RBAC_POST)
# Load the driver early as it also provides validation
driver = driver_factory.get_driver(provider)

View File

@ -117,6 +117,7 @@ class L7PolicyController(base.BaseController):
"""Creates a l7policy on a listener."""
l7policy = l7policy_.l7policy
context = pecan_request.context.get('octavia_context')
# Verify the parent listener exists
listener_id = l7policy.listener_id
listener = self._get_db_listener(
@ -124,15 +125,16 @@ class L7PolicyController(base.BaseController):
load_balancer_id = listener.load_balancer_id
l7policy.project_id, provider = self._get_lb_project_id_provider(
context.session, load_balancer_id)
self._auth_validate_action(context, l7policy.project_id,
constants.RBAC_POST)
# Make sure any pool specified by redirect_pool_id exists
if l7policy.redirect_pool_id:
db_pool = self._get_db_pool(
context.session, l7policy.redirect_pool_id)
self._validate_protocol(listener.protocol, db_pool.protocol)
self._auth_validate_action(context, l7policy.project_id,
constants.RBAC_POST)
# Load the driver early as it also provides validation
driver = driver_factory.get_driver(provider)
@ -200,6 +202,16 @@ class L7PolicyController(base.BaseController):
def put(self, id, l7policy_):
"""Updates a l7policy."""
l7policy = l7policy_.l7policy
context = pecan_request.context.get('octavia_context')
db_l7policy = self._get_db_l7policy(context.session, id,
show_deleted=False)
load_balancer_id, listener_id = self._get_listener_and_loadbalancer_id(
db_l7policy)
project_id, provider = self._get_lb_project_id_provider(
context.session, load_balancer_id)
self._auth_validate_action(context, project_id, constants.RBAC_PUT)
l7policy_dict = validate.sanitize_l7policy_api_args(
l7policy.to_dict(render_unsets=False))
# Reset renamed attributes
@ -207,10 +219,7 @@ class L7PolicyController(base.BaseController):
if val in l7policy_dict:
l7policy_dict[attr] = l7policy_dict.pop(val)
sanitized_l7policy = l7policy_types.L7PolicyPUT(**l7policy_dict)
context = pecan_request.context.get('octavia_context')
db_l7policy = self._get_db_l7policy(context.session, id,
show_deleted=False)
listener = self._get_db_listener(
context.session, db_l7policy.listener_id)
# Make sure any specified redirect_pool_id exists
@ -218,12 +227,6 @@ class L7PolicyController(base.BaseController):
db_pool = self._get_db_pool(
context.session, l7policy_dict['redirect_pool_id'])
self._validate_protocol(listener.protocol, db_pool.protocol)
load_balancer_id, listener_id = self._get_listener_and_loadbalancer_id(
db_l7policy)
project_id, provider = self._get_lb_project_id_provider(
context.session, load_balancer_id)
self._auth_validate_action(context, project_id, constants.RBAC_PUT)
# Load the driver early as it also provides validation
driver = driver_factory.get_driver(provider)

View File

@ -123,10 +123,6 @@ class L7RuleController(base.BaseController):
def post(self, rule_):
"""Creates a l7rule on an l7policy."""
l7rule = rule_.rule
try:
validate.l7rule_data(l7rule)
except Exception as e:
raise exceptions.L7RuleValidation(error=e)
context = pecan_request.context.get('octavia_context')
db_l7policy = self._get_db_l7policy(context.session, self.l7policy_id,
@ -135,12 +131,16 @@ class L7RuleController(base.BaseController):
db_l7policy)
l7rule.project_id, provider = self._get_lb_project_id_provider(
context.session, load_balancer_id)
self._check_l7policy_max_rules(context.session)
self._auth_validate_action(context, l7rule.project_id,
constants.RBAC_POST)
try:
validate.l7rule_data(l7rule)
except Exception as e:
raise exceptions.L7RuleValidation(error=e)
self._check_l7policy_max_rules(context.session)
# Load the driver early as it also provides validation
driver = driver_factory.get_driver(provider)
@ -192,15 +192,6 @@ class L7RuleController(base.BaseController):
context = pecan_request.context.get('octavia_context')
db_l7rule = self._get_db_l7rule(context.session, id,
show_deleted=False)
# Handle the invert unset
if l7rule.invert is None:
l7rule.invert = False
new_l7rule = db_l7rule.to_dict()
new_l7rule.update(l7rule.to_dict())
new_l7rule = data_models.L7Rule.from_dict(new_l7rule)
db_l7policy = self._get_db_l7policy(context.session, self.l7policy_id,
show_deleted=False)
load_balancer_id, listener_id = self._get_listener_and_loadbalancer_id(
@ -210,6 +201,14 @@ class L7RuleController(base.BaseController):
self._auth_validate_action(context, project_id, constants.RBAC_PUT)
# Handle the invert unset
if l7rule.invert is None:
l7rule.invert = False
new_l7rule = db_l7rule.to_dict()
new_l7rule.update(l7rule.to_dict())
new_l7rule = data_models.L7Rule.from_dict(new_l7rule)
try:
validate.l7rule_data(new_l7rule)
except Exception as e:

View File

@ -146,12 +146,6 @@ class MemberController(base.BaseController):
member = member_.member
context = pecan_request.context.get('octavia_context')
validate.ip_not_reserved(member.address)
# Validate member subnet
if (member.subnet_id and
not validate.subnet_exists(member.subnet_id, context=context)):
raise exceptions.NotFound(resource='Subnet', id=member.subnet_id)
pool = self.repositories.pool.get(context.session, id=self.pool_id)
member.project_id, provider = self._get_lb_project_id_provider(
context.session, pool.load_balancer_id)
@ -159,6 +153,13 @@ class MemberController(base.BaseController):
self._auth_validate_action(context, member.project_id,
constants.RBAC_POST)
validate.ip_not_reserved(member.address)
# Validate member subnet
if (member.subnet_id and
not validate.subnet_exists(member.subnet_id, context=context)):
raise exceptions.NotFound(resource='Subnet', id=member.subnet_id)
# Load the driver early as it also provides validation
driver = driver_factory.get_driver(provider)
@ -232,7 +233,6 @@ class MemberController(base.BaseController):
context = pecan_request.context.get('octavia_context')
db_member = self._get_db_member(context.session, id,
show_deleted=False)
pool = self.repositories.pool.get(context.session,
id=db_member.pool_id)
project_id, provider = self._get_lb_project_id_provider(

View File

@ -203,22 +203,13 @@ class PoolsController(base.BaseController):
# pool_dict:
pool = pool_.pool
context = pecan_request.context.get('octavia_context')
if pool.protocol == constants.PROTOCOL_UDP:
self._validate_pool_request_for_udp(pool)
else:
if (pool.session_persistence and (
pool.session_persistence.persistence_timeout or
pool.session_persistence.persistence_granularity)):
raise exceptions.ValidationException(detail=_(
"persistence_timeout and persistence_granularity "
"is only for UDP protocol pools."))
listener = None
if pool.loadbalancer_id:
pool.project_id, provider = self._get_lb_project_id_provider(
context.session, pool.loadbalancer_id)
elif pool.listener_id:
listener = self.repositories.listener.get(
context.session, id=pool.listener_id)
self._validate_protocol(listener.protocol, pool.protocol)
pool.loadbalancer_id = listener.load_balancer_id
pool.project_id, provider = self._get_lb_project_id_provider(
context.session, pool.loadbalancer_id)
@ -230,6 +221,19 @@ class PoolsController(base.BaseController):
self._auth_validate_action(context, pool.project_id,
constants.RBAC_POST)
if pool.listener_id and listener:
self._validate_protocol(listener.protocol, pool.protocol)
if pool.protocol == constants.PROTOCOL_UDP:
self._validate_pool_request_for_udp(pool)
else:
if (pool.session_persistence and (
pool.session_persistence.persistence_timeout or
pool.session_persistence.persistence_granularity)):
raise exceptions.ValidationException(detail=_(
"persistence_timeout and persistence_granularity "
"is only for UDP protocol pools."))
if pool.session_persistence:
sp_dict = pool.session_persistence.to_dict(render_unsets=False)
validate.check_session_persistence(sp_dict)
@ -467,15 +471,16 @@ class PoolsController(base.BaseController):
"""Deletes a pool from a load balancer."""
context = pecan_request.context.get('octavia_context')
db_pool = self._get_db_pool(context.session, id, show_deleted=False)
if db_pool.l7policies:
raise exceptions.PoolInUseByL7Policy(
id=db_pool.id, l7policy_id=db_pool.l7policies[0].id)
project_id, provider = self._get_lb_project_id_provider(
context.session, db_pool.load_balancer_id)
self._auth_validate_action(context, project_id, constants.RBAC_DELETE)
if db_pool.l7policies:
raise exceptions.PoolInUseByL7Policy(
id=db_pool.id, l7policy_id=db_pool.l7policies[0].id)
# Load the driver early as it also provides validation
driver = driver_factory.get_driver(provider)