diff options
-rw-r--r-- | custodia.conf | 5 | ||||
-rwxr-xr-x | custodia/custodia | 5 | ||||
-rw-r--r-- | custodia/store/__init__.py | 0 | ||||
-rw-r--r-- | custodia/store/interface.py | 17 | ||||
-rw-r--r-- | custodia/store/sqlite.py | 62 |
5 files changed, 88 insertions, 1 deletions
diff --git a/custodia.conf b/custodia.conf index 747c446..4a32c11 100644 --- a/custodia.conf +++ b/custodia.conf @@ -11,6 +11,11 @@ handler = custodia.http.authenticators.SimpleHeaderAuth name = REMOTE_USER value = simo +[store:simple] +handler = custodia.store.sqlite.SqliteStore +dburi = secrets.db +table = secrets + [/] handler = custodia.root.Root diff --git a/custodia/custodia b/custodia/custodia index cf66554..4bcb7cb 100755 --- a/custodia/custodia +++ b/custodia/custodia @@ -31,7 +31,7 @@ def parse_config(cfgfile): if len(files) == 0: raise IOError("Failed to read config file") - config = {'authenticators': dict(), 'consumers': dict()} + config = {'authenticators': dict(), 'consumers': dict(), 'stores': dict()} for s in parser.sections(): if s == 'global': for opt, val in parser.items(s): @@ -48,6 +48,9 @@ def parse_config(cfgfile): if s.startswith('auth:'): menu = 'authenticators' name = s[5:] + elif s.startswith('store:'): + menu = 'stores' + name = s[6:] else: raise ValueError('Invalid section name [%s].\n' % s) diff --git a/custodia/store/__init__.py b/custodia/store/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/custodia/store/__init__.py diff --git a/custodia/store/interface.py b/custodia/store/interface.py new file mode 100644 index 0000000..c804670 --- /dev/null +++ b/custodia/store/interface.py @@ -0,0 +1,17 @@ +# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file + + +class CSStoreError(Exception): + pass + + +class CSStore(object): + + def get(self, key): + raise NotImplementedError + + def set(self, key, value): + raise NotImplementedError + + def list(self, keyfilter=None): + raise NotImplementedError diff --git a/custodia/store/sqlite.py b/custodia/store/sqlite.py new file mode 100644 index 0000000..f5908d0 --- /dev/null +++ b/custodia/store/sqlite.py @@ -0,0 +1,62 @@ +# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file + +from custodia.store.interface import CSStore, CSStoreError +import os +import sqlite3 +import sys + + +def log_error(error): + print >> sys.stderr, error + + +class SqliteStore(CSStore): + + def __init__(self, config): + if 'dburi' not in config: + raise ValueError('Missing "dburi" for Sqlite Store') + self.dburi = config['dburi'] + if 'table' in config: + self.table = config['table'] + else: + self.table = "CustodiaSecrets" + + def get(self, key): + query = "SELECT value from %s WHERE key=?" % self.table + try: + conn = sqlite3.connect(self.dburi) + c = conn.cursor() + r = c.execute(query, (key)) + value = r.fetchall() + except sqlite3.Error as err: + log_error("Error fetching key %s: [%r]" % (key, repr(err))) + raise CSStoreError('Error occurred while trying to get key') + return value + + def _create(self, cur): + create = "CREATE TABLE IF NOT EXISTS %s (key, value)" % self.table + cur.execute(create) + + def set(self, key, value): + setdata = "INSERT OR REPLACE into %s VALUES (?, ?)" % self.table + try: + conn = sqlite3.connect(self.dburi) + with conn: + c = conn.cursor() + self._create(c) + c.execute(setdata, (key, value)) + except sqlite3.Error as err: + log_error("Error storing key %s: [%r]" % (key, repr(err))) + raise CSStoreError('Error occurred while trying to store key') + + def list(self, keyfilter='/'): + search = "SELECT * FROM %s WHERE key LIKE ?" % self.table + key = os.path.join(keyfilter, '%') + try: + conn = sqlite3.connect(self.dburi) + r = conn.execute(search, (key,)) + value = r.fetchall() + except sqlite3.Error as err: + log_error("Error listing (filter: %s): [%r]" % (key, repr(err))) + raise CSStoreError('Error occurred while trying to list keys') + return value |