diff options
Diffstat (limited to 'macaroonbakery/store.py')
-rw-r--r-- | macaroonbakery/store.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/macaroonbakery/store.py b/macaroonbakery/store.py new file mode 100644 index 0000000..ae5f7a7 --- /dev/null +++ b/macaroonbakery/store.py @@ -0,0 +1,77 @@ +# Copyright 2017 Canonical Ltd. +# Licensed under the LGPLv3, see LICENCE file for details. +import abc +import os + + +class MemoryOpsStore: + ''' A multi-op store that stores the operations in memory. + ''' + def __init__(self): + self._store = {} + + def put_ops(self, key, time, ops): + ''' Put an ops only if not already there, otherwise it's a no op. + ''' + if self._store.get(key) is None: + self._store[key] = ops + + def get_ops(self, key): + ''' Returns ops from the key if found otherwise raises a KeyError. + ''' + ops = self._store.get(key) + if ops is None: + raise KeyError( + 'cannot get operations for {}'.format(key)) + return ops + + +class RootKeyStore(object): + ''' Defines a store for macaroon root keys. + ''' + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def get(self, id): + ''' Returns the root key for the given id. + If the item is not there, it returns None. + @param id: bytes + @return: bytes + ''' + raise NotImplementedError('get method must be defined in ' + 'subclass') + + @abc.abstractmethod + def root_key(self): + ''' Returns the root key to be used for making a new macaroon, and an + id that can be used to look it up later with the get method. + Note that the root keys should remain available for as long as the + macaroons using them are valid. + Note that there is no need for it to return a new root key for every + call - keys may be reused, although some key cycling is over time is + advisable. + @return: bytes + ''' + + +class MemoryKeyStore(RootKeyStore): + ''' MemoryKeyStore returns an implementation of + Store that generates a single key and always + returns that from root_key. The same id ("0") is always + used. + ''' + def __init__(self, key=None): + ''' If the key is not specified a random key will be generated. + @param key: bytes + ''' + if key is None: + key = os.urandom(24) + self._key = key + + def get(self, id): + if id != b'0': + return None + return self._key + + def root_key(self): + return self._key, b'0' |