From fe09214372f199d4cfbff76aabf76470543c26f2 Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Mon, 6 Aug 2012 09:45:20 -0400 Subject: [PATCH] Enhance Base MAC validation Fixes bug 1033520 The base mac will now be validated when the configuration file is read. In addition to this the following has been done: 1. checks validaity of the base mac - for example it cannot be a multicast MAC 2. adds a framework for attributes tests Change-Id: Ibffab039ca7ee9e87eb79a7288e86401170bf129 --- quantum/api/v2/attributes.py | 3 + quantum/common/config.py | 8 +++ quantum/db/db_base_plugin_v2.py | 6 -- quantum/tests/unit/test_attributes.py | 85 +++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 quantum/tests/unit/test_attributes.py diff --git a/quantum/api/v2/attributes.py b/quantum/api/v2/attributes.py index cf5767be8..05fe29250 100644 --- a/quantum/api/v2/attributes.py +++ b/quantum/api/v2/attributes.py @@ -116,6 +116,9 @@ HEX_ELEM = '[0-9A-Fa-f]' UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}', HEX_ELEM + '{4}', HEX_ELEM + '{4}', HEX_ELEM + '{12}']) +# Note: In order to ensure that the MAC address is unicast the first byte +# must be even. +MAC_PATTERN = "^%s[aceACE02468](:%s{2}){5}$" % (HEX_ELEM, HEX_ELEM) # Dictionary that maintains a list of validation functions validators = {'type:boolean': _validate_boolean, diff --git a/quantum/common/config.py b/quantum/common/config.py index 3d70c665e..eb84e9eb4 100644 --- a/quantum/common/config.py +++ b/quantum/common/config.py @@ -26,6 +26,7 @@ import sys from paste import deploy +from quantum.api.v2 import attributes from quantum.openstack.common import cfg from quantum.version import version_string @@ -53,6 +54,13 @@ def parse(args): cfg.CONF(args=args, project='quantum', version='%%prog %s' % version_string()) + # Validate that the base_mac is of the correct format + msg = attributes._validate_regex(cfg.CONF.base_mac, + attributes.MAC_PATTERN) + if msg: + msg = "Base MAC: %s" % msg + raise Exception(msg) + def setup_logging(conf): """ diff --git a/quantum/db/db_base_plugin_v2.py b/quantum/db/db_base_plugin_v2.py index 9ad7aa37d..7b4d10e4c 100644 --- a/quantum/db/db_base_plugin_v2.py +++ b/quantum/db/db_base_plugin_v2.py @@ -49,12 +49,6 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): sql_connection = 'sqlite:///:memory:' db.configure_db({'sql_connection': sql_connection, 'base': models_v2.model_base.BASEV2}) - self._check_base_mac_format() - - def _check_base_mac_format(self): - base_mac = cfg.CONF.base_mac.split(':') - if len(base_mac) != 6: - raise Exception("illegal base_mac format %s", cfg.CONF.base_mac) def _get_tenant_id_for_create(self, context, resource): if context.is_admin and 'tenant_id' in resource: diff --git a/quantum/tests/unit/test_attributes.py b/quantum/tests/unit/test_attributes.py new file mode 100644 index 000000000..bb788b455 --- /dev/null +++ b/quantum/tests/unit/test_attributes.py @@ -0,0 +1,85 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC +# All Rights Reserved. +# +# 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. + +import unittest2 + +from quantum.api.v2 import attributes + + +class TestAttributes(unittest2.TestCase): + + def test_mac_addresses(self): + # Valid - 3 octets + base_mac = "fa:16:3e:00:00:00" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + self.assertEquals(msg, None) + + # Valid - 4 octets + base_mac = "fa:16:3e:4f:00:00" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + self.assertEquals(msg, None) + + # Invalid - not unicast + base_mac = "01:16:3e:4f:00:00" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + error = '%s is not valid' % base_mac + self.assertEquals(msg, error) + + # Invalid - invalid format + base_mac = "a:16:3e:4f:00:00" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + error = '%s is not valid' % base_mac + self.assertEquals(msg, error) + + # Invalid - invalid format + base_mac = "ffa:16:3e:4f:00:00" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + error = '%s is not valid' % base_mac + self.assertEquals(msg, error) + + # Invalid - invalid format + base_mac = "01163e4f0000" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + error = '%s is not valid' % base_mac + self.assertEquals(msg, error) + + # Invalid - invalid format + base_mac = "01-16-3e-4f-00-00" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + error = '%s is not valid' % base_mac + self.assertEquals(msg, error) + + # Invalid - invalid format + base_mac = "00:16:3:f:00:00" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + error = '%s is not valid' % base_mac + self.assertEquals(msg, error) + + # Invalid - invalid format + base_mac = "12:3:4:5:67:89ab" + msg = attributes._validate_regex(base_mac, + attributes.MAC_PATTERN) + error = '%s is not valid' % base_mac + self.assertEquals(msg, error) -- 2.45.2