def test_add(self): db = Storage() keydb = KeyDB(db, load=True) db._sync_db() assert len(os.listdir(os.getcwd())) == 1 keydb.add_key("public1", "private1") keydb.add_key("public2", "private2") assert len(keydb.get_public_keys()) == 2 assert keydb.get_public_keys()[0] == "public1" assert keydb.get_public_keys()[1] == "public2"
def test_revoking_break(self): db = Storage() keydb = KeyDB(db, load=False) db._sync_db() assert len(os.listdir(os.getcwd())) == 1 keydb.add_key('public1', 'private1') keydb.add_key('public2', 'private2') assert keydb.get_revoked_key() is None assert len(keydb.get_public_keys()) == 2 keydb.revoke_key(count=1) assert len(keydb.get_public_keys()) == 1 assert keydb.get_revoked_key()['public'] == 'public1'
def test_get_revoked_key(self): db = Storage() keydb = KeyDB(db, load=True) db._sync_db() assert len(os.listdir(os.getcwd())) == 1 assert keydb.get_revoked_key() is None keydb.add_key('public1', 'private1') keydb.add_key('public2', 'private2') assert len(keydb.get_public_keys()) == 2 keydb.revoke_key(count=2) assert len(keydb.get_public_keys()) == 0
def test_revoking_break(self): db = Storage() keydb = KeyDB(db, load=False) db._sync_db() assert len(os.listdir(os.getcwd())) == 1 keydb.add_key("public1", "private1") keydb.add_key("public2", "private2") assert keydb.get_revoked_key() is None assert len(keydb.get_public_keys()) == 2 keydb.revoke_key(count=1) assert len(keydb.get_public_keys()) == 1 assert keydb.get_revoked_key()["public"] == "public1"
def test_get_revoked_key(self): db = Storage() keydb = KeyDB(db, load=True) db._sync_db() assert len(os.listdir(os.getcwd())) == 1 assert keydb.get_revoked_key() is None keydb.add_key("public1", "private1") keydb.add_key("public2", "private2") assert len(keydb.get_public_keys()) == 2 keydb.revoke_key(count=2) assert len(keydb.get_public_keys()) == 0
def init_app(self, obj, db): """Sets up client with config values from obj Args: obj (instance): config object """ # Copies and sets all needed config attributes # for this object self.app_name = obj.get('APP_NAME') self.private_key_name = self.app_name + '.pem' self.public_key_name = self.app_name + '.pub' data_dir = obj.get('DATA_DIR', os.getcwd()) self.db = db self.keysdb = KeyDB(db) self.data_dir = os.path.join(data_dir, settings.USER_DATA_FOLDER) self.deploy_dir = os.path.join(self.data_dir, 'deploy') self.version_file = os.path.join(self.deploy_dir, settings.VERSION_FILE)
def test_add(self): db = Storage() keydb = KeyDB(db, load=True) db._sync_db() assert len(os.listdir(os.getcwd())) == 1 keydb.add_key('public1', 'private1') keydb.add_key('public2', 'private2') assert len(keydb.get_public_keys()) == 2 assert keydb.get_public_keys()[0] == 'public1' assert keydb.get_public_keys()[1] == 'public2'
class KeyHandler(object): """KeyHanlder object is used to manage keys used for signing updates Kwargs: app (obj): Config object to get config values from db (dict): Framework metadata """ def __init__(self, app=None, db=None): self.key_encoding = 'base64' if app is not None: self.init_app(app, db) def init_app(self, obj, db): """Sets up client with config values from obj Args: obj (instance): config object """ # Copies and sets all needed config attributes # for this object self.app_name = obj.get('APP_NAME') self.private_key_name = self.app_name + '.pem' self.public_key_name = self.app_name + '.pub' data_dir = obj.get('DATA_DIR', os.getcwd()) self.db = db self.keysdb = KeyDB(db) self.data_dir = os.path.join(data_dir, settings.USER_DATA_FOLDER) self.deploy_dir = os.path.join(self.data_dir, 'deploy') self.version_file = os.path.join(self.deploy_dir, settings.VERSION_FILE) def make_keys(self, count=3): """Makes public and private keys for signing and verification Kwargs: count (bool): The number of keys to create. """ log.info('Creating {} keys'.format(count)) c = 0 while c < count: self._make_keys() c += 1 def _make_keys(self): # Makes a set of private and public keys # Used for authentication self.keysdb.load() privkey, pubkey = ed25519.create_keypair() pri = privkey.to_ascii(encoding=self.key_encoding) pub = pubkey.to_ascii(encoding=self.key_encoding) self.keysdb.add_key(pub, pri) def sign_update(self): """Signs version file with private key Proxy method for :meth:`_add_sig` """ # Loads private key # Loads version file to memory # Signs Version file # Writes version file back to disk self._add_sig() def get_public_keys(self): "Returns (object): Public Key" self.keysdb.load() return self.keysdb.get_public_keys() def get_recent_revoked_key(self): self.keysdb.load() return self.keysdb.get_revoked_key() def print_public_keys(self): "Prints public key data to console" keys = self.get_public_key() print('Public Key:\n{}\n\n'.format(keys)) def revoke_key(self, count): self.keysdb.revoke_key(count) self.make_keys(count) def _load_private_keys(self): # Loads private key log.debug('Loading private key') return self.keysdb.get_private_keys() def _add_sig(self): # Adding new signature to version file private_keys = self._load_private_keys() # Just making sure we have a least 2 keys so when revoke is # called we have a fall back if len(private_keys) < 2: self.make_keys() private_keys = self._load_private_keys() update_data = self._load_update_data() if 'sigs' in update_data: log.debug('Removing signatures from version file') del update_data['sigs'] update_data_str = json.dumps(update_data, sort_keys=True) signatures = [] for p in private_keys: if six.PY2 is True and isinstance(p, unicode) is True: log.debug('Got type: {}'.format(type(p))) p = str(p) log.debug('Key type: {}'.format(type(p))) privkey = ed25519.SigningKey(p, encoding=self.key_encoding) # Signs update data with private key sig = privkey.sign(six.b(update_data_str), encoding=self.key_encoding) log.debug('Sig: {}'.format(sig)) signatures.append(sig) og_data = json.loads(update_data_str) update_data = og_data.copy() # Add signatures to update data update_data['sigs'] = signatures log.info('Adding sig to update data') # Write updated version file to filesystem self._write_update_data(og_data, update_data) def _write_update_data(self, data, version): # Save update data to repo database self.db.save(settings.CONFIG_DB_KEY_VERSION_META, data) log.debug('Saved version meta data') # Gzip update date with gzip.open(self.version_file, 'wb') as f: f.write(json.dumps(version, indent=2, sort_keys=True)) log.info('Created gzipped version manifest in deploy dir') def _load_update_data(self): log.debug("Loading version data") update_data = self.db.load(settings.CONFIG_DB_KEY_VERSION_META) # If update_data is None, create a new one if update_data is None: update_data = {} log.error('Version meta data not found') self.db.save(settings.CONFIG_DB_KEY_VERSION_META, update_data) log.info('Created new version meta data') log.debug('Version file loaded') return update_data