diff options
author | Jose Plana <jplana@gmail.com> | 2013-10-07 02:09:11 +0200 |
---|---|---|
committer | Jose Plana <jplana@gmail.com> | 2013-10-09 01:02:17 +0200 |
commit | 5ea7fe2d75f99414da457a9e613f06d823537e22 (patch) | |
tree | 3d0fa243d153b81ee569df9bbd6c5421965ef2f1 /src | |
parent | adb5618971ded2d9f1005b576ff03816bf3f9035 (diff) |
CA validation implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/etcd/client.py | 16 | ||||
-rw-r--r-- | src/etcd/tests/integration/test_simple.py | 93 |
2 files changed, 107 insertions, 2 deletions
diff --git a/src/etcd/client.py b/src/etcd/client.py index 42efe57..967ca69 100644 --- a/src/etcd/client.py +++ b/src/etcd/client.py @@ -24,7 +24,8 @@ class Client(object): read_timeout=60, allow_redirect=True, protocol='http', - cert = None + cert = None, + ca_cert = None, ): """ Initialize the client. @@ -40,7 +41,10 @@ class Client(object): protocol (str): Protocol used to connect to etcd. - cert (mixed): If a string, the whole ssl client certificate; if a tuple, the cert and key file names. + cert (mixed): If a string, the whole ssl client certificate; + if a tuple, the cert and key file names. + + ca_cert (str): The ca certificate. If pressent it will enable validation. """ self._host = host @@ -85,7 +89,15 @@ class Client(object): else: #combined certificate kw['cert_file'] = cert + kw['ssl_version'] = ssl.PROTOCOL_TLSv1 + + + if ca_cert: + kw['ca_certs'] = ca_cert + kw['cert_reqs'] = ssl.CERT_REQUIRED + kw['ssl_version'] = ssl.PROTOCOL_SSLv3 + self.http = urllib3.PoolManager(num_pools=10, **kw) @property diff --git a/src/etcd/tests/integration/test_simple.py b/src/etcd/tests/integration/test_simple.py index 70d0d5c..9f31e98 100644 --- a/src/etcd/tests/integration/test_simple.py +++ b/src/etcd/tests/integration/test_simple.py @@ -302,6 +302,99 @@ class TestWatch(EtcdIntegrationTest): +class TestAuthenticatedAccess(EtcdIntegrationTest): + + @classmethod + def setUpClass(cls): + program = cls._get_exe() + cls.directory = tempfile.mkdtemp(prefix='python-etcd') + + cls.ca_cert_path = os.path.join(cls.directory, 'ca.crt') + ca_key_path = os.path.join(cls.directory, 'ca.key') + + cls.ca2_cert_path = os.path.join(cls.directory, 'ca2.crt') + ca2_key_path = os.path.join(cls.directory, 'ca2.key') + + server_cert_path = os.path.join(cls.directory, 'server.crt') + server_key_path = os.path.join(cls.directory, 'server.key') + + ca, ca_key = helpers.TestingCA.create_test_ca_certificate( + cls.ca_cert_path, ca_key_path, 'TESTCA') + + ca2, ca2_key = helpers.TestingCA.create_test_ca_certificate( + cls.ca2_cert_path, ca2_key_path, 'TESTCA2') + + helpers.TestingCA.create_test_certificate( + ca, ca_key, server_cert_path, server_key_path, '127.0.0.1') + + cls.processHelper = helpers.EtcdProcessHelper( + cls.directory, + proc_name=program, + port_range_start=6001, + internal_port_range_start=8001) + + cls.processHelper.run(number=3, + proc_args=[ + '-clientCert=%s' % server_cert_path, + '-clientKey=%s' % server_key_path + ]) + + def test_get_set_unauthenticated(self): + """ INTEGRATION: set/get a new value unauthenticated (http->https) """ + + client = etcd.Client(port=6001) + + try: + set_result = client.set('/test_set', 'test-key') + self.fail() + + except etcd.EtcdException, e: + self.assertEquals(e.message, "Unable to decode server response") + + try: + get_result = client.get('/test_set') + self.fail() + + except etcd.EtcdException, e: + self.assertEquals(e.message, "Unable to decode server response") + + def test_get_set_unauthenticated_missing_ca(self): + """ INTEGRATION: set/get a new value unauthenticated without validation (https->https) """ + + client = etcd.Client(protocol='https', port=6001) + set_result = client.set('/test_set', 'test-key') + get_result = client.get('/test_set') + + + def test_get_set_unauthenticated_with_ca(self): + """ INTEGRATION: set/get a new value unauthenticated without validation (https->https) """ + + client = etcd.Client( + protocol='https', port=6001, ca_cert = self.ca2_cert_path) + + try: + set_result = client.set('/test_set', 'test-key') + assert False + except urllib3.exceptions.SSLError, e: + assert True + + try: + get_result = client.get('/test_set') + except urllib3.exceptions.SSLError, e: + assert True + + + def test_get_set_authenticated(self): + """ INTEGRATION: set/get a new value authenticated """ + + client = etcd.Client( + port=6001, protocol='https', ca_cert = self.ca_cert_path) + + set_result = client.set('/test_set', 'test-key') + get_result = client.get('/test_set') + + + class TestClientAuthenticatedAccess(EtcdIntegrationTest): @classmethod |