Allow blocking IPs from member addresses

This patch adds a configuration option for reserved IP addresses that
cannot be used for load balancer member addresses. By default, this will
include the nova metadata service address 169.254.169.254.

Change-Id: I25de5ed5f6f35afc55dd1154c3e02934fddb100a
Story: 2003413
Task: 24555
This commit is contained in:
Michael Johnson 2018-08-14 21:51:05 -07:00 committed by Adam Harwell
parent 91fae05a7d
commit 1ad9fd7272
6 changed files with 56 additions and 0 deletions

View File

@ -161,6 +161,9 @@
# List of network_ids that are valid for VIP creation.
# If this field empty, no validation is performed.
# valid_vip_networks =
# List of reserved IP addresses that cannot be used for member addresses
# The default is the nova metadata service address
# reserved_ips = ['169.254.169.254']
[haproxy_amphora]
# base_path = /var/lib/octavia

View File

@ -135,6 +135,9 @@ class MemberController(base.BaseController):
"""Creates a pool member on a pool."""
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):
raise exceptions.NotFound(resource='Subnet',

View File

@ -165,6 +165,12 @@ networking_opts = [
help=_('List of network_ids that are valid for VIP '
'creation. If this field is empty, no validation '
'is performed.')),
cfg.ListOpt('reserved_ips',
default=['169.254.169.254'],
item_type=cfg.types.IPAddress(),
help=_('List of IP addresses reserved from being used for '
'member addresses. IPv6 addresses should be in '
'expanded, uppercase form.')),
]
healthmanager_opts = [

View File

@ -19,11 +19,13 @@ Defined here so these can also be used at deeper levels than the API.
"""
import ipaddress
import re
import netaddr
from oslo_config import cfg
import rfc3986
import six
from octavia.common import constants
from octavia.common import exceptions
@ -322,3 +324,11 @@ def check_session_persistence(SP_dict):
except Exception:
raise exceptions.ValidationException(detail=_(
'Invalid session_persistence provided.'))
def ip_not_reserved(ip_address):
ip_address = (
ipaddress.ip_address(six.text_type(ip_address)).exploded.upper())
if ip_address in CONF.networking.reserved_ips:
raise exceptions.InvalidOption(value=ip_address,
option='member address')

View File

@ -414,3 +414,31 @@ class TestValidations(base.TestCase):
self.assertRaises(exceptions.ValidationException,
validate.check_session_persistence,
valid_cookie_name_dict)
def test_ip_not_reserved(self):
self.conf.config(group="networking", reserved_ips=['198.51.100.4'])
# Test good address
validate.ip_not_reserved('203.0.113.5')
# Test IPv4 reserved address
self.assertRaises(exceptions.InvalidOption,
validate.ip_not_reserved,
'198.51.100.4')
self.conf.config(
group="networking",
reserved_ips=['2001:0DB8:0000:0000:0000:0000:0000:0005'])
# Test good IPv6 address
validate.ip_not_reserved('2001:0DB8::9')
# Test reserved IPv6 expanded
self.assertRaises(exceptions.InvalidOption,
validate.ip_not_reserved,
'2001:0DB8:0000:0000:0000:0000:0000:0005')
# Test reserved IPv6 short hand notation
self.assertRaises(exceptions.InvalidOption,
validate.ip_not_reserved,
'2001:0DB8::5')

View File

@ -0,0 +1,6 @@
---
security:
- |
Adds a configuration option, "reserved_ips" that allows the operator to
block addresses from being used in load balancer members. The default
setting blocks the nova metadata service address.