summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJose Plana <jplana@gmail.com>2013-10-07 02:09:11 +0200
committerJose Plana <jplana@gmail.com>2013-10-09 01:02:17 +0200
commit5ea7fe2d75f99414da457a9e613f06d823537e22 (patch)
tree3d0fa243d153b81ee569df9bbd6c5421965ef2f1 /src
parentadb5618971ded2d9f1005b576ff03816bf3f9035 (diff)
CA validation implementation
Diffstat (limited to 'src')
-rw-r--r--src/etcd/client.py16
-rw-r--r--src/etcd/tests/integration/test_simple.py93
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