X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=n2vc%2Fstore.py;h=c8e5910d08b5192b906f4aef78312c16269e891d;hb=5f069332606e512f74791c6497af40326b611344;hp=b827d5123ad2b07a40f795e1d0aa531296562202;hpb=eb8943a887e2fb8cce0240382811f9e504f3c7fb;p=osm%2FN2VC.git diff --git a/n2vc/store.py b/n2vc/store.py index b827d51..c8e5910 100644 --- a/n2vc/store.py +++ b/n2vc/store.py @@ -13,16 +13,14 @@ # limitations under the License. import abc -import asyncio -from base64 import b64decode -import re import typing -from Crypto.Cipher import AES from motor.motor_asyncio import AsyncIOMotorClient from n2vc.config import EnvironConfig from n2vc.vca.connection_data import ConnectionData from osm_common.dbmongo import DbMongo, DbException +from osm_common.dbbase import Encryption + DB_NAME = "osm" @@ -184,17 +182,21 @@ class DbMongoStore(Store): class MotorStore(Store): - def __init__(self, uri: str, loop=None): + def __init__(self, uri: str): """ Constructor :param: uri: Connection string to connect to the database. - :param: loop: Asyncio Loop """ self._client = AsyncIOMotorClient(uri) - self.loop = loop or asyncio.get_event_loop() self._secret_key = None self._config = EnvironConfig(prefixes=["OSMLCM_", "OSMMON_"]) + self.encryption = Encryption( + uri=uri, + config=self._config, + encoding_type="utf-8", + logger_name="db", + ) @property def _database(self): @@ -223,7 +225,7 @@ class MotorStore(Store): data = await self._vca_collection.find_one({"_id": vca_id}) if not data: raise Exception("vca with id {} not found".format(vca_id)) - await self.decrypt_fields( + await self.encryption.decrypt_fields( data, ["secret", "cacert"], schema_version=data["schema_version"], @@ -294,97 +296,3 @@ class MotorStore(Store): async def _get_juju_info(self): """Get Juju information (the default VCA) from the admin collection""" return await self._admin_collection.find_one({"_id": "juju"}) - - # DECRYPT METHODS - async def decrypt_fields( - self, - item: dict, - fields: typing.List[str], - schema_version: str = None, - salt: str = None, - ): - """ - Decrypt fields - - Decrypt fields from a dictionary. Follows the same logic as in osm_common. - - :param: item: Dictionary with the keys to be decrypted - :param: fields: List of keys to decrypt - :param: schema version: Schema version. (i.e. 1.11) - :param: salt: Salt for the decryption - """ - flags = re.I - - async def process(_item): - if isinstance(_item, list): - for elem in _item: - await process(elem) - elif isinstance(_item, dict): - for key, val in _item.items(): - if isinstance(val, str): - if any(re.search(f, key, flags) for f in fields): - _item[key] = await self.decrypt(val, schema_version, salt) - else: - await process(val) - - await process(item) - - async def decrypt(self, value, schema_version=None, salt=None): - """ - Decrypt an encrypted value - :param value: value to be decrypted. It is a base64 string - :param schema_version: used for known encryption method used. If None or '1.0' no encryption has been done. - If '1.1' symmetric AES encryption has been done - :param salt: optional salt to be used - :return: Plain content of value - """ - if not await self.secret_key or not schema_version or schema_version == "1.0": - return value - else: - secret_key = self._join_secret_key(salt) - encrypted_msg = b64decode(value) - cipher = AES.new(secret_key) - decrypted_msg = cipher.decrypt(encrypted_msg) - try: - unpadded_private_msg = decrypted_msg.decode().rstrip("\0") - except UnicodeDecodeError: - raise DbException( - "Cannot decrypt information. Are you using same COMMONKEY in all OSM components?", - http_code=500, - ) - return unpadded_private_msg - - def _join_secret_key(self, update_key: typing.Any): - """ - Join secret key - - :param: update_key: str or bytes with the to update - """ - if isinstance(update_key, str): - update_key_bytes = update_key.encode() - else: - update_key_bytes = update_key - new_secret_key = ( - bytearray(self._secret_key) if self._secret_key else bytearray(32) - ) - for i, b in enumerate(update_key_bytes): - new_secret_key[i % 32] ^= b - return bytes(new_secret_key) - - @property - async def secret_key(self): - if self._secret_key: - return self._secret_key - else: - if self.database_key: - self._secret_key = self._join_secret_key(self.database_key) - version_data = await self._admin_collection.find_one({"_id": "version"}) - if version_data and version_data.get("serial"): - self._secret_key = self._join_secret_key( - b64decode(version_data["serial"]) - ) - return self._secret_key - - @property - def database_key(self): - return self._config["database_commonkey"]