summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-04-07 16:28:17 -0400
committerSimo Sorce <simo@redhat.com>2015-04-07 17:44:46 -0400
commitc975057c632e5cd9f3eeeecd9ee0f73aeca3dabc (patch)
tree2ec54c038b664e2b53fb64f04ecff659235f338f
parentec754903728595bd3a29fff5993dd1495506c188 (diff)
downloadcustodia-c975057c632e5cd9f3eeeecd9ee0f73aeca3dabc.tar.gz
custodia-c975057c632e5cd9f3eeeecd9ee0f73aeca3dabc.tar.xz
custodia-c975057c632e5cd9f3eeeecd9ee0f73aeca3dabc.zip
Check that intermediate containers exist
If a container does not exist PUTing a key should fail
-rw-r--r--custodia/secrets.py43
1 files changed, 41 insertions, 2 deletions
diff --git a/custodia/secrets.py b/custodia/secrets.py
index e808e19..316ebd0 100644
--- a/custodia/secrets.py
+++ b/custodia/secrets.py
@@ -23,7 +23,9 @@ class Secrets(HTTPConsumer):
if ns == trail[0]:
f = self._get_key(namespaces, trail)
break
- if f is None:
+ if f is None:
+ raise HTTPError(403)
+ else:
# Consider the first namespace as the default one
t = [namespaces[0]] + trail
f = self._get_key(namespaces, t)
@@ -63,7 +65,14 @@ class Secrets(HTTPConsumer):
for k in keydict:
# strip away the internal prefix for storing keys
name = k[len('keys/'):]
- output[name] = json.loads(keydict[k])
+ value = keydict[k]
+ # remove the containers themselves, we list only keys
+ if name.endswith('/'):
+ continue
+ if value == '':
+ output[name] = ''
+ else:
+ output[name] = json.loads(value)
response['output'] = json.dumps(output)
except CSStoreError:
raise HTTPError(404)
@@ -96,8 +105,28 @@ class Secrets(HTTPConsumer):
except ValueError as e:
raise HTTPError(400, str(e))
+ # must _get_key first as access control is done here for now
+ # otherwise users would e able to probe containers in namespaces
+ # they do not have access to.
key = self._get_key(ns, trail)
+
try:
+ # check that the containers exist
+ n = 0
+ for n in range(1, len(trail)):
+ probe = self._get_key(ns, trail[:n] + [''])
+ try:
+ check = self.root.store.get(probe)
+ if check is None:
+ break
+ except CSStoreError:
+ break
+ # create if default namespace
+ if n == 1 and ns[0] == trail[0]:
+ self.root.store.set(probe, '')
+ else:
+ raise HTTPError(404)
+
self.root.store.set(key, value)
except CSStoreError:
raise HTTPError(500)
@@ -207,6 +236,16 @@ class SecretsTests(unittest.TestCase):
self.secrets.PUT(req, rep)
self.assertEqual(err.exception.code, 403)
+ def test_4_PUTKey_errors_404(self):
+ req = {'headers': {'Content-Type': 'application/json; charset=utf-8'},
+ 'remote_user': 'test',
+ 'trail': ['test', 'more', 'key1'],
+ 'body': '{"type":"simple","value":"1234"}'}
+ rep = {}
+ with self.assertRaises(HTTPError) as err:
+ self.secrets.PUT(req, rep)
+ self.assertEqual(err.exception.code, 404)
+
def test_4_PUTKey_errors_405(self):
req = {'headers': {'Content-Type': 'application/json; charset=utf-8'},
'remote_user': 'test',