def test_setup_db_erase_all(app, engine, capsys, erase): app.echo = Echo(verbosity=1) # GIVEN a database with records app.cli_cmd = "init-database" setup_db(app) init_db_tables(app, drop_data=True, add_defaults=True) KEY = "linotp.foobar" item = Config(Key=KEY, Value="123", Type="int", Description="test item") db.session.add(item) db.session.commit() assert db.session.query(Config).filter_by(Key=KEY).count() == 1 db.session.remove() # WHEN I invoke `setup_db` setup_db(app) init_db_tables(app, drop_data=erase, add_defaults=False) if erase: # Additional record should have disappeared assert db.session.query(Config).filter_by(Key=KEY).count() == 0 else: # Additional record should still be there assert db.session.query(Config).filter_by(Key=KEY).count() == 1 item = db.session.query(Config).filter_by(Key=KEY).first() db.session.delete(item) db.session.commit()
def test_setup_db_doesnt_create_tables(app, engine, capsys): app.echo = Echo(verbosity=1) # GIVEN an empty database assert 'Config' not in engine.table_names() # WHEN I call `setup_db` without additional arguments setup_db(app) # THEN the tables are NOT created (because `init_db_tables` does that). assert 'Config' not in engine.table_names()
def fix_db_encoding_command(): """Fix the python2+mysql iso8859 encoding by conversion to utf-8.""" try: # Even though we skip initialising the database when doing # `linotp init …`, at this point we do need a database engine # after all. setup_db(current_app) result, response = fix_db_encoding(current_app) except Exception as exx: current_app.echo(f"Conversion could not be completed: {exx}") sys.exit(1) if not result: current_app.echo(f"Conversion failed: {response}") sys.exit(1) current_app.echo(f"Conversion response: {response}") sys.exit(0)
def init_db_command(erase_all_data): """ Create new tables The database is initialized and optionally data is cleared. """ if erase_all_data: info = 'Recreating database' else: info = 'Creating database' current_app.echo(info, v=1) try: # Even though we skip initialising the database when doing # `linotp init …`, at this point we do need a database engine # after all. current_app.cli_cmd = 'init-database' # anything but `init` setup_db(current_app) init_db_tables(current_app, erase_all_data) except Exception as exx: current_app.echo(f'Failed to create database: {exx!s}') raise sys.exit(1) current_app.echo('Database created', v=1)
def __init__(self, app: LinOTPApp) -> None: setup_db(app) self.user_class = ImportedUserSchema self.session: Session = db.session() self.admin_resolver_name = app.config["ADMIN_RESOLVER_NAME"] self.admin_realm_name = app.config["ADMIN_REALM_NAME"].lower()
def test_padding_migration(app, base_app, engine): """Check that the padding migration has changed 0. create an empty database 1. set the security module to the old padding, and 2. set the db schema version to lower than the padding migration version and generate an encrypted value with the old padding and store both entries 3. restore the original padding function 4. run the db_init, which now re-encryptes the values the stored encrypted values must now be different, while the decrypted values should be the same """ from linotp.lib.security.default import DefaultSecurityModule class MockSecurityModule(DefaultSecurityModule): @staticmethod def old_padd_data(input_data): data = b"\x01\x02" padding = (16 - len(input_data + data) % 16) % 16 return input_data + data + padding * b"\0" app.echo = Echo(verbosity=1) # we need a base_app context which contains the security provider that is # needed for the re-encryption during the 3.1.0.0 migration with base_app.app_context(): # GIVEN a database with records app.cli_cmd = "init-database" # 0. drop all data and add defaults setup_db(app) init_db_tables(app, drop_data=True, add_defaults=False) # 1. set the security module to the old padding sec_provider = base_app.security_provider sec_module = sec_provider.security_modules[sec_provider.activeOne] sec_module.padd_data = MockSecurityModule.old_padd_data # 2. # set the db schema version to lower than the padding migration # version and generate an encrypted value with the old padding # and store both entries db_schema_version = "linotp.sql_data_model_version" db.session.query(Config).filter_by(Key=db_schema_version).delete() item = Config( Key=db_schema_version, Value="3.0.0.0", Type="", Description="db schema version", ) db.session.add(item) item = Config( Key="linotp.Config", Value="2021-08-25 11:26:13.101147", Type="", Description="db config change time stamp", ) db.session.add(item) value = "Test123Test123Test123Test123Test123" enc_value = sec_module.encryptPassword(value.encode("utf-8")) enc_data_key = "linotp.padding_migration_test_password" enc_item = Config( Key=enc_data_key, Value=enc_value, Type="encrypted_data", Description="migration test password", ) db.session.add(enc_item) pw_token = Token(serial="new_pw_token") pw_token.LinOtpTokenType = "pw" pw_token.LinOtpKeyIV = binascii.hexlify(b":1:") pw_token.LinOtpKeyEnc = binascii.hexlify( b"$6$XjPTQ1cdb8xFEdnF$m.XoQ//RSPABWGym7o9aPx/.RS1ZySekGBDW7wu" b"TZlCDhEM7nf7aOjp03Erk1UFX2OiOhKqaXBMw0a.o4Sbev.") db.session.add(pw_token) hmac_token = Token(serial="new_hmac_token") hmac_token.LinOtpTokenType = "hmac" crypted_value = sec_module.encryptPin( cryptPin=b"01234567890123456789012345678901") iv, _, enc_key = crypted_value.partition(":") hmac_token.LinOtpKeyIV = iv.encode("utf-8") hmac_token.LinOtpKeyEnc = enc_key.encode("utf-8") db.session.add(hmac_token) db.session.commit() db.session.remove() # 3. restore the original padding function sec_module.padd_data = DefaultSecurityModule.padd_data # 4. run the db_init, which now re-encrypts the values setup_db(app) init_db_tables(app, drop_data=False, add_defaults=False) # verify the expected behavior new_enc = db.session.query(Config).filter_by(Key=enc_data_key).first() assert new_enc.Value != enc_value new_value = sec_module.decryptPassword(new_enc.Value).decode("utf-8") assert new_value == value