예제 #1
0
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()
예제 #2
0
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()
예제 #3
0
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)
예제 #4
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)
예제 #5
0
 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()
예제 #6
0
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