From 2780854f1e206563b7451087984f729d0b748d35 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 27 Oct 2015 14:39:01 -0400 Subject: Refactor CustodiaClient interface Use the term secret and not key to refer to .. well .. secrets. Store the last response instead of returning it to the caller, this way there is a consistent way to get access to it and only as needed. Change the name to CustodiaSimpleClient in preparaion for extending the support to other Secret types. Signed-off-by: Simo Sorce --- custodia/client.py | 68 ++++++++++++++++++++++++++++++++++-------------------- tests/custodia.py | 61 ++++++++++++++++++++++++------------------------ 2 files changed, 73 insertions(+), 56 deletions(-) diff --git a/custodia/client.py b/custodia/client.py index 4a17927..221080a 100644 --- a/custodia/client.py +++ b/custodia/client.py @@ -50,6 +50,7 @@ class CustodiaHTTPClient(object): self.session.mount('http+unix://', HTTPUnixAdapter()) self.headers = dict(DEFAULT_HEADERS) self.url = url + self._last_response = None def set_simple_auth_keys(self, name, key, name_header='CUSTODIA_AUTH_ID', @@ -68,9 +69,15 @@ class CustodiaHTTPClient(object): return headers def _request(self, cmd, path, **kwargs): + self._last_response = None url = self._join_url(path) kwargs['headers'] = self._add_headers(**kwargs) - return cmd(url, **kwargs) + self._last_response = cmd(url, **kwargs) + return self._last_response + + @property + def last_response(self): + return self._last_response def delete(self, path, **kwargs): return self._request(self.session.delete, path, **kwargs) @@ -90,45 +97,56 @@ class CustodiaHTTPClient(object): def put(self, path, **kwargs): return self._request(self.session.put, path, **kwargs) + def container_name(self, name): + return name if name.endswith('/') else name + '/' + + def create_container(self, name): + raise NotImplementedError + + def list_container(self, name): + raise NotImplementedError + + def delete_container(self, name): + raise NotImplementedError + + def get_secret(self, name): + raise NotImplementedError + + def set_secret(self, name, value): + raise NotImplementedError + + def del_secret(self, name): + raise NotImplementedError + -class CustodiaClient(CustodiaHTTPClient): +class CustodiaSimpleClient(CustodiaHTTPClient): def create_container(self, name): - r = self.post(name if name.endswith('/') else name + '/') + r = self.post(self.container_name(name)) r.raise_for_status() - return r def delete_container(self, name): - r = self.delete(name if name.endswith('/') else name + '/') + r = self.delete(self.container_name(name)) r.raise_for_status() - return r def list_container(self, name): - r = self.get(name if name.endswith('/') else name + '/') + r = self.get(self.container_name(name)) r.raise_for_status() - return r + return r.json() - def get_key(self, name): + def get_secret(self, name): r = self.get(name) r.raise_for_status() - return r - - def set_key(self, name, data_to_json): - r = self.put(name, json=data_to_json) - r.raise_for_status() - return r - - def del_key(self, name): - r = self.delete(name) - r.raise_for_status() - return r - - def get_simple_key(self, name): - simple = self.get_key(name).json() + simple = r.json() ktype = simple.get("type", None) if ktype != "simple": raise TypeError("Invalid key type: %s" % ktype) return simple["value"] - def set_simple_key(self, name, value): - self.set_key(name, {"type": "simple", "value": value}) + def set_secret(self, name, value): + r = self.put(name, json={"type": "simple", "value": value}) + r.raise_for_status() + + def del_secret(self, name): + r = self.delete(name) + r.raise_for_status() diff --git a/tests/custodia.py b/tests/custodia.py index cce1c40..9db0e4b 100644 --- a/tests/custodia.py +++ b/tests/custodia.py @@ -14,7 +14,7 @@ from jwcrypto import jwk from requests.exceptions import HTTPError -from custodia.client import CustodiaClient +from custodia.client import CustodiaSimpleClient TEST_CUSTODIA_CONF = """ @@ -138,15 +138,15 @@ class CustodiaTests(unittest.TestCase): raise AssertionError( "Premature termination of Custodia server, see test_log.txt") cls.custodia_process = p - cls.client = CustodiaClient(cls.socket_url + '/secrets/uns') + cls.client = CustodiaSimpleClient(cls.socket_url + '/secrets/uns') cls.client.headers['REMOTE_USER'] = 'test' - cls.admin = CustodiaClient(cls.socket_url + '/secrets') + cls.admin = CustodiaSimpleClient(cls.socket_url + '/secrets') cls.admin.headers['REMOTE_USER'] = 'admin' - cls.fwd = CustodiaClient(cls.socket_url + '/forwarder') + cls.fwd = CustodiaSimpleClient(cls.socket_url + '/forwarder') cls.fwd.headers['REMOTE_USER'] = 'test' - cls.loop = CustodiaClient(cls.socket_url + '/forwarder_loop') + cls.loop = CustodiaSimpleClient(cls.socket_url + '/forwarder_loop') cls.loop.headers['REMOTE_USER'] = 'test' - cls.enc = CustodiaClient(cls.socket_url + '/enc') + cls.enc = CustodiaSimpleClient(cls.socket_url + '/enc') cls.enc.headers['REMOTE_USER'] = 'enc' @classmethod @@ -157,8 +157,7 @@ class CustodiaTests(unittest.TestCase): def test_0_0_setup(self): self.admin.create_container('fwd') self.admin.create_container('sak') - self.admin.set_simple_key('sak/' + self.test_auth_id, - self.test_auth_key) + self.admin.set_secret('sak/' + self.test_auth_id, self.test_auth_key) self.admin.create_container('test') def test_0_create_container(self): @@ -168,59 +167,59 @@ class CustodiaTests(unittest.TestCase): self.client.delete_container('test/container') def test_1_set_simple_key(self): - self.client.set_simple_key('test/key', 'VmVycnlTZWNyZXQK') + self.client.set_secret('test/key', 'VmVycnlTZWNyZXQK') def test_2_get_simple_key(self): - key = self.client.get_simple_key('test/key') + key = self.client.get_secret('test/key') self.assertEqual(key, 'VmVycnlTZWNyZXQK') def test_3_list_container(self): - r = self.client.list_container('test') - self.assertEqual(r.json(), ["key"]) + cl = self.client.list_container('test') + self.assertEqual(cl, ["key"]) def test_4_del_simple_key(self): - self.client.del_key('test/key') + self.client.del_secret('test/key') try: - self.client.get_key('test/key') - except HTTPError as e: - self.assertEqual(e.response.status_code, 404) + self.client.get_secret('test/key') + except HTTPError: + self.assertEqual(self.client.last_response.status_code, 404) def test_5_list_empty(self): - r = self.client.list_container('test') - self.assertEqual(r.json(), []) + cl = self.client.list_container('test') + self.assertEqual(cl, []) def test_6_create_forwarded_container(self): self.fwd.create_container('dir') - r = self.admin.list_container('fwd/dir') - self.assertEqual(r.json(), []) + cl = self.admin.list_container('fwd/dir') + self.assertEqual(cl, []) def test_7_delete_forwarded_container(self): self.fwd.delete_container('dir') try: self.admin.list_container('fwd/dir') - except HTTPError as e: - self.assertEqual(e.response.status_code, 404) + except HTTPError: + self.assertEqual(self.admin.last_response.status_code, 404) def test_9_loop(self): try: self.loop.list_container('test') - except HTTPError as e: - self.assertEqual(e.response.status_code, 502) + except HTTPError: + self.assertEqual(self.loop.last_response.status_code, 502) def test_A_enc_1_create_container(self): self.enc.create_container('container') - r = self.enc.list_container('container') - self.assertEqual(r.json(), []) + cl = self.enc.list_container('container') + self.assertEqual(cl, []) self.enc.delete_container('container') try: self.enc.list_container('container') - except HTTPError as e: - self.assertEqual(e.response.status_code, 404) + except HTTPError: + self.assertEqual(self.enc.last_response.status_code, 404) def test_A_enc_2_set_simple_key(self): self.enc.create_container('enc') - self.enc.set_simple_key('enc/key', 'simple') - key = self.admin.get_simple_key('enc/key') + self.enc.set_secret('enc/key', 'simple') + key = self.admin.get_secret('enc/key') self.assertNotEqual(key, 'simple') - key = self.enc.get_simple_key('enc/key') + key = self.enc.get_secret('enc/key') self.assertEqual(key, 'simple') -- cgit