Beispiel #1
0
def regression(self,
               local,
               clickhouse_binary_path,
               parallel=None,
               stress=None):
    """ClickHouse LDAP integration regression module.
    """
    args = {"local": local, "clickhouse_binary_path": clickhouse_binary_path}

    if stress is not None:
        self.context.stress = stress

    with Pool(3) as pool:
        try:
            Feature(test=load("ldap.authentication.regression", "regression"),
                    parallel=True,
                    executor=pool)(**args)
            Feature(test=load("ldap.external_user_directory.regression",
                              "regression"),
                    parallel=True,
                    executor=pool)(**args)
            Feature(test=load("ldap.role_mapping.regression", "regression"),
                    parallel=True,
                    executor=pool)(**args)
        finally:
            join()
Beispiel #2
0
def regression(self,
               local,
               clickhouse_binary_path,
               stress=None,
               parallel=None):
    """ClickHouse regression.
    """
    top().terminating = False
    args = {
        "local": local,
        "clickhouse_binary_path": clickhouse_binary_path,
        "stress": stress,
        "parallel": parallel
    }

    self.context.stress = stress
    self.context.parallel = parallel

    tasks = []
    with Pool(8) as pool:
        try:
            run_scenario(
                pool, tasks,
                Feature(test=load("example.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("ldap.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("rbac.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("aes_encryption.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("map_type.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("window_functions.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("datetime64_extended_range.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("kerberos.regression", "regression")), args)
            #run_scenario(pool, tasks, Feature(test=load("extended_precision_data_types.regression", "regression")), args)
        finally:
            join(tasks)
Beispiel #3
0
def regression(self,
               local,
               clickhouse_binary_path,
               parallel=None,
               stress=None):
    """ClickHouse LDAP integration regression module.
    """
    top().terminating = False
    args = {"local": local, "clickhouse_binary_path": clickhouse_binary_path}

    if stress is not None:
        self.context.stress = stress
    if parallel is not None:
        self.context.parallel = parallel

    tasks = []
    with Pool(3) as pool:
        try:
            run_scenario(
                pool, tasks,
                Feature(
                    test=load("ldap.authentication.regression", "regression")),
                args)
            run_scenario(
                pool, tasks,
                Feature(test=load("ldap.external_user_directory.regression",
                                  "regression")), args)
            run_scenario(
                pool, tasks,
                Feature(
                    test=load("ldap.role_mapping.regression", "regression")),
                args)
        finally:
            join(tasks)
Beispiel #4
0
def regression(self,
               local,
               clickhouse_binary_path,
               stress=None,
               parallel=None):
    """ClickHouse AES encryption functions regression module.
    """
    top().terminating = False
    nodes = {
        "clickhouse": ("clickhouse1", "clickhouse2", "clickhouse3"),
    }

    if stress is not None:
        self.context.stress = stress
    if parallel is not None:
        self.context.parallel = parallel

    with Cluster(local,
                 clickhouse_binary_path,
                 nodes=nodes,
                 docker_compose_project_dir=os.path.join(
                     current_dir(), "aes_encryption_env")) as cluster:
        self.context.cluster = cluster

        tasks = []
        with Pool(5) as pool:
            try:
                run_scenario(
                    pool, tasks,
                    Feature(test=load("aes_encryption.tests.encrypt",
                                      "feature"),
                            flags=TE))
                run_scenario(
                    pool, tasks,
                    Feature(test=load("aes_encryption.tests.decrypt",
                                      "feature"),
                            flags=TE))
                run_scenario(
                    pool, tasks,
                    Feature(test=load("aes_encryption.tests.encrypt_mysql",
                                      "feature"),
                            flags=TE))
                run_scenario(
                    pool, tasks,
                    Feature(test=load("aes_encryption.tests.decrypt_mysql",
                                      "feature"),
                            flags=TE))
                run_scenario(
                    pool, tasks,
                    Feature(test=load(
                        "aes_encryption.tests.compatibility.feature",
                        "feature"),
                            flags=TE))
            finally:
                join(tasks)
Beispiel #5
0
def parallel_login(self, server=None, user_count=10, timeout=300):
    """Check that login of valid and invalid users works in parallel
    using local users defined using RBAC and LDAP users authenticated using
    multiple LDAP external user directories when server is restarted
    in the middle of parallel login attempts. After server is restarted
    makes sure that parallel logins work as expected.
    """
    servers = {
        "openldap1": {
            "host": "openldap1",
            "port": "389",
            "enable_tls": "no",
            "auth_dn_prefix": "cn=",
            "auth_dn_suffix": ",ou=users,dc=company,dc=com"
        },
        "openldap2": {
            "host": "openldap2",
            "port": "636",
            "enable_tls": "yes",
            "auth_dn_prefix": "cn=",
            "auth_dn_suffix": ",ou=users,dc=company,dc=com",
            "tls_require_cert": "never",
        }
    }

    with Given("I have two LDAP servers"):
        entries = [
            (["openldap1"], []),
            (["openldap2"], [])
        ]

    with And("I define a group of users to be created on each LDAP server"):
        user_groups = {
            "openldap1_users": [{"cn": f"openldap1_parallel_user{i}", "userpassword": randomword(20)} for i in
                                range(user_count)],
            "openldap2_users": [{"cn": f"openldap2_parallel_user{i}", "userpassword": randomword(20)} for i in
                                range(user_count)],
            "local_users": [{"cn": f"local_parallel_user{i}", "userpassword": randomword(20)} for i in
                            range(user_count)]
        }

    @TestStep(When)
    @Name("I login as {username} and execute query")
    def login_and_execute_query_during_restart(self, username, password, exitcode, message, steps=True, timeout=60):
        """Execute a query and ignore exitcode and message as
        during restart exit codes and messages vary based on the state
        of the restarted container and the ClickHouse server
        and there are too many cases and complete list is not fully known
        therefore trying to list all possible cases produces random fails.
        """
        r = self.context.cluster.command(None, f"{self.context.cluster.docker_compose} exec {self.context.node.name} " +
           f"clickhouse client -q \"SELECT 1\" --user {username} --password {password}", steps=steps, timeout=timeout)

        return r

    @TestStep(When)
    @Name("I login as {username} and execute query")
    def login_and_execute_query(self, username, password, exitcode=None, message=None, steps=True, timeout=60):
        self.context.node.query("SELECT 1",
            settings=[("user", username), ("password", password)],
            exitcode=exitcode or 0,
            message=message, steps=steps, timeout=timeout)

    def login_with_valid_username_and_password(users, i, iterations=10, during_restart=False):
        """Login with valid username and password.
        """
        query = login_and_execute_query
        if during_restart:
            query = login_and_execute_query_during_restart

        with When(f"valid users try to login #{i}"):
            for i in range(iterations):
                random_user = users[random.randint(0, len(users) - 1)]

                query(username=random_user["cn"], password=random_user["userpassword"],
                    exitcode=0, message="1", steps=False)

    def login_with_valid_username_and_invalid_password(users, i, iterations=10, during_restart=False):
        """Login with valid username and invalid password.
        """
        query = login_and_execute_query
        if during_restart:
            query = login_and_execute_query_during_restart

        with When(f"users try to login with valid username and invalid password #{i}"):
            for i in range(iterations):
                random_user = users[random.randint(0, len(users) - 1)]

                query(username=random_user["cn"],
                    password=(random_user["userpassword"] + randomword(1)),
                    exitcode=4,
                    message=f"DB::Exception: {random_user['cn']}: Authentication failed: password is incorrect or there is no user with such name",
                    steps=False)

    def login_with_invalid_username_and_valid_password(users, i, iterations=10, during_restart=False):
        """Login with invalid username and valid password.
        """
        query = login_and_execute_query
        if during_restart:
            query = login_and_execute_query_during_restart

        with When(f"users try to login with invalid username and valid password #{i}"):
            for i in range(iterations):
                random_user = dict(users[random.randint(0, len(users) - 1)])
                random_user["cn"] += randomword(1)

                query(username=random_user["cn"],
                    password=random_user["userpassword"],
                    exitcode=4,
                    message=f"DB::Exception: {random_user['cn']}: Authentication failed: password is incorrect or there is no user with such name",
                    steps=False)

    with And("I have a list of checks that I want to run for each user group"):
        checks = [
            login_with_valid_username_and_password,
            login_with_valid_username_and_invalid_password,
            login_with_invalid_username_and_valid_password
        ]

    with And("I create config file to define LDAP external user directory for each LDAP server"):
        config = create_entries_ldap_external_user_directory_config_content(entries)

    with ldap_servers(servers):
        with ldap_external_user_directory(server=None, roles=None, restart=True, config=config):
            with ldap_users(*user_groups["openldap1_users"], node=self.context.cluster.node("openldap1")):
                with ldap_users(*user_groups["openldap2_users"], node=self.context.cluster.node("openldap2")):
                    with rbac_users(*user_groups["local_users"]):
                        tasks = []
                        with Pool(4) as pool:
                            try:
                                with When("I restart the server during parallel login of users in each group"):
                                    for users in user_groups.values():
                                        for check in checks:
                                            tasks.append(pool.apply_async(check, (users, 0, 25, True)))
    
                                    tasks.append(pool.apply_async(restart))
                            finally:
                                with Then("logins during restart should work"):
                                    join(tasks, timeout)

                        tasks = []
                        with Pool(4) as pool:
                            try:
                                with When("I perform parallel login of users in each group after restart"):
                                    for users in user_groups.values():
                                        for check in checks:
                                            tasks.append(pool.apply_async(check, (users, 0, 10, False)))
                            finally:
                                with Then("logins after restart should work"):
                                    join(tasks, timeout)
def parallel_login(self, server, user_count=10, timeout=300, rbac=False):
    """Check that login of valid and invalid LDAP authenticated users works in parallel.
    """
    self.context.ldap_node = self.context.cluster.node(server)
    user = None

    users = [{
        "cn": f"parallel_user{i}",
        "userpassword": randomword(20)
    } for i in range(user_count)]

    with ldap_users(*users):
        with ldap_authenticated_users(*[{
                "username": user["cn"],
                "server": server
        } for user in users],
                                      rbac=rbac):

            def login_with_valid_username_and_password(users,
                                                       i,
                                                       iterations=10):
                with When(f"valid users try to login #{i}"):
                    for i in range(iterations):
                        random_user = users[random.randint(0, len(users) - 1)]
                        login_and_execute_query(
                            username=random_user["cn"],
                            password=random_user["userpassword"],
                            steps=False)

            def login_with_valid_username_and_invalid_password(
                    users, i, iterations=10):
                with When(
                        f"users try to login with valid username and invalid password #{i}"
                ):
                    for i in range(iterations):
                        random_user = users[random.randint(0, len(users) - 1)]
                        login_and_execute_query(
                            username=random_user["cn"],
                            password=(random_user["userpassword"] +
                                      randomword(1)),
                            exitcode=4,
                            message=
                            f"DB::Exception: {random_user['cn']}: Authentication failed: password is incorrect or there is no user with such name",
                            steps=False)

            def login_with_invalid_username_and_valid_password(
                    users, i, iterations=10):
                with When(
                        f"users try to login with invalid username and valid password #{i}"
                ):
                    for i in range(iterations):
                        random_user = dict(users[random.randint(
                            0,
                            len(users) - 1)])
                        random_user["cn"] += randomword(1)
                        login_and_execute_query(
                            username=random_user["cn"],
                            password=random_user["userpassword"],
                            exitcode=4,
                            message=
                            f"DB::Exception: {random_user['cn']}: Authentication failed: password is incorrect or there is no user with such name",
                            steps=False)

            with When("I login in parallel"):
                tasks = []
                with Pool(4) as pool:
                    try:
                        for i in range(5):
                            tasks.append(
                                pool.apply_async(
                                    login_with_valid_username_and_password, (
                                        users,
                                        i,
                                        50,
                                    )))
                            tasks.append(
                                pool.apply_async(
                                    login_with_valid_username_and_invalid_password,
                                    (
                                        users,
                                        i,
                                        50,
                                    )))
                            tasks.append(
                                pool.apply_async(
                                    login_with_invalid_username_and_valid_password,
                                    (
                                        users,
                                        i,
                                        50,
                                    )))
                    finally:
                        with Then("it should work"):
                            join(tasks, timeout=timeout)