def test_rename_secret(set_up): m_pwd = u"memorabile" domain = u"my_domain" access = u"my_access" new_domain = u"new_domain" new_access = u"new_access" info = {'message': 'secret'} try: #before assert not du.has_secret(domain, access) assert not du.has_secret(new_domain, new_access) #after insertion du.insert_secret(domain, access, None, None, info, m_pwd, parameters.get_salt_key()) assert du.has_secret(domain, access) assert not du.has_secret(new_domain, new_access) #after rename du.rename_secret(domain, access, new_domain, new_access) assert not du.has_secret(domain, access) assert du.has_secret(new_domain, new_access) res = du.get_secret(new_domain, new_access, m_pwd, parameters.get_salt_key()) assert info['message'] == res['info']['message'] finally: du.delete_secret(domain, access) du.delete_secret(new_domain, new_access)
def test_update_info_dict_remove_key(set_up): m_pwd = u"memorabile" domain = u"my_domain" access = u"my_access" secret_info = {'key1': 'value1', 'key2': 'value2'} salt = parameters.get_salt_key() try: ns = du.count_secrets() du.insert_secret(domain, access, None, None, secret_info, m_pwd, parameters.get_salt_key()) assert ns + 1 == du.count_secrets() res = du.get_secret(domain, access, m_pwd, salt, False) #no decryption of secret old_ts = res['timestamp'] info = res['info'] assert 2 == len(info) del info['key2'] #remove one entry du.update_secret_info_dictionary(domain, access, info) res = du.get_secret(domain, access, m_pwd, salt) ts = res['timestamp'] info = res['info'] assert 1 == len(info) assert 'value1' == info['key1'] assert ts != old_ts finally: du.delete_secret(domain, access)
def test_update_secret_info_change_password_and_a_value(set_up): m_pwd = u"memorabile" domain = u"my_domain" access = u"my_access" secret_uid = u"me@home" secret_pwd = u"ciao mamma" secret_pwd2 = u"another password" secret_info = {'message': 'secret'} info_key = 'message' info_val = 'a new secret' try: du.insert_secret(domain, access, secret_uid, secret_pwd, secret_info, m_pwd, parameters.get_salt_key()) res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) old_ts = res['timestamp'] assert 'secret' == res['info'][info_key] assert secret_pwd == res['pwd'] du.update_secret(domain, access, None, secret_pwd2, info_key, info_val, m_pwd, parameters.get_salt_key()) res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) assert info_val == res['info'][info_key] assert secret_pwd2 == res['pwd'] assert old_ts < res['timestamp'] finally: du.delete_secret(domain, access)
def test_update_missing_secret_no_effect(set_up): m_pwd = u"memorabile" domain = u"my_domain" access = u"my_access" access2 = u"my_second access" secret_uid = u"me@home" secret_pwd = u"ciao mamma" secret_pwd2 = u"my second password" secret_info = {'message': 'secret'} try: ns = du.count_secrets() du.insert_secret(domain, access, secret_uid, secret_pwd, secret_info, m_pwd, parameters.get_salt_key()) assert ns + 1 == du.count_secrets() res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) old_ts = res['timestamp'] assert 'secret' == res['info']['message'] assert secret_pwd == res['pwd'] assert secret_uid == res['uid'] du.update_secret(domain, access2, None, secret_pwd2, None, None, m_pwd, parameters.get_salt_key()) assert ns + 1 == du.count_secrets() res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) assert old_ts == res['timestamp'] finally: du.delete_secret(domain, access)
def test_update_secret_login(set_up): m_pwd = u"memorabile" secret_uid = u"me@home" secret_uid2 = u"me@office" secret_pwd = u"ciao mamma" domain = u"my_domain" access = u"my_access" try: ns = du.count_secrets() du.insert_secret(domain, access, secret_uid, secret_pwd, None, m_pwd, parameters.get_salt_key()) assert ns + 1 == du.count_secrets() assert du.has_secret(domain, access) old_ts = du.get_secret(domain, access, m_pwd, parameters.get_salt_key())['timestamp'] du.update_secret(domain, access, secret_uid2, None, None, None, m_pwd, parameters.get_salt_key()) assert ns + 1 == du.count_secrets( ) #no change to the number of secrets res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) assert secret_uid2 == res['uid'] assert secret_pwd == res['pwd'] assert old_ts < res['timestamp'] finally: du.delete_secret(domain, access)
def test_insert_select_compare_info(set_up): m_pwd = u"memorabile" secret_info = {'message': 'secret'} domain = u"my_domain" access = u"my_access" try: du.insert_secret(domain, access, None, None, secret_info, m_pwd, parameters.get_salt_key()) res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) assert secret_info['message'] == res['info']['message'] finally: du.delete_secret(domain, access)
def test_insert_select_compare_login(set_up): m_pwd = u"memorabile" secret_uid = u"me@home" secret_pwd = u"ciao mamma" domain = u"my_domain" access = u"my_access" try: du.insert_secret(domain, access, secret_uid, secret_pwd, None, m_pwd, parameters.get_salt_key()) res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) assert secret_uid == res['uid'] assert secret_pwd == res['pwd'] finally: du.delete_secret(domain, access)
def test_encrypt_decrypt_secret(set_up): conf_file = set_up c_pwd = u"passwd" m_pwd = u"memorabile" secret = u"mamma" set_configuration(encrypt_key(c_pwd), None, None, None, conf_file) parameters.set_data(get_configuration(conf_file)) esecret = cu.encrypt(secret, m_pwd, parameters.get_salt_key()) v1 = cu.decrypt(esecret, m_pwd, parameters.get_salt_key()) esecret2 = cu.encrypt(secret, m_pwd, parameters.get_salt_key()) v2 = cu.decrypt(esecret2, m_pwd, parameters.get_salt_key()) assert v1 == v2 assert v1 == secret
def get_secret(domain, access, mem_pwd, salt=None, need_decrypt=True): """Retrieves a secret by primary key input: domain the domain, i.e. logical context, of the secret access the secret sub-domain or access specification mem_pwd memorable password to encrypt the secret salt a string representation of the salt (optional) need_decrypt a flag to indicate if decryption is required (default True) output: returns the decrypted secret """ if salt is None: salt = parameters.get_salt_key() resp = _get_table().get_item(Key={'domain' :domain, 'access' : access}) ret = resp['Item'] if not need_decrypt: return ret if 'uid' in ret and ret['uid'] is not None and 'pwd' in ret and ret['pwd'] is not None: ret['uid'] = decrypt(ret['uid'], mem_pwd, salt) ret['pwd'] = decrypt(ret['pwd'], mem_pwd, salt) if 'info' in ret and ret['info'] is not None: ret['info'] = decrypt_info(ret['info'], mem_pwd, salt) return ret
def insert_secret(domain, access, uid, pwd, info, mem_pwd, salt=None): """Insert a secret access record in the cloud DB input: domain the domain, i.e. logical context, of the secret access the secret sub-domain or access specification uid the user id for that access pwd the password for that access info a map of informations (not encryted) mem_pwd memorable password to encrypt the secret salt a string representation of the salt (optional) """ if salt is None: salt = parameters.get_salt_key() timestamp = datetime.now().isoformat() if uid is None: uid = "" if pwd is None: pwd = "" if info is None: info = {} _get_table().put_item(Item={'domain' : domain, 'access' : access, 'uid' : encrypt(uid, mem_pwd, salt), 'pwd' : encrypt(pwd, mem_pwd, salt), 'info' : encrypt_info(info, mem_pwd, salt), 'timestamp' : timestamp})
def test_update_info(set_up): sleep(1) sys.argv=['secret_wallet','set','-d',DOMAIN, '-a', ACCESS, '-ik','first_key','-iv','first_value'] Parser() sys.argv=['secret_wallet','set','-d',DOMAIN, '-a', ACCESS, '-ik','second_key','-iv','second_value'] Parser() res = du.get_secret(DOMAIN, ACCESS, 'memorable', parameters.get_salt_key()) assert 3 == len(res['info']) assert 'value' == res['info']['key'] assert 'first_value' == res['info']['first_key'] assert 'second_value' == res['info']['second_key']
def update_secret(domain, access, uid, pwd, info_key, info_value, mem_pwd, salt=None): """Update a secret access record in the cloud DB input: domain the domain, i.e. logical context, of the secret access the secret sub-domain or access specification uid the user id for that access pwd the password for that access info_key the key for an extra info info_value the value for an extra info mem_pwd memorable password to encrypt the secret salt a string representation of the salt (optional) """ if salt is None: salt = parameters.get_salt_key() timestamp = datetime.now().isoformat() # #domain is the simbolyc field name and maps table column 'domain' to id #domain expression_attributes = {'#domain':'domain', '#access':'access'} # :domain is the symbolic value to be used in expressions for domain expression_values = {':domain':domain, ':access':access} update_expression = "SET" condition_expression = "#domain = :domain AND #access = :access" if uid is not None: expression_attributes.update({'#uid':'uid'}) expression_values.update({':uid' : encrypt(uid, mem_pwd, salt)}) update_expression += ' #uid = :uid,' if pwd is not None: expression_attributes.update({'#pwd':'pwd'}) expression_values.update({':pwd' : encrypt(pwd, mem_pwd, salt)}) update_expression += ' #pwd = :pwd,' if info_key is not None and info_value is not None: expression_attributes.update({'#info':'info','#key':info_key}) expression_values.update({':info':encrypt(info_value, mem_pwd, salt)}) update_expression += ' #info.#key = :info,' #if nothing to update then return if update_expression == 'SET': return #now add the timestamp expression_attributes.update({'#timestamp':'timestamp'}) expression_values.update({':ts': timestamp}) update_expression += ' #timestamp = :ts' try: _get_table().update_item(Key={"domain": domain, "access": access}, ExpressionAttributeNames = expression_attributes, ExpressionAttributeValues = expression_values, UpdateExpression = update_expression, ConditionExpression = condition_expression ) except: pass #the condition failed but there should be no side effect
def test_has_not_secret(set_up): m_pwd = u"memorabile" secret_uid = u"me@home" secret_pwd = u"ciao mamma" domain = u"my_domain" access = u"my_access" try: du.insert_secret(domain, access, secret_uid, secret_pwd, None, m_pwd, parameters.get_salt_key()) assert not du.has_secret('new_domain', access) finally: du.delete_secret(domain, access)
def test_update_secret_info_change_value(set_up): m_pwd = u"memorabile" domain = u"my_domain" access = u"my_access" secret_info = {'message': 'secret'} info_key = 'message' info_val = 'a new secret' try: du.insert_secret(domain, access, None, None, secret_info, m_pwd, parameters.get_salt_key()) res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) old_ts = res['timestamp'] assert 'secret' == res['info'][info_key] du.update_secret(domain, access, None, None, info_key, info_val, m_pwd, parameters.get_salt_key()) res = du.get_secret(domain, access, m_pwd, parameters.get_salt_key()) assert info_val == res['info'][info_key] assert old_ts < res['timestamp'] finally: du.delete_secret(domain, access)
def test_insert_delete_login(set_up): m_pwd = u"memorabile" secret_uid = u"me@home" secret_pwd = u"ciao mamma" domain = u"my_domain" access = u"my_access" ns = du.count_secrets() try: du.insert_secret(domain, access, secret_uid, secret_pwd, None, m_pwd, parameters.get_salt_key()) assert ns + 1 == du.count_secrets() finally: du.delete_secret(domain, access) assert ns == du.count_secrets()
def test_delete_secrets(set_up): m_pwd = u"memorabile" domain = u"my_domain" info = {'message': 'secret'} #cleanup du.delete_secrets(du.list_secrets(None)) cnt = du.count_secrets() for i in range(5): access = f"access_{i}" du.insert_secret(domain, access, None, None, info, m_pwd, parameters.get_salt_key()) assert cnt + 5 == du.count_secrets() # now get the secret back by domain secrets = du.list_secrets(domain) #delete them in block du.delete_secrets(secrets) #check that they are gone assert cnt == du.count_secrets()