From 37c99a575bd8165704b2786dc1ebe5b82d4494cb Mon Sep 17 00:00:00 2001 From: Stephen Balukoff Date: Wed, 9 Mar 2016 15:51:31 -0800 Subject: [PATCH] Use rfc3986 module for URL validations Change-Id: I9466490b17e38a6653f85a6d1ceba7d10aa59a62 Closes-Bug: #1548919 --- octavia/common/constants.py | 3 --- octavia/common/validate.py | 10 ++++++++-- octavia/tests/unit/common/test_validations.py | 4 ++++ requirements.txt | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/octavia/common/constants.py b/octavia/common/constants.py index 4cb9ef0674..7546a09e30 100644 --- a/octavia/common/constants.py +++ b/octavia/common/constants.py @@ -116,9 +116,6 @@ MAX_POLICY_POSITION = 2147483647 # 53 rules per policy MAX_L7RULES_PER_L7POLICY = 50 -URL_REGEX = (r'\Ahttp[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|' - r'(?:%[0-9a-fA-F][0-9a-fA-F]))+') - # See RFCs 2616, 2965, 6265, 7230: Should match characters valid in a # http header or cookie name. HTTP_HEADER_NAME_REGEX = r'\A[a-zA-Z0-9!#$%&\'*+-.^_`|~]+\Z' diff --git a/octavia/common/validate.py b/octavia/common/validate.py index 4762f6b359..a093e48a21 100644 --- a/octavia/common/validate.py +++ b/octavia/common/validate.py @@ -20,6 +20,7 @@ Defined here so these can also be used at deeper levels than the API. import re +import rfc3986 from octavia.common import constants from octavia.common import exceptions @@ -27,8 +28,13 @@ from octavia.common import exceptions def url(url): """Raises an error if the url doesn't look like a URL.""" - p = re.compile(constants.URL_REGEX) - if not p.match(url): + try: + if not rfc3986.is_valid_uri(url, require_scheme=True): + raise exceptions.InvalidURL(url=url) + p_url = rfc3986.urlparse(rfc3986.normalize_uri(url)) + if p_url.scheme != 'http' and p_url.scheme != 'https': + raise exceptions.InvalidURL(url=url) + except Exception: raise exceptions.InvalidURL(url=url) return True diff --git a/octavia/tests/unit/common/test_validations.py b/octavia/tests/unit/common/test_validations.py index 5362bb7960..2af5789791 100644 --- a/octavia/tests/unit/common/test_validations.py +++ b/octavia/tests/unit/common/test_validations.py @@ -29,6 +29,10 @@ class TestValidations(base.TestCase): def test_validate_bad_url(self): self.assertRaises(exceptions.InvalidURL, validate.url, 'bad url') + def test_validate_url_bad_schema(self): + self.assertRaises(exceptions.InvalidURL, validate.url, + 'ssh://www.example.com/') + def test_validate_header_name(self): ret = validate.header_name('Some-header') self.assertTrue(ret) diff --git a/requirements.txt b/requirements.txt index 6a9da0f0e1..0ca772a359 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,7 @@ SQLAlchemy<1.1.0,>=1.0.10 # MIT Babel>=1.3 # BSD eventlet!=0.18.3,>=0.18.2 # MIT requests!=2.9.0,>=2.8.1 # Apache-2.0 +rfc3986>=0.2.0 # Apache-2.0 keystoneauth1>=2.1.0 # Apache-2.0 keystonemiddleware!=4.1.0,>=4.0.0 # Apache-2.0 python-neutronclient!=4.1.0,>=2.6.0 # Apache-2.0