mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-28 10:31:57 +00:00
Merge pull request #16249 from traceon/access-storage-added-log
Add a log message after an access storage is added
This commit is contained in:
commit
121ebfdc81
@ -35,7 +35,7 @@ RUN apt-get update \
|
|||||||
ENV TZ=Europe/Moscow
|
ENV TZ=Europe/Moscow
|
||||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
RUN pip3 install urllib3 testflows==1.6.48 docker-compose docker dicttoxml kazoo tzlocal
|
RUN pip3 install urllib3 testflows==1.6.57 docker-compose docker dicttoxml kazoo tzlocal
|
||||||
|
|
||||||
ENV DOCKER_CHANNEL stable
|
ENV DOCKER_CHANNEL stable
|
||||||
ENV DOCKER_VERSION 17.09.1-ce
|
ENV DOCKER_VERSION 17.09.1-ce
|
||||||
@ -72,5 +72,5 @@ RUN set -x \
|
|||||||
VOLUME /var/lib/docker
|
VOLUME /var/lib/docker
|
||||||
EXPOSE 2375
|
EXPOSE 2375
|
||||||
ENTRYPOINT ["dockerd-entrypoint.sh"]
|
ENTRYPOINT ["dockerd-entrypoint.sh"]
|
||||||
CMD ["sh", "-c", "python3 regression.py --no-color --local --clickhouse-binary-path ${CLICKHOUSE_TESTS_SERVER_BIN_PATH} --log test.log ${TESTFLOWS_OPTS}; cat test.log | tfs report results --format json > results.json"]
|
CMD ["sh", "-c", "python3 regression.py --no-color -o classic --local --clickhouse-binary-path ${CLICKHOUSE_TESTS_SERVER_BIN_PATH} --log test.log ${TESTFLOWS_OPTS}; cat test.log | tfs report results --format json > results.json"]
|
||||||
|
|
||||||
|
@ -137,7 +137,6 @@ AccessControlManager::AccessControlManager()
|
|||||||
|
|
||||||
AccessControlManager::~AccessControlManager() = default;
|
AccessControlManager::~AccessControlManager() = default;
|
||||||
|
|
||||||
|
|
||||||
void AccessControlManager::setUsersConfig(const Poco::Util::AbstractConfiguration & users_config_)
|
void AccessControlManager::setUsersConfig(const Poco::Util::AbstractConfiguration & users_config_)
|
||||||
{
|
{
|
||||||
auto storages = getStoragesPtr();
|
auto storages = getStoragesPtr();
|
||||||
@ -163,6 +162,7 @@ void AccessControlManager::addUsersConfigStorage(const String & storage_name_, c
|
|||||||
auto new_storage = std::make_shared<UsersConfigAccessStorage>(storage_name_, check_setting_name_function);
|
auto new_storage = std::make_shared<UsersConfigAccessStorage>(storage_name_, check_setting_name_function);
|
||||||
new_storage->setConfig(users_config_);
|
new_storage->setConfig(users_config_);
|
||||||
addStorage(new_storage);
|
addStorage(new_storage);
|
||||||
|
LOG_DEBUG(getLogger(), "Added {} access storage '{}', path: {}", String(new_storage->getStorageType()), new_storage->getStorageName(), new_storage->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccessControlManager::addUsersConfigStorage(
|
void AccessControlManager::addUsersConfigStorage(
|
||||||
@ -195,6 +195,7 @@ void AccessControlManager::addUsersConfigStorage(
|
|||||||
auto new_storage = std::make_shared<UsersConfigAccessStorage>(storage_name_, check_setting_name_function);
|
auto new_storage = std::make_shared<UsersConfigAccessStorage>(storage_name_, check_setting_name_function);
|
||||||
new_storage->load(users_config_path_, include_from_path_, preprocessed_dir_, get_zookeeper_function_);
|
new_storage->load(users_config_path_, include_from_path_, preprocessed_dir_, get_zookeeper_function_);
|
||||||
addStorage(new_storage);
|
addStorage(new_storage);
|
||||||
|
LOG_DEBUG(getLogger(), "Added {} access storage '{}', path: {}", String(new_storage->getStorageType()), new_storage->getStorageName(), new_storage->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccessControlManager::reloadUsersConfigs()
|
void AccessControlManager::reloadUsersConfigs()
|
||||||
@ -238,7 +239,9 @@ void AccessControlManager::addDiskStorage(const String & storage_name_, const St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addStorage(std::make_shared<DiskAccessStorage>(storage_name_, directory_, readonly_));
|
auto new_storage = std::make_shared<DiskAccessStorage>(storage_name_, directory_, readonly_);
|
||||||
|
addStorage(new_storage);
|
||||||
|
LOG_DEBUG(getLogger(), "Added {} access storage '{}', path: {}", String(new_storage->getStorageType()), new_storage->getStorageName(), new_storage->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -250,13 +253,17 @@ void AccessControlManager::addMemoryStorage(const String & storage_name_)
|
|||||||
if (auto memory_storage = typeid_cast<std::shared_ptr<MemoryAccessStorage>>(storage))
|
if (auto memory_storage = typeid_cast<std::shared_ptr<MemoryAccessStorage>>(storage))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addStorage(std::make_shared<MemoryAccessStorage>(storage_name_));
|
auto new_storage = std::make_shared<MemoryAccessStorage>(storage_name_);
|
||||||
|
addStorage(new_storage);
|
||||||
|
LOG_DEBUG(getLogger(), "Added {} access storage '{}'", String(new_storage->getStorageType()), new_storage->getStorageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AccessControlManager::addLDAPStorage(const String & storage_name_, const Poco::Util::AbstractConfiguration & config_, const String & prefix_)
|
void AccessControlManager::addLDAPStorage(const String & storage_name_, const Poco::Util::AbstractConfiguration & config_, const String & prefix_)
|
||||||
{
|
{
|
||||||
addStorage(std::make_shared<LDAPAccessStorage>(storage_name_, this, config_, prefix_));
|
auto new_storage = std::make_shared<LDAPAccessStorage>(storage_name_, this, config_, prefix_);
|
||||||
|
addStorage(new_storage);
|
||||||
|
LOG_DEBUG(getLogger(), "Added {} access storage '{}', LDAP server name: {}", String(new_storage->getStorageType()), new_storage->getStorageName(), new_storage->getLDAPServerName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ LDAPAccessStorage::LDAPAccessStorage(const String & storage_name_, AccessControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String LDAPAccessStorage::getLDAPServerName() const
|
||||||
|
{
|
||||||
|
return ldap_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LDAPAccessStorage::setConfiguration(AccessControlManager * access_control_manager_, const Poco::Util::AbstractConfiguration & config, const String & prefix)
|
void LDAPAccessStorage::setConfiguration(AccessControlManager * access_control_manager_, const Poco::Util::AbstractConfiguration & config, const String & prefix)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
@ -32,6 +32,8 @@ public:
|
|||||||
explicit LDAPAccessStorage(const String & storage_name_, AccessControlManager * access_control_manager_, const Poco::Util::AbstractConfiguration & config, const String & prefix);
|
explicit LDAPAccessStorage(const String & storage_name_, AccessControlManager * access_control_manager_, const Poco::Util::AbstractConfiguration & config, const String & prefix);
|
||||||
virtual ~LDAPAccessStorage() override = default;
|
virtual ~LDAPAccessStorage() override = default;
|
||||||
|
|
||||||
|
String getLDAPServerName() const;
|
||||||
|
|
||||||
public: // IAccessStorage implementations.
|
public: // IAccessStorage implementations.
|
||||||
virtual const char * getStorageType() const override;
|
virtual const char * getStorageType() const override;
|
||||||
virtual String getStorageParamsJSON() const override;
|
virtual String getStorageParamsJSON() const override;
|
||||||
|
@ -28,6 +28,8 @@ servers = {
|
|||||||
@TestStep(When)
|
@TestStep(When)
|
||||||
@Name("I login as {username} and execute query")
|
@Name("I login as {username} and execute query")
|
||||||
def login_and_execute_query(self, username, password, exitcode=None, message=None, steps=True):
|
def login_and_execute_query(self, username, password, exitcode=None, message=None, steps=True):
|
||||||
|
"""Execute query as some user.
|
||||||
|
"""
|
||||||
self.context.node.query("SELECT 1",
|
self.context.node.query("SELECT 1",
|
||||||
settings=[("user", username), ("password", password)],
|
settings=[("user", username), ("password", password)],
|
||||||
exitcode=exitcode or 0,
|
exitcode=exitcode or 0,
|
||||||
@ -35,7 +37,8 @@ def login_and_execute_query(self, username, password, exitcode=None, message=Non
|
|||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
def add_user_to_ldap_and_login(self, server, user=None, ch_user=None, login=None, exitcode=None, message=None, rbac=False):
|
def add_user_to_ldap_and_login(self, server, user=None, ch_user=None, login=None, exitcode=None, message=None, rbac=False):
|
||||||
"""Add user to LDAP and ClickHouse and then try to login."""
|
"""Add user to LDAP and ClickHouse and then try to login.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
|
|
||||||
if ch_user is None:
|
if ch_user is None:
|
||||||
@ -60,7 +63,8 @@ def add_user_to_ldap_and_login(self, server, user=None, ch_user=None, login=None
|
|||||||
RQ_SRS_007_LDAP_Authentication_Parallel_ValidAndInvalid("1.0")
|
RQ_SRS_007_LDAP_Authentication_Parallel_ValidAndInvalid("1.0")
|
||||||
)
|
)
|
||||||
def parallel_login(self, server, user_count=10, timeout=200, rbac=False):
|
def parallel_login(self, server, user_count=10, timeout=200, rbac=False):
|
||||||
"""Check that login of valid and invalid LDAP authenticated users works in parallel."""
|
"""Check that login of valid and invalid LDAP authenticated users works in parallel.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
@ -114,7 +118,8 @@ def parallel_login(self, server, user_count=10, timeout=200, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Invalid_DeletedUser("1.0")
|
RQ_SRS_007_LDAP_Authentication_Invalid_DeletedUser("1.0")
|
||||||
)
|
)
|
||||||
def login_after_user_is_deleted_from_ldap(self, server, rbac=False):
|
def login_after_user_is_deleted_from_ldap(self, server, rbac=False):
|
||||||
"""Check that login fails after user is deleted from LDAP."""
|
"""Check that login fails after user is deleted from LDAP.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
@ -146,7 +151,8 @@ def login_after_user_is_deleted_from_ldap(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_PasswordChanged("1.0")
|
RQ_SRS_007_LDAP_Authentication_PasswordChanged("1.0")
|
||||||
)
|
)
|
||||||
def login_after_user_password_changed_in_ldap(self, server, rbac=False):
|
def login_after_user_password_changed_in_ldap(self, server, rbac=False):
|
||||||
"""Check that login fails after user password is changed in LDAP."""
|
"""Check that login fails after user password is changed in LDAP.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
@ -182,7 +188,8 @@ def login_after_user_password_changed_in_ldap(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_UsernameChanged("1.0")
|
RQ_SRS_007_LDAP_Authentication_UsernameChanged("1.0")
|
||||||
)
|
)
|
||||||
def login_after_user_cn_changed_in_ldap(self, server, rbac=False):
|
def login_after_user_cn_changed_in_ldap(self, server, rbac=False):
|
||||||
"""Check that login fails after user cn is changed in LDAP."""
|
"""Check that login fails after user cn is changed in LDAP.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
new_user = None
|
new_user = None
|
||||||
@ -215,7 +222,8 @@ def login_after_user_cn_changed_in_ldap(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_LDAPServerRestart("1.0")
|
RQ_SRS_007_LDAP_Authentication_LDAPServerRestart("1.0")
|
||||||
)
|
)
|
||||||
def login_after_ldap_server_is_restarted(self, server, timeout=60, rbac=False):
|
def login_after_ldap_server_is_restarted(self, server, timeout=60, rbac=False):
|
||||||
"""Check that login succeeds after LDAP server is restarted."""
|
"""Check that login succeeds after LDAP server is restarted.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
@ -250,7 +258,8 @@ def login_after_ldap_server_is_restarted(self, server, timeout=60, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_ClickHouseServerRestart("1.0")
|
RQ_SRS_007_LDAP_Authentication_ClickHouseServerRestart("1.0")
|
||||||
)
|
)
|
||||||
def login_after_clickhouse_server_is_restarted(self, server, timeout=60, rbac=False):
|
def login_after_clickhouse_server_is_restarted(self, server, timeout=60, rbac=False):
|
||||||
"""Check that login succeeds after ClickHouse server is restarted."""
|
"""Check that login succeeds after ClickHouse server is restarted.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
@ -285,7 +294,8 @@ def login_after_clickhouse_server_is_restarted(self, server, timeout=60, rbac=Fa
|
|||||||
RQ_SRS_007_LDAP_Authentication_Password_Empty("1.0")
|
RQ_SRS_007_LDAP_Authentication_Password_Empty("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_with_valid_empty_password(self, server, rbac=False):
|
def valid_username_with_valid_empty_password(self, server, rbac=False):
|
||||||
"""Check that we can't login using valid username that has empty password."""
|
"""Check that we can't login using valid username that has empty password.
|
||||||
|
"""
|
||||||
user = {"cn": "empty_password", "userpassword": ""}
|
user = {"cn": "empty_password", "userpassword": ""}
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message = f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
message = f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
@ -298,7 +308,8 @@ def valid_username_with_valid_empty_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Password_Empty("1.0")
|
RQ_SRS_007_LDAP_Authentication_Password_Empty("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_and_invalid_empty_password(self, server, rbac=False):
|
def valid_username_and_invalid_empty_password(self, server, rbac=False):
|
||||||
"""Check that we can't login using valid username but invalid empty password."""
|
"""Check that we can't login using valid username but invalid empty password.
|
||||||
|
"""
|
||||||
username = "user_non_empty_password"
|
username = "user_non_empty_password"
|
||||||
user = {"cn": username, "userpassword": username}
|
user = {"cn": username, "userpassword": username}
|
||||||
login = {"password": ""}
|
login = {"password": ""}
|
||||||
@ -313,7 +324,8 @@ def valid_username_and_invalid_empty_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Valid("1.0")
|
RQ_SRS_007_LDAP_Authentication_Valid("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_and_password(self, server, rbac=False):
|
def valid_username_and_password(self, server, rbac=False):
|
||||||
"""Check that we can login using valid username and password."""
|
"""Check that we can login using valid username and password.
|
||||||
|
"""
|
||||||
username = "valid_username_and_password"
|
username = "valid_username_and_password"
|
||||||
user = {"cn": username, "userpassword": username}
|
user = {"cn": username, "userpassword": username}
|
||||||
|
|
||||||
@ -326,7 +338,8 @@ def valid_username_and_password(self, server, rbac=False):
|
|||||||
)
|
)
|
||||||
def valid_username_and_password_invalid_server(self, server=None, rbac=False):
|
def valid_username_and_password_invalid_server(self, server=None, rbac=False):
|
||||||
"""Check that we can't login using valid username and valid
|
"""Check that we can't login using valid username and valid
|
||||||
password but for a different server."""
|
password but for a different server.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node("openldap1")
|
self.context.ldap_node = self.context.cluster.node("openldap1")
|
||||||
|
|
||||||
user = {"username": "user2", "userpassword": "user2", "server": "openldap1"}
|
user = {"username": "user2", "userpassword": "user2", "server": "openldap1"}
|
||||||
@ -344,7 +357,8 @@ def valid_username_and_password_invalid_server(self, server=None, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Configuration_User_Name_Long("1.0")
|
RQ_SRS_007_LDAP_Configuration_User_Name_Long("1.0")
|
||||||
)
|
)
|
||||||
def valid_long_username_and_short_password(self, server, rbac=False):
|
def valid_long_username_and_short_password(self, server, rbac=False):
|
||||||
"""Check that we can login using valid very long username and short password."""
|
"""Check that we can login using valid very long username and short password.
|
||||||
|
"""
|
||||||
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||||
user = {"cn": username, "userpassword": "long_username"}
|
user = {"cn": username, "userpassword": "long_username"}
|
||||||
|
|
||||||
@ -355,7 +369,8 @@ def valid_long_username_and_short_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def invalid_long_username_and_valid_short_password(self, server, rbac=False):
|
def invalid_long_username_and_valid_short_password(self, server, rbac=False):
|
||||||
"""Check that we can't login using slightly invalid long username but valid password."""
|
"""Check that we can't login using slightly invalid long username but valid password.
|
||||||
|
"""
|
||||||
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||||
user = {"cn": username, "userpassword": "long_username"}
|
user = {"cn": username, "userpassword": "long_username"}
|
||||||
login = {"username": f"{username}?"}
|
login = {"username": f"{username}?"}
|
||||||
@ -371,7 +386,8 @@ def invalid_long_username_and_valid_short_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Password_Long("1.0")
|
RQ_SRS_007_LDAP_Authentication_Password_Long("1.0")
|
||||||
)
|
)
|
||||||
def valid_short_username_and_long_password(self, server, rbac=False):
|
def valid_short_username_and_long_password(self, server, rbac=False):
|
||||||
"""Check that we can login using valid short username with very long password."""
|
"""Check that we can login using valid short username with very long password.
|
||||||
|
"""
|
||||||
username = "long_password"
|
username = "long_password"
|
||||||
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
||||||
add_user_to_ldap_and_login(user=user, server=server, rbac=rbac)
|
add_user_to_ldap_and_login(user=user, server=server, rbac=rbac)
|
||||||
@ -381,7 +397,8 @@ def valid_short_username_and_long_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def valid_short_username_and_invalid_long_password(self, server, rbac=False):
|
def valid_short_username_and_invalid_long_password(self, server, rbac=False):
|
||||||
"""Check that we can't login using valid short username and invalid long password."""
|
"""Check that we can't login using valid short username and invalid long password.
|
||||||
|
"""
|
||||||
username = "long_password"
|
username = "long_password"
|
||||||
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
||||||
login = {"password": user["userpassword"] + "1"}
|
login = {"password": user["userpassword"] + "1"}
|
||||||
@ -396,7 +413,8 @@ def valid_short_username_and_invalid_long_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_and_invalid_password(self, server, rbac=False):
|
def valid_username_and_invalid_password(self, server, rbac=False):
|
||||||
"""Check that we can't login using valid username and invalid password."""
|
"""Check that we can't login using valid username and invalid password.
|
||||||
|
"""
|
||||||
username = "valid_username_and_invalid_password"
|
username = "valid_username_and_invalid_password"
|
||||||
user = {"cn": username, "userpassword": username}
|
user = {"cn": username, "userpassword": username}
|
||||||
login = {"password": user["userpassword"] + "1"}
|
login = {"password": user["userpassword"] + "1"}
|
||||||
@ -411,7 +429,8 @@ def valid_username_and_invalid_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
RQ_SRS_007_LDAP_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def invalid_username_and_valid_password(self, server, rbac=False):
|
def invalid_username_and_valid_password(self, server, rbac=False):
|
||||||
"""Check that we can't login using slightly invalid username but valid password."""
|
"""Check that we can't login using slightly invalid username but valid password.
|
||||||
|
"""
|
||||||
username = "invalid_username_and_valid_password"
|
username = "invalid_username_and_valid_password"
|
||||||
user = {"cn": username, "userpassword": username}
|
user = {"cn": username, "userpassword": username}
|
||||||
login = {"username": user["cn"] + "1"}
|
login = {"username": user["cn"] + "1"}
|
||||||
@ -428,7 +447,8 @@ def invalid_username_and_valid_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Configuration_User_Name_UTF8("1.0")
|
RQ_SRS_007_LDAP_Configuration_User_Name_UTF8("1.0")
|
||||||
)
|
)
|
||||||
def valid_utf8_username_and_ascii_password(self, server, rbac=False):
|
def valid_utf8_username_and_ascii_password(self, server, rbac=False):
|
||||||
"""Check that we can login using valid utf-8 username with ascii password."""
|
"""Check that we can login using valid utf-8 username with ascii password.
|
||||||
|
"""
|
||||||
username = "utf8_username_Gãńdåłf_Thê_Gręât"
|
username = "utf8_username_Gãńdåłf_Thê_Gręât"
|
||||||
user = {"cn": username, "userpassword": "utf8_username"}
|
user = {"cn": username, "userpassword": "utf8_username"}
|
||||||
|
|
||||||
@ -440,7 +460,8 @@ def valid_utf8_username_and_ascii_password(self, server, rbac=False):
|
|||||||
RQ_SRS_007_LDAP_Authentication_Password_UTF8("1.0")
|
RQ_SRS_007_LDAP_Authentication_Password_UTF8("1.0")
|
||||||
)
|
)
|
||||||
def valid_ascii_username_and_utf8_password(self, server, rbac=False):
|
def valid_ascii_username_and_utf8_password(self, server, rbac=False):
|
||||||
"""Check that we can login using valid ascii username with utf-8 password."""
|
"""Check that we can login using valid ascii username with utf-8 password.
|
||||||
|
"""
|
||||||
username = "utf8_password"
|
username = "utf8_password"
|
||||||
user = {"cn": username, "userpassword": "utf8_password_Gãńdåłf_Thê_Gręât"}
|
user = {"cn": username, "userpassword": "utf8_password_Gãńdåłf_Thê_Gręât"}
|
||||||
|
|
||||||
@ -449,7 +470,8 @@ def valid_ascii_username_and_utf8_password(self, server, rbac=False):
|
|||||||
@TestScenario
|
@TestScenario
|
||||||
def empty_username_and_empty_password(self, server=None, rbac=False):
|
def empty_username_and_empty_password(self, server=None, rbac=False):
|
||||||
"""Check that we can login using empty username and empty password as
|
"""Check that we can login using empty username and empty password as
|
||||||
it will use the default user and that has an empty password."""
|
it will use the default user and that has an empty password.
|
||||||
|
"""
|
||||||
login_and_execute_query(username="", password="")
|
login_and_execute_query(username="", password="")
|
||||||
|
|
||||||
@TestOutline(Feature)
|
@TestOutline(Feature)
|
||||||
|
@ -95,6 +95,8 @@ def add_config(config, timeout=20, restart=False):
|
|||||||
if exitcode == 0:
|
if exitcode == 0:
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
if settings.debug:
|
||||||
|
node.command(f"cat /var/lib/clickhouse/preprocessed_configs/{config.preprocessed_name}")
|
||||||
assert exitcode == 0, error()
|
assert exitcode == 0, error()
|
||||||
|
|
||||||
def wait_for_config_to_be_loaded():
|
def wait_for_config_to_be_loaded():
|
||||||
|
@ -98,7 +98,8 @@ def starttls_with_custom_port(self):
|
|||||||
login(servers, *users)
|
login(servers, *users)
|
||||||
|
|
||||||
def tls_connection(enable_tls, tls_require_cert):
|
def tls_connection(enable_tls, tls_require_cert):
|
||||||
"""Try to login using LDAP user authentication over a TLS connection."""
|
"""Try to login using LDAP user authentication over a TLS connection.
|
||||||
|
"""
|
||||||
servers = {
|
servers = {
|
||||||
"openldap2": {
|
"openldap2": {
|
||||||
"host": "openldap2",
|
"host": "openldap2",
|
||||||
@ -152,7 +153,8 @@ def tls(self):
|
|||||||
RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_Default("1.0")
|
RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_Default("1.0")
|
||||||
)
|
)
|
||||||
def tls_enable_tls_default_yes(self):
|
def tls_enable_tls_default_yes(self):
|
||||||
"""Check that the default value for the `enable_tls` is set to `yes`."""
|
"""Check that the default value for the `enable_tls` is set to `yes`.
|
||||||
|
"""
|
||||||
servers = {
|
servers = {
|
||||||
"openldap2": {
|
"openldap2": {
|
||||||
"host": "openldap2",
|
"host": "openldap2",
|
||||||
@ -171,7 +173,8 @@ def tls_enable_tls_default_yes(self):
|
|||||||
RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Default("1.0")
|
RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Default("1.0")
|
||||||
)
|
)
|
||||||
def tls_require_cert_default_demand(self):
|
def tls_require_cert_default_demand(self):
|
||||||
"""Check that the default value for the `tls_require_cert` is set to `demand`."""
|
"""Check that the default value for the `tls_require_cert` is set to `demand`.
|
||||||
|
"""
|
||||||
servers = {
|
servers = {
|
||||||
"openldap2": {
|
"openldap2": {
|
||||||
"host": "openldap2",
|
"host": "openldap2",
|
||||||
@ -210,7 +213,8 @@ def starttls(self):
|
|||||||
RQ_SRS_007_LDAP_Configuration_Server_TLSCipherSuite("1.0")
|
RQ_SRS_007_LDAP_Configuration_Server_TLSCipherSuite("1.0")
|
||||||
)
|
)
|
||||||
def tls_cipher_suite(self):
|
def tls_cipher_suite(self):
|
||||||
"""Check that `tls_cipher_suite` parameter can be used specify allowed cipher suites."""
|
"""Check that `tls_cipher_suite` parameter can be used specify allowed cipher suites.
|
||||||
|
"""
|
||||||
servers = {
|
servers = {
|
||||||
"openldap4": {
|
"openldap4": {
|
||||||
"host": "openldap4",
|
"host": "openldap4",
|
||||||
@ -241,7 +245,8 @@ def tls_cipher_suite(self):
|
|||||||
])
|
])
|
||||||
def tls_minimum_protocol_version(self, version, exitcode, message):
|
def tls_minimum_protocol_version(self, version, exitcode, message):
|
||||||
"""Check that `tls_minimum_protocol_version` parameter can be used specify
|
"""Check that `tls_minimum_protocol_version` parameter can be used specify
|
||||||
to specify the minimum protocol version of SSL/TLS."""
|
to specify the minimum protocol version of SSL/TLS.
|
||||||
|
"""
|
||||||
|
|
||||||
servers = {
|
servers = {
|
||||||
"openldap4": {
|
"openldap4": {
|
||||||
@ -278,6 +283,8 @@ def tls_minimum_protocol_version(self, version, exitcode, message):
|
|||||||
@TestFeature
|
@TestFeature
|
||||||
@Name("connection protocols")
|
@Name("connection protocols")
|
||||||
def feature(self, node="clickhouse1"):
|
def feature(self, node="clickhouse1"):
|
||||||
|
"""Check different LDAP connection protocols.
|
||||||
|
"""
|
||||||
self.context.node = self.context.cluster.node(node)
|
self.context.node = self.context.cluster.node(node)
|
||||||
|
|
||||||
for scenario in loads(current_module(), Scenario):
|
for scenario in loads(current_module(), Scenario):
|
||||||
|
@ -14,6 +14,7 @@ def scenario(self, node="clickhouse1"):
|
|||||||
authenticate users.
|
authenticate users.
|
||||||
"""
|
"""
|
||||||
self.context.node = self.context.cluster.node(node)
|
self.context.node = self.context.cluster.node(node)
|
||||||
|
|
||||||
servers = {
|
servers = {
|
||||||
"openldap1": {
|
"openldap1": {
|
||||||
"host": "openldap1",
|
"host": "openldap1",
|
||||||
@ -35,4 +36,6 @@ def scenario(self, node="clickhouse1"):
|
|||||||
{"server": "openldap1", "username": "user1", "password": "user1", "login": True},
|
{"server": "openldap1", "username": "user1", "password": "user1", "login": True},
|
||||||
{"server": "openldap2", "username": "user2", "password": "user2", "login": True}
|
{"server": "openldap2", "username": "user2", "password": "user2", "login": True}
|
||||||
]
|
]
|
||||||
login(servers, *users)
|
|
||||||
|
with When("I add multiple LDAP servers and users that use different servers and try to login"):
|
||||||
|
login(servers, *users)
|
||||||
|
@ -267,5 +267,6 @@ def feature(self, node="clickhouse1"):
|
|||||||
"""Check that LDAP server configuration.
|
"""Check that LDAP server configuration.
|
||||||
"""
|
"""
|
||||||
self.context.node = self.context.cluster.node(node)
|
self.context.node = self.context.cluster.node(node)
|
||||||
|
|
||||||
for scenario in loads(current_module(), Scenario):
|
for scenario in loads(current_module(), Scenario):
|
||||||
scenario()
|
scenario()
|
||||||
|
@ -28,7 +28,8 @@ servers = {
|
|||||||
|
|
||||||
@TestOutline
|
@TestOutline
|
||||||
def add_user_to_ldap_and_login(self, server, user=None, ch_user=None, login=None, exitcode=None, message=None):
|
def add_user_to_ldap_and_login(self, server, user=None, ch_user=None, login=None, exitcode=None, message=None):
|
||||||
"""Add user to LDAP and ClickHouse and then try to login."""
|
"""Add user to LDAP and ClickHouse and then try to login.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
|
|
||||||
if ch_user is None:
|
if ch_user is None:
|
||||||
@ -91,23 +92,25 @@ def parallel_login(self, server, user_count=10, timeout=200):
|
|||||||
with Given("a group of LDAP users"):
|
with Given("a group of LDAP users"):
|
||||||
users = [{"cn": f"parallel_user{i}", "userpassword": randomword(20)} for i in range(user_count)]
|
users = [{"cn": f"parallel_user{i}", "userpassword": randomword(20)} for i in range(user_count)]
|
||||||
|
|
||||||
with ldap_users(*users):
|
with rbac_roles("ldap_role") as roles:
|
||||||
tasks = []
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
try:
|
with ldap_users(*users):
|
||||||
with When("users try to login in parallel", description="""
|
tasks = []
|
||||||
* with valid username and password
|
try:
|
||||||
* with invalid username and valid password
|
with When("users try to login in parallel", description="""
|
||||||
* with valid username and invalid password
|
* with valid username and password
|
||||||
"""):
|
* with invalid username and valid password
|
||||||
p = Pool(15)
|
* with valid username and invalid password
|
||||||
for i in range(25):
|
"""):
|
||||||
tasks.append(p.apply_async(login_with_valid_username_and_password, (users, i, 50,)))
|
p = Pool(15)
|
||||||
tasks.append(p.apply_async(login_with_valid_username_and_invalid_password, (users, i, 50,)))
|
for i in range(25):
|
||||||
tasks.append(p.apply_async(login_with_invalid_username_and_valid_password, (users, i, 50,)))
|
tasks.append(p.apply_async(login_with_valid_username_and_password, (users, i, 50,)))
|
||||||
|
tasks.append(p.apply_async(login_with_valid_username_and_invalid_password, (users, i, 50,)))
|
||||||
|
tasks.append(p.apply_async(login_with_invalid_username_and_valid_password, (users, i, 50,)))
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
with Then("it should work"):
|
with Then("it should work"):
|
||||||
join(tasks, timeout)
|
join(tasks, timeout)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -124,34 +127,36 @@ def parallel_login_with_the_same_user(self, server, timeout=200):
|
|||||||
with Given("only one LDAP user"):
|
with Given("only one LDAP user"):
|
||||||
users = [{"cn": f"parallel_user1", "userpassword": randomword(20)}]
|
users = [{"cn": f"parallel_user1", "userpassword": randomword(20)}]
|
||||||
|
|
||||||
with ldap_users(*users):
|
with rbac_roles("ldap_role") as roles:
|
||||||
tasks = []
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
try:
|
with ldap_users(*users):
|
||||||
with When("the same user tries to login in parallel", description="""
|
tasks = []
|
||||||
* with valid username and password
|
try:
|
||||||
* with invalid username and valid password
|
with When("the same user tries to login in parallel", description="""
|
||||||
* with valid username and invalid password
|
* with valid username and password
|
||||||
"""):
|
* with invalid username and valid password
|
||||||
p = Pool(15)
|
* with valid username and invalid password
|
||||||
for i in range(25):
|
"""):
|
||||||
tasks.append(p.apply_async(login_with_valid_username_and_password, (users, i, 50,)))
|
p = Pool(15)
|
||||||
tasks.append(p.apply_async(login_with_valid_username_and_invalid_password, (users, i, 50,)))
|
for i in range(25):
|
||||||
tasks.append(p.apply_async(login_with_invalid_username_and_valid_password, (users, i, 50,)))
|
tasks.append(p.apply_async(login_with_valid_username_and_password, (users, i, 50,)))
|
||||||
|
tasks.append(p.apply_async(login_with_valid_username_and_invalid_password, (users, i, 50,)))
|
||||||
|
tasks.append(p.apply_async(login_with_invalid_username_and_valid_password, (users, i, 50,)))
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
with Then("it should work"):
|
with Then("it should work"):
|
||||||
join(tasks, timeout)
|
join(tasks, timeout)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
def login_after_ldap_external_user_directory_is_removed(self, server):
|
def login_after_ldap_external_user_directory_is_removed(self, server):
|
||||||
"""Check that ClickHouse stops authenticating LDAP users
|
"""Check that ClickHouse stops authenticating LDAP users
|
||||||
after LDAP external user directory is removed.
|
after LDAP external user directory is removed.
|
||||||
"""
|
"""
|
||||||
with When("I attempt to login after LDAP external user directory is added"):
|
with When("I login after LDAP external user directory is added"):
|
||||||
with ldap_external_user_directory(server="openldap2", roles=[], restart=True):
|
with ldap_external_user_directory(server="openldap2", roles=[], restart=True):
|
||||||
login_and_execute_query(username="user2", password="user2")
|
login_and_execute_query(username="user2", password="user2")
|
||||||
|
|
||||||
with When("I attempt to login after LDAP external user directory is removed"):
|
with And("I attempt to login after LDAP external user directory is removed"):
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message = f"DB::Exception: user2: Authentication failed: password is incorrect or there is no user with such name"
|
message = f"DB::Exception: user2: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
login_and_execute_query(username="user2", password="user2", exitcode=exitcode, message=message)
|
login_and_execute_query(username="user2", password="user2", exitcode=exitcode, message=message)
|
||||||
@ -318,29 +323,34 @@ def parallel_login_with_rbac_users(self, server, user_count=10, timeout=200):
|
|||||||
|
|
||||||
users = [{"cn": f"parallel_user{i}", "userpassword": randomword(20)} for i in range(user_count)]
|
users = [{"cn": f"parallel_user{i}", "userpassword": randomword(20)} for i in range(user_count)]
|
||||||
|
|
||||||
with rbac_users(*users):
|
with rbac_roles("ldap_role") as roles:
|
||||||
tasks = []
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
try:
|
with rbac_users(*users):
|
||||||
with When("I login in parallel"):
|
tasks = []
|
||||||
p = Pool(15)
|
try:
|
||||||
for i in range(25):
|
with When("I login in parallel"):
|
||||||
tasks.append(p.apply_async(login_with_valid_username_and_password, (users, i, 50,)))
|
p = Pool(15)
|
||||||
tasks.append(p.apply_async(login_with_valid_username_and_invalid_password, (users, i, 50,)))
|
for i in range(25):
|
||||||
tasks.append(p.apply_async(login_with_invalid_username_and_valid_password, (users, i, 50,)))
|
tasks.append(p.apply_async(login_with_valid_username_and_password, (users, i, 50,)))
|
||||||
finally:
|
tasks.append(p.apply_async(login_with_valid_username_and_invalid_password, (users, i, 50,)))
|
||||||
with Then("it should work"):
|
tasks.append(p.apply_async(login_with_invalid_username_and_valid_password, (users, i, 50,)))
|
||||||
join(tasks, timeout)
|
finally:
|
||||||
|
with Then("it should work"):
|
||||||
|
join(tasks, timeout)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Users_Authentication_NewUsers("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Users_Authentication_NewUsers("1.0")
|
||||||
)
|
)
|
||||||
def login_after_user_is_added_to_ldap(self, server):
|
def login_after_user_is_added_to_ldap(self, server):
|
||||||
"""Check that user can login as soon as it is added to LDAP."""
|
"""Check that user can login as soon as it is added to LDAP.
|
||||||
|
"""
|
||||||
user = {"cn": "myuser", "userpassword": "myuser"}
|
user = {"cn": "myuser", "userpassword": "myuser"}
|
||||||
|
|
||||||
with When(f"I add user to LDAP and try to login"):
|
with rbac_roles("ldap_role") as roles:
|
||||||
add_user_to_ldap_and_login(user=user, server=server)
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
with When(f"I add user to LDAP and try to login"):
|
||||||
|
add_user_to_ldap_and_login(user=user, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -348,29 +358,32 @@ def login_after_user_is_added_to_ldap(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_DeletedUsers("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_DeletedUsers("1.0")
|
||||||
)
|
)
|
||||||
def login_after_user_is_deleted_from_ldap(self, server):
|
def login_after_user_is_deleted_from_ldap(self, server):
|
||||||
"""Check that login fails after user is deleted from LDAP."""
|
"""Check that login fails after user is deleted from LDAP.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
try:
|
with rbac_roles("ldap_role") as roles:
|
||||||
with Given(f"I add user to LDAP"):
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
user = {"cn": "myuser", "userpassword": "myuser"}
|
try:
|
||||||
user = add_user_to_ldap(**user)
|
with Given(f"I add user to LDAP"):
|
||||||
|
user = {"cn": "myuser", "userpassword": "myuser"}
|
||||||
|
user = add_user_to_ldap(**user)
|
||||||
|
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
||||||
|
|
||||||
with When("I delete this user from LDAP"):
|
with When("I delete this user from LDAP"):
|
||||||
delete_user_from_ldap(user)
|
delete_user_from_ldap(user)
|
||||||
|
|
||||||
with Then("when I try to login again it should fail"):
|
with Then("when I try to login again it should fail"):
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"],
|
login_and_execute_query(username=user["cn"], password=user["userpassword"],
|
||||||
exitcode=4,
|
exitcode=4,
|
||||||
message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
with Finally("I make sure LDAP user is deleted"):
|
with Finally("I make sure LDAP user is deleted"):
|
||||||
if user is not None:
|
if user is not None:
|
||||||
delete_user_from_ldap(user, exitcode=None)
|
delete_user_from_ldap(user, exitcode=None)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -378,33 +391,36 @@ def login_after_user_is_deleted_from_ldap(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_PasswordChanged("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_PasswordChanged("1.0")
|
||||||
)
|
)
|
||||||
def login_after_user_password_changed_in_ldap(self, server):
|
def login_after_user_password_changed_in_ldap(self, server):
|
||||||
"""Check that login fails after user password is changed in LDAP."""
|
"""Check that login fails after user password is changed in LDAP.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
try:
|
with rbac_roles("ldap_role") as roles:
|
||||||
with Given(f"I add user to LDAP"):
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
user = {"cn": "myuser", "userpassword": "myuser"}
|
try:
|
||||||
user = add_user_to_ldap(**user)
|
with Given(f"I add user to LDAP"):
|
||||||
|
user = {"cn": "myuser", "userpassword": "myuser"}
|
||||||
|
user = add_user_to_ldap(**user)
|
||||||
|
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
||||||
|
|
||||||
with When("I change user password in LDAP"):
|
with When("I change user password in LDAP"):
|
||||||
change_user_password_in_ldap(user, "newpassword")
|
change_user_password_in_ldap(user, "newpassword")
|
||||||
|
|
||||||
with Then("when I try to login again it should fail"):
|
with Then("when I try to login again it should fail"):
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"],
|
login_and_execute_query(username=user["cn"], password=user["userpassword"],
|
||||||
exitcode=4,
|
exitcode=4,
|
||||||
message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
)
|
)
|
||||||
|
|
||||||
with And("when I try to login with the new password it should work"):
|
with And("when I try to login with the new password it should work"):
|
||||||
login_and_execute_query(username=user["cn"], password="newpassword")
|
login_and_execute_query(username=user["cn"], password="newpassword")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
with Finally("I make sure LDAP user is deleted"):
|
with Finally("I make sure LDAP user is deleted"):
|
||||||
if user is not None:
|
if user is not None:
|
||||||
delete_user_from_ldap(user, exitcode=None)
|
delete_user_from_ldap(user, exitcode=None)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -412,30 +428,33 @@ def login_after_user_password_changed_in_ldap(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_UsernameChanged("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_UsernameChanged("1.0")
|
||||||
)
|
)
|
||||||
def login_after_user_cn_changed_in_ldap(self, server):
|
def login_after_user_cn_changed_in_ldap(self, server):
|
||||||
"""Check that login fails after user cn is changed in LDAP."""
|
"""Check that login fails after user cn is changed in LDAP.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
new_user = None
|
new_user = None
|
||||||
|
|
||||||
try:
|
with rbac_roles("ldap_role") as roles:
|
||||||
with Given(f"I add user to LDAP"):
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
user = {"cn": "myuser", "userpassword": "myuser"}
|
try:
|
||||||
user = add_user_to_ldap(**user)
|
with Given(f"I add user to LDAP"):
|
||||||
|
user = {"cn": "myuser", "userpassword": "myuser"}
|
||||||
|
user = add_user_to_ldap(**user)
|
||||||
|
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
||||||
|
|
||||||
with When("I change user password in LDAP"):
|
with When("I change user password in LDAP"):
|
||||||
new_user = change_user_cn_in_ldap(user, "myuser2")
|
new_user = change_user_cn_in_ldap(user, "myuser2")
|
||||||
|
|
||||||
with Then("when I try to login again it should fail"):
|
with Then("when I try to login again it should fail"):
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"],
|
login_and_execute_query(username=user["cn"], password=user["userpassword"],
|
||||||
exitcode=4,
|
exitcode=4,
|
||||||
message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
with Finally("I make sure LDAP user is deleted"):
|
with Finally("I make sure LDAP user is deleted"):
|
||||||
if new_user is not None:
|
if new_user is not None:
|
||||||
delete_user_from_ldap(new_user, exitcode=None)
|
delete_user_from_ldap(new_user, exitcode=None)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -443,33 +462,36 @@ def login_after_user_cn_changed_in_ldap(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_LDAPServerRestart("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_LDAPServerRestart("1.0")
|
||||||
)
|
)
|
||||||
def login_after_ldap_server_is_restarted(self, server, timeout=60):
|
def login_after_ldap_server_is_restarted(self, server, timeout=60):
|
||||||
"""Check that login succeeds after LDAP server is restarted."""
|
"""Check that login succeeds after LDAP server is restarted.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
try:
|
with rbac_roles("ldap_role") as roles:
|
||||||
with Given(f"I add user to LDAP"):
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
user = {"cn": "myuser", "userpassword": getuid()}
|
try:
|
||||||
user = add_user_to_ldap(**user)
|
with Given(f"I add user to LDAP"):
|
||||||
|
user = {"cn": "myuser", "userpassword": getuid()}
|
||||||
|
user = add_user_to_ldap(**user)
|
||||||
|
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
||||||
|
|
||||||
with When("I restart LDAP server"):
|
with When("I restart LDAP server"):
|
||||||
self.context.ldap_node.restart()
|
self.context.ldap_node.restart()
|
||||||
|
|
||||||
with Then("I try to login until it works", description=f"timeout {timeout} sec"):
|
with Then("I try to login until it works", description=f"timeout {timeout} sec"):
|
||||||
started = time.time()
|
started = time.time()
|
||||||
while True:
|
while True:
|
||||||
r = self.context.node.query("SELECT 1",
|
r = self.context.node.query("SELECT 1",
|
||||||
settings=[("user", user["cn"]), ("password", user["userpassword"])],
|
settings=[("user", user["cn"]), ("password", user["userpassword"])],
|
||||||
no_checks=True)
|
no_checks=True)
|
||||||
if r.exitcode == 0:
|
if r.exitcode == 0:
|
||||||
break
|
break
|
||||||
assert time.time() - started < timeout, error(r.output)
|
assert time.time() - started < timeout, error(r.output)
|
||||||
finally:
|
finally:
|
||||||
with Finally("I make sure LDAP user is deleted"):
|
with Finally("I make sure LDAP user is deleted"):
|
||||||
if user is not None:
|
if user is not None:
|
||||||
delete_user_from_ldap(user, exitcode=None)
|
delete_user_from_ldap(user, exitcode=None)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -477,33 +499,36 @@ def login_after_ldap_server_is_restarted(self, server, timeout=60):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_ClickHouseServerRestart("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_ClickHouseServerRestart("1.0")
|
||||||
)
|
)
|
||||||
def login_after_clickhouse_server_is_restarted(self, server, timeout=60):
|
def login_after_clickhouse_server_is_restarted(self, server, timeout=60):
|
||||||
"""Check that login succeeds after ClickHouse server is restarted."""
|
"""Check that login succeeds after ClickHouse server is restarted.
|
||||||
|
"""
|
||||||
self.context.ldap_node = self.context.cluster.node(server)
|
self.context.ldap_node = self.context.cluster.node(server)
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
try:
|
with rbac_roles("ldap_role") as roles:
|
||||||
with Given(f"I add user to LDAP"):
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
user = {"cn": "myuser", "userpassword": getuid()}
|
try:
|
||||||
user = add_user_to_ldap(**user)
|
with Given(f"I add user to LDAP"):
|
||||||
|
user = {"cn": "myuser", "userpassword": getuid()}
|
||||||
|
user = add_user_to_ldap(**user)
|
||||||
|
|
||||||
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
login_and_execute_query(username=user["cn"], password=user["userpassword"])
|
||||||
|
|
||||||
with When("I restart ClickHouse server"):
|
with When("I restart ClickHouse server"):
|
||||||
self.context.node.restart()
|
self.context.node.restart()
|
||||||
|
|
||||||
with Then("I try to login until it works", description=f"timeout {timeout} sec"):
|
with Then("I try to login until it works", description=f"timeout {timeout} sec"):
|
||||||
started = time.time()
|
started = time.time()
|
||||||
while True:
|
while True:
|
||||||
r = self.context.node.query("SELECT 1",
|
r = self.context.node.query("SELECT 1",
|
||||||
settings=[("user", user["cn"]), ("password", user["userpassword"])],
|
settings=[("user", user["cn"]), ("password", user["userpassword"])],
|
||||||
no_checks=True)
|
no_checks=True)
|
||||||
if r.exitcode == 0:
|
if r.exitcode == 0:
|
||||||
break
|
break
|
||||||
assert time.time() - started < timeout, error(r.output)
|
assert time.time() - started < timeout, error(r.output)
|
||||||
finally:
|
finally:
|
||||||
with Finally("I make sure LDAP user is deleted"):
|
with Finally("I make sure LDAP user is deleted"):
|
||||||
if user is not None:
|
if user is not None:
|
||||||
delete_user_from_ldap(user, exitcode=None)
|
delete_user_from_ldap(user, exitcode=None)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -511,12 +536,15 @@ def login_after_clickhouse_server_is_restarted(self, server, timeout=60):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_Empty("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_Empty("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_with_valid_empty_password(self, server):
|
def valid_username_with_valid_empty_password(self, server):
|
||||||
"""Check that we can't login using valid username that has empty password."""
|
"""Check that we can't login using valid username that has empty password.
|
||||||
|
"""
|
||||||
user = {"cn": "empty_password", "userpassword": ""}
|
user = {"cn": "empty_password", "userpassword": ""}
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message = f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
message = f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, exitcode=exitcode, message=message, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, exitcode=exitcode, message=message, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -524,41 +552,50 @@ def valid_username_with_valid_empty_password(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_Empty("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_Empty("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_and_invalid_empty_password(self, server):
|
def valid_username_and_invalid_empty_password(self, server):
|
||||||
"""Check that we can't login using valid username but invalid empty password."""
|
"""Check that we can't login using valid username but invalid empty password.
|
||||||
username = "user_non_empty_password"
|
"""
|
||||||
user = {"cn": username, "userpassword": username}
|
username = "user_non_empty_password"
|
||||||
login = {"password": ""}
|
user = {"cn": username, "userpassword": username}
|
||||||
|
login = {"password": ""}
|
||||||
|
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message = f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name"
|
message = f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Valid("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Valid("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_and_password(self, server):
|
def valid_username_and_password(self, server):
|
||||||
"""Check that we can login using valid username and password."""
|
"""Check that we can login using valid username and password.
|
||||||
username = "valid_username_and_password"
|
"""
|
||||||
user = {"cn": username, "userpassword": username}
|
username = "valid_username_and_password"
|
||||||
|
user = {"cn": username, "userpassword": username}
|
||||||
|
|
||||||
with When(f"I add user {username} to LDAP and try to login"):
|
with rbac_roles("ldap_role") as roles:
|
||||||
add_user_to_ldap_and_login(user=user, server=server)
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
with When(f"I add user {username} to LDAP and try to login"):
|
||||||
|
add_user_to_ldap_and_login(user=user, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_and_password_invalid_server(self, server=None):
|
def valid_username_and_password_invalid_server(self, server=None):
|
||||||
"""Check that we can't login using valid username and valid
|
"""Check that we can't login using valid username and valid
|
||||||
password but for a different server."""
|
password but for a different server.
|
||||||
self.context.ldap_node = self.context.cluster.node("openldap1")
|
"""
|
||||||
|
self.context.ldap_node = self.context.cluster.node("openldap1")
|
||||||
|
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message = f"DB::Exception: user2: Authentication failed: password is incorrect or there is no user with such name"
|
message = f"DB::Exception: user2: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
|
|
||||||
login_and_execute_query(username="user2", password="user2", exitcode=exitcode, message=message)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
login_and_execute_query(username="user2", password="user2", exitcode=exitcode, message=message)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -566,26 +603,32 @@ def valid_username_and_password_invalid_server(self, server=None):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Username_Long("1.0"),
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Username_Long("1.0"),
|
||||||
)
|
)
|
||||||
def valid_long_username_and_short_password(self, server):
|
def valid_long_username_and_short_password(self, server):
|
||||||
"""Check that we can login using valid very long username and short password."""
|
"""Check that we can login using valid very long username and short password.
|
||||||
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
"""
|
||||||
user = {"cn": username, "userpassword": "long_username"}
|
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||||
|
user = {"cn": username, "userpassword": "long_username"}
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def invalid_long_username_and_valid_short_password(self, server):
|
def invalid_long_username_and_valid_short_password(self, server):
|
||||||
"""Check that we can't login using slightly invalid long username but valid password."""
|
"""Check that we can't login using slightly invalid long username but valid password.
|
||||||
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
"""
|
||||||
user = {"cn": username, "userpassword": "long_username"}
|
username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||||
login = {"username": f"{username}?"}
|
user = {"cn": username, "userpassword": "long_username"}
|
||||||
|
login = {"username": f"{username}?"}
|
||||||
|
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message=f"DB::Exception: {login['username']}: Authentication failed: password is incorrect or there is no user with such name"
|
message=f"DB::Exception: {login['username']}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -593,55 +636,68 @@ def invalid_long_username_and_valid_short_password(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_Long("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_Long("1.0")
|
||||||
)
|
)
|
||||||
def valid_short_username_and_long_password(self, server):
|
def valid_short_username_and_long_password(self, server):
|
||||||
"""Check that we can login using valid short username with very long password."""
|
"""Check that we can login using valid short username with very long password.
|
||||||
username = "long_password"
|
"""
|
||||||
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
username = "long_password"
|
||||||
add_user_to_ldap_and_login(user=user, server=server)
|
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
||||||
|
|
||||||
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def valid_short_username_and_invalid_long_password(self, server):
|
def valid_short_username_and_invalid_long_password(self, server):
|
||||||
"""Check that we can't login using valid short username and invalid long password."""
|
"""Check that we can't login using valid short username and invalid long password.
|
||||||
username = "long_password"
|
"""
|
||||||
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
username = "long_password"
|
||||||
login = {"password": user["userpassword"] + "1"}
|
user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
||||||
|
login = {"password": user["userpassword"] + "1"}
|
||||||
|
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message=f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name"
|
message=f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def valid_username_and_invalid_password(self, server):
|
def valid_username_and_invalid_password(self, server):
|
||||||
"""Check that we can't login using valid username and invalid password."""
|
"""Check that we can't login using valid username and invalid password.
|
||||||
username = "valid_username_and_invalid_password"
|
"""
|
||||||
user = {"cn": username, "userpassword": username}
|
username = "valid_username_and_invalid_password"
|
||||||
login = {"password": user["userpassword"] + "1"}
|
user = {"cn": username, "userpassword": username}
|
||||||
|
login = {"password": user["userpassword"] + "1"}
|
||||||
|
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message=f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name"
|
message=f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Invalid("1.0")
|
||||||
)
|
)
|
||||||
def invalid_username_and_valid_password(self, server):
|
def invalid_username_and_valid_password(self, server):
|
||||||
"""Check that we can't login using slightly invalid username but valid password."""
|
"""Check that we can't login using slightly invalid username but valid password.
|
||||||
username = "invalid_username_and_valid_password"
|
"""
|
||||||
user = {"cn": username, "userpassword": username}
|
username = "invalid_username_and_valid_password"
|
||||||
login = {"username": user["cn"] + "1"}
|
user = {"cn": username, "userpassword": username}
|
||||||
|
login = {"username": user["cn"] + "1"}
|
||||||
|
|
||||||
exitcode = 4
|
exitcode = 4
|
||||||
message=f"DB::Exception: {login['username']}: Authentication failed: password is incorrect or there is no user with such name"
|
message=f"DB::Exception: {login['username']}: Authentication failed: password is incorrect or there is no user with such name"
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -649,11 +705,14 @@ def invalid_username_and_valid_password(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Username_UTF8("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Username_UTF8("1.0")
|
||||||
)
|
)
|
||||||
def valid_utf8_username_and_ascii_password(self, server):
|
def valid_utf8_username_and_ascii_password(self, server):
|
||||||
"""Check that we can login using valid utf-8 username with ascii password."""
|
"""Check that we can login using valid utf-8 username with ascii password.
|
||||||
username = "utf8_username_Gãńdåłf_Thê_Gręât"
|
"""
|
||||||
user = {"cn": username, "userpassword": "utf8_username"}
|
username = "utf8_username_Gãńdåłf_Thê_Gręât"
|
||||||
|
user = {"cn": username, "userpassword": "utf8_username"}
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -661,17 +720,23 @@ def valid_utf8_username_and_ascii_password(self, server):
|
|||||||
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_UTF8("1.0")
|
RQ_SRS_009_LDAP_ExternalUserDirectory_Authentication_Password_UTF8("1.0")
|
||||||
)
|
)
|
||||||
def valid_ascii_username_and_utf8_password(self, server):
|
def valid_ascii_username_and_utf8_password(self, server):
|
||||||
"""Check that we can login using valid ascii username with utf-8 password."""
|
"""Check that we can login using valid ascii username with utf-8 password.
|
||||||
|
"""
|
||||||
username = "utf8_password"
|
username = "utf8_password"
|
||||||
user = {"cn": username, "userpassword": "utf8_password_Gãńdåłf_Thê_Gręât"}
|
user = {"cn": username, "userpassword": "utf8_password_Gãńdåłf_Thê_Gręât"}
|
||||||
|
|
||||||
add_user_to_ldap_and_login(user=user, server=server)
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
add_user_to_ldap_and_login(user=user, server=server)
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
def empty_username_and_empty_password(self, server=None):
|
def empty_username_and_empty_password(self, server=None):
|
||||||
"""Check that we can login using empty username and empty password as
|
"""Check that we can login using empty username and empty password as
|
||||||
it will use the default user and that has an empty password."""
|
it will use the default user and that has an empty password.
|
||||||
login_and_execute_query(username="", password="")
|
"""
|
||||||
|
with rbac_roles("ldap_role") as roles:
|
||||||
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
|
login_and_execute_query(username="", password="")
|
||||||
|
|
||||||
@TestScenario
|
@TestScenario
|
||||||
@Requirements(
|
@Requirements(
|
||||||
@ -698,16 +763,18 @@ def user_lookup_priority(self, server):
|
|||||||
"ldap": {"username": "ldap", "password": "userldap"}
|
"ldap": {"username": "ldap", "password": "userldap"}
|
||||||
}
|
}
|
||||||
|
|
||||||
with ldap_users(*[{"cn": user["username"], "userpassword": user["password"]} for user in users.values()]):
|
with rbac_roles("ldap_role") as roles:
|
||||||
with rbac_users({"cn": "local", "userpassword": "local"}):
|
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
||||||
with When("I try to login as 'default' user which is also defined in users.xml it should fail"):
|
with ldap_users(*[{"cn": user["username"], "userpassword": user["password"]} for user in users.values()]):
|
||||||
login_and_execute_query(**users["default"], exitcode=exitcode, message=message.format(username="default"))
|
with rbac_users({"cn": "local", "userpassword": "local"}):
|
||||||
|
with When("I try to login as 'default' user which is also defined in users.xml it should fail"):
|
||||||
|
login_and_execute_query(**users["default"], exitcode=exitcode, message=message.format(username="default"))
|
||||||
|
|
||||||
with When("I try to login as 'local' user which is also defined in local storage it should fail"):
|
with When("I try to login as 'local' user which is also defined in local storage it should fail"):
|
||||||
login_and_execute_query(**users["local"], exitcode=exitcode, message=message.format(username="local"))
|
login_and_execute_query(**users["local"], exitcode=exitcode, message=message.format(username="local"))
|
||||||
|
|
||||||
with When("I try to login as 'ldap' user defined only in LDAP it should work"):
|
with When("I try to login as 'ldap' user defined only in LDAP it should work"):
|
||||||
login_and_execute_query(**users["ldap"])
|
login_and_execute_query(**users["ldap"])
|
||||||
|
|
||||||
|
|
||||||
@TestOutline(Feature)
|
@TestOutline(Feature)
|
||||||
@ -728,7 +795,5 @@ def feature(self, servers=None, server=None, node="clickhouse1"):
|
|||||||
server = "openldap1"
|
server = "openldap1"
|
||||||
|
|
||||||
with ldap_servers(servers):
|
with ldap_servers(servers):
|
||||||
with rbac_roles("ldap_role") as roles:
|
for scenario in loads(current_module(), Scenario):
|
||||||
with ldap_external_user_directory(server=server, roles=roles, restart=True):
|
Scenario(test=scenario, flags=TE)(server=server)
|
||||||
for scenario in loads(current_module(), Scenario):
|
|
||||||
Scenario(test=scenario, flags=TE)(server=server)
|
|
||||||
|
@ -70,6 +70,15 @@ def rbac_roles(*roles):
|
|||||||
with By(f"dropping role {role}", flags=TE):
|
with By(f"dropping role {role}", flags=TE):
|
||||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||||
|
|
||||||
|
def verify_ldap_user_exists(server, username, password):
|
||||||
|
"""Check that LDAP user is defined on the LDAP server.
|
||||||
|
"""
|
||||||
|
with By("searching LDAP database"):
|
||||||
|
ldap_node = current().context.cluster.node(server)
|
||||||
|
r = ldap_node.command(
|
||||||
|
f"ldapwhoami -H ldap://localhost -D 'cn={username},ou=users,dc=company,dc=com' -w {password}")
|
||||||
|
assert r.exitcode == 0, error()
|
||||||
|
|
||||||
def create_ldap_external_user_directory_config_content(server=None, roles=None, **kwargs):
|
def create_ldap_external_user_directory_config_content(server=None, roles=None, **kwargs):
|
||||||
"""Create LDAP external user directory configuration file content.
|
"""Create LDAP external user directory configuration file content.
|
||||||
"""
|
"""
|
||||||
@ -197,8 +206,26 @@ def login(servers, directory_server, *users, config=None):
|
|||||||
|
|
||||||
@TestStep(When)
|
@TestStep(When)
|
||||||
@Name("I login as {username} and execute query")
|
@Name("I login as {username} and execute query")
|
||||||
def login_and_execute_query(self, username, password, exitcode=None, message=None, steps=True, timeout=60):
|
def login_and_execute_query(self, username, password, exitcode=None, message=None, steps=True, timeout=60, poll=False):
|
||||||
self.context.node.query("SELECT 1",
|
if poll:
|
||||||
settings=[("user", username), ("password", password)],
|
start_time = time.time()
|
||||||
exitcode=exitcode or 0,
|
attempt = 0
|
||||||
message=message, steps=steps, timeout=timeout)
|
|
||||||
|
with By("repeatedly trying to login until successful or timeout"):
|
||||||
|
while True:
|
||||||
|
with When(f"attempt #{attempt}"):
|
||||||
|
r = self.context.node.query("SELECT 1", settings=[("user", username), ("password", password)],
|
||||||
|
no_checks=True, steps=False, timeout=timeout)
|
||||||
|
|
||||||
|
if r.exitcode == (0 if exitcode is None else exitcode) and (message in r.output if message is not None else True):
|
||||||
|
break
|
||||||
|
|
||||||
|
if time.time() - start_time > timeout:
|
||||||
|
fail(f"timeout {timeout} trying to login")
|
||||||
|
|
||||||
|
attempt += 1
|
||||||
|
else:
|
||||||
|
self.context.node.query("SELECT 1",
|
||||||
|
settings=[("user", username), ("password", password)],
|
||||||
|
exitcode=(0 if exitcode is None else exitcode),
|
||||||
|
message=message, steps=steps, timeout=timeout)
|
||||||
|
Loading…
Reference in New Issue
Block a user