From 97418019e4d9fef7826ffa0d837722dcc4f81e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Pitucha?= Date: Mon, 3 Aug 2015 15:23:07 +1000 Subject: [PATCH] Move all plugins to stevedore Move validators and authentication to stevedore backend. There should be no impact on normal usage. Configuration also remains the same. Change-Id: Iea2e772efe240656c2824e36e860d8ce5147551e --- anchor/app.py | 5 +++-- anchor/auth/__init__.py | 4 ++-- anchor/certificate_ops.py | 2 +- anchor/jsonloader.py | 9 +++++++++ setup.cfg | 20 ++++++++++++++++++++ tests/auth/test_static.py | 3 +++ tests/controllers/test_app.py | 1 + tests/test_functional.py | 16 +++++++++++----- 8 files changed, 50 insertions(+), 10 deletions(-) diff --git a/anchor/app.py b/anchor/app.py index 0568c2c..152a62e 100644 --- a/anchor/app.py +++ b/anchor/app.py @@ -23,7 +23,6 @@ from paste import translogger # noqa import pecan from anchor import jsonloader -from anchor import validators logger = logging.getLogger(__name__) @@ -163,7 +162,9 @@ def validate_registration_authority_config(ra_name, conf): ra_validators = ra_conf['validators'] for step in ra_validators.keys(): - if not hasattr(validators, step): + try: + jsonloader.conf.get_validator(step) + except KeyError: raise ConfigValidationException( "Unknown validator <{}> found (for registration " "authority {})".format(step, ra_name)) diff --git a/anchor/auth/__init__.py b/anchor/auth/__init__.py index f495ca6..5270b02 100644 --- a/anchor/auth/__init__.py +++ b/anchor/auth/__init__.py @@ -35,8 +35,8 @@ def validate(ra_name, user, secret): """ auth_conf = jsonloader.authentication_for_registration_authority(ra_name) backend_name = auth_conf['backend'] - module = globals()[backend_name] - res = module.login(ra_name, user, secret) + backend = jsonloader.conf.get_authentication(backend_name) + res = backend(ra_name, user, secret) if res: return res diff --git a/anchor/certificate_ops.py b/anchor/certificate_ops.py index 9db6451..92c4987 100644 --- a/anchor/certificate_ops.py +++ b/anchor/certificate_ops.py @@ -81,7 +81,7 @@ def _run_validator(name, body, args): # perform the actual check logger.debug("_run_validator: checking <%s> with rules: %s", name, body) try: - validator = getattr(validators, name) + validator = jsonloader.conf.get_validator(name) validator(**new_kwargs) logger.debug("_run_validator: success: <%s> ", name) return True # validator passed b/c no exceptions diff --git a/anchor/jsonloader.py b/anchor/jsonloader.py index fd8d2c9..4377c4c 100644 --- a/anchor/jsonloader.py +++ b/anchor/jsonloader.py @@ -60,10 +60,19 @@ class AnchorConf(): def load_extensions(self): self._signing_backends = stevedore.ExtensionManager( "anchor.signing_backends") + self._validators = stevedore.ExtensionManager("anchor.validators") + self._authentication = stevedore.ExtensionManager( + "anchor.authentication") def get_signing_backend(self, name): return self._signing_backends[name].plugin + def get_validator(self, name): + return self._validators[name].plugin + + def get_authentication(self, name): + return self._authentication[name].plugin + @property def config(self): '''Property to return the config dictionary diff --git a/setup.cfg b/setup.cfg index 15ca13d..32dfb7a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,6 +25,26 @@ classifier = anchor.signing_backends = anchor = anchor.certificate_ops:sign +anchor.validators = + check_domains = anchor.validators:check_domains + iter_alternative_names = anchor.validators:iter_alternative_names + check_networks = anchor.validators:check_networks + check_networks_strict = anchor.validators:check_networks_strict + common_name = anchor.validators:common_name + alternative_names = anchor.validators:alternative_names + alternative_names_ip = anchor.validators:alternative_names_ip + blacklist_names = anchor.validators:blacklist_names + server_group = anchor.validators:server_group + extensions = anchor.validators:extensions + key_usage = anchor.validators:key_usage + ca_status = anchor.validators:ca_status + source_cidrs = anchor.validators:source_cidrs + +anchor.authentication = + keystone = anchor.auth.keystone:login + ldap = anchor.auth.ldap:login + static = anchor.auth.static:login + [files] packages = anchor diff --git a/tests/auth/test_static.py b/tests/auth/test_static.py index 6959e8f..edddf3c 100644 --- a/tests/auth/test_static.py +++ b/tests/auth/test_static.py @@ -21,6 +21,7 @@ from webob import exc as http_status from anchor import auth from anchor.auth import results +from anchor import jsonloader import tests @@ -34,6 +35,7 @@ class AuthStaticTests(tests.DefaultConfigMixin, unittest.TestCase): def test_validate_static(self): """Test all static user/pass authentication paths.""" + jsonloader.conf.load_extensions() config = "anchor.jsonloader.conf._config" self.sample_conf_auth['default_auth'] = { "backend": "static", @@ -58,6 +60,7 @@ class AuthStaticTests(tests.DefaultConfigMixin, unittest.TestCase): def test_validate_static_malformed1(self): """Test static user/pass authentication with malformed config.""" + jsonloader.conf.load_extensions() config = "anchor.jsonloader.conf._config" self.sample_conf_auth['default_auth'] = {'backend': 'static'} data = self.sample_conf diff --git a/tests/controllers/test_app.py b/tests/controllers/test_app.py index a92ff6b..56a2727 100644 --- a/tests/controllers/test_app.py +++ b/tests/controllers/test_app.py @@ -29,6 +29,7 @@ import tests class TestApp(tests.DefaultConfigMixin, unittest.TestCase): def setUp(self): self.expected_key_permissions = (stat.S_IRUSR | stat.S_IFREG) + jsonloader.conf.load_extensions() super(TestApp, self).setUp() def tearDown(self): diff --git a/tests/test_functional.py b/tests/test_functional.py index 8d64499..043d9df 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -22,11 +22,12 @@ import tempfile import textwrap import unittest +import mock import pecan from pecan import testing as pecan_testing +import stevedore from anchor import jsonloader -from anchor import validators from anchor.X509 import certificate as X509_cert import config import tests @@ -154,15 +155,20 @@ class TestFunctional(tests.DefaultConfigMixin, unittest.TestCase): 'encoding': 'pem', 'csr': TestFunctional.csr_good} - def derp(**kwdargs): - raise Exception("BOOM") + derp = mock.MagicMock() + derp.side_effect = Exception("BOOM") + + derp_ext = stevedore.extension.Extension("broken_validator", None, + derp, None) + manager = jsonloader.conf._validators.make_test_instance([derp_ext]) + jsonloader.conf._validators = manager - validators.broken_validator = derp ra = jsonloader.conf.registration_authority['default_ra'] - ra['validators']["broken_validator"] = {} + ra['validators'] = {"broken_validator": {}} resp = self.app.post('/v1/sign/default_ra', data, expect_errors=True) self.assertEqual(500, resp.status_int) self.assertTrue(("Internal Validation Error running validator " "'broken_validator' for registration authority " "'default_ra'") in str(resp)) + self.assertTrue(derp.called)