diff --git a/programs/server/Server.cpp b/programs/server/Server.cpp index 4c7bacdd89e..3a975325851 100644 --- a/programs/server/Server.cpp +++ b/programs/server/Server.cpp @@ -534,31 +534,12 @@ int Server::main(const std::vector & /*args*/) }, /* already_loaded = */ true); - /// Initialize users config reloader. - std::string users_config_path = config().getString("users_config", config_path); - /// If path to users' config isn't absolute, try guess its root (current) dir. - /// At first, try to find it in dir of main config, after will use current dir. - if (users_config_path.empty() || users_config_path[0] != '/') - { - std::string config_dir = Poco::Path(config_path).parent().toString(); - if (Poco::File(config_dir + users_config_path).exists()) - users_config_path = config_dir + users_config_path; - } - - if (users_config_path != config_path) - checkForUsersNotInMainConfig(config(), config_path, users_config_path, log); - auto & access_control = global_context->getAccessControlManager(); if (config().has("custom_settings_prefixes")) access_control.setCustomSettingsPrefixes(config().getString("custom_settings_prefixes")); - if (!users_config_path.empty()) - access_control.addUsersConfigStorage(users_config_path, include_from_path, path, [&] { return global_context->getZooKeeper(); }); - - /// Sets a local directory storing information about access control. - std::string access_control_local_path = config().getString("access_control_path", ""); - if (!access_control_local_path.empty()) - access_control.addDiskStorage(access_control_local_path); + /// Initialize access storages. + access_control.addStoragesFromMainConfig(config(), config_path, [&] { return global_context->getZooKeeper(); }); /// Reload config in SYSTEM RELOAD CONFIG query. global_context->setConfigReloadCallback([&]() diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index e82f6e05578..6158be1b603 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -21,10 +22,35 @@ namespace DB { namespace ErrorCodes { + extern const int UNKNOWN_ELEMENT_IN_CONFIG; extern const int UNKNOWN_SETTING; } +namespace +{ + void checkForUsersNotInMainConfig( + const Poco::Util::AbstractConfiguration & config, + const std::string & config_path, + const std::string & users_config_path, + Poco::Logger * log) + { + if (config.getBool("skip_check_for_incorrect_settings", false)) + return; + + if (config.has("users") || config.has("profiles") || config.has("quotas")) + { + /// We cannot throw exception here, because we have support for obsolete 'conf.d' directory + /// (that does not correspond to config.d or users.d) but substitute configuration to both of them. + + LOG_ERROR(log, "The , and elements should be located in users config file: {} not in main config {}." + " Also note that you should place configuration changes to the appropriate *.d directory like 'users.d'.", + users_config_path, config_path); + } + } +} + + class AccessControlManager::ContextAccessCache { public: @@ -199,6 +225,100 @@ void AccessControlManager::addMemoryStorage(const String & storage_name_) } +void AccessControlManager::addStoragesFromUserDirectoriesConfig( + const Poco::Util::AbstractConfiguration & config, + const String & key, + const String & config_dir, + const String & dbms_dir, + const String & include_from_path, + const zkutil::GetZooKeeper & get_zookeeper_function) +{ + Strings keys_in_user_directories; + config.keys(key, keys_in_user_directories); + + for (const String & key_in_user_directories : keys_in_user_directories) + { + String prefix = key + "." + key_in_user_directories; + + String type = key_in_user_directories; + if (size_t bracket_pos = type.find('['); bracket_pos != String::npos) + type.resize(bracket_pos); + if ((type == "users_xml") || (type == "users_config")) + type = UsersConfigAccessStorage::STORAGE_TYPE; + else if ((type == "local") || (type == "local_directory")) + type = DiskAccessStorage::STORAGE_TYPE; + + String name = config.getString(prefix + ".name", type); + + if (type == MemoryAccessStorage::STORAGE_TYPE) + { + addMemoryStorage(name); + } + else if (type == UsersConfigAccessStorage::STORAGE_TYPE) + { + String path = config.getString(prefix + ".path"); + if (std::filesystem::path{path}.is_relative() && std::filesystem::exists(config_dir + path)) + path = config_dir + path; + addUsersConfigStorage(name, path, include_from_path, dbms_dir, get_zookeeper_function); + } + else if (type == DiskAccessStorage::STORAGE_TYPE) + { + String path = config.getString(prefix + ".path"); + bool readonly = config.getBool(prefix + ".readonly", false); + addDiskStorage(name, path, readonly); + } + else + throw Exception("Unknown storage type '" + type + "' at " + prefix + " in config", ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG); + } +} + + +void AccessControlManager::addStoragesFromMainConfig( + const Poco::Util::AbstractConfiguration & config, + const String & config_path, + const zkutil::GetZooKeeper & get_zookeeper_function) +{ + String config_dir = std::filesystem::path{config_path}.remove_filename().string(); + String dbms_dir = config.getString("path", DBMS_DEFAULT_PATH); + String include_from_path = config.getString("include_from", "/etc/metrika.xml"); + + if (config.has("user_directories")) + { + if (config.has("users_config")) + LOG_WARNING(getLogger(), " is specified, the path from won't be used: " + config.getString("users_config")); + if (config.has("access_control_path")) + LOG_WARNING(getLogger(), " is specified, the path from won't be used: " + config.getString("access_control_path")); + + addStoragesFromUserDirectoriesConfig( + config, + "user_directories", + config_dir, + dbms_dir, + include_from_path, + get_zookeeper_function); + } + else + { + /// If path to users' config isn't absolute, try guess its root (current) dir. + /// At first, try to find it in dir of main config, after will use current dir. + String users_config_path = config.getString("users_config", ""); + if (users_config_path.empty()) + users_config_path = config_path; + else if (std::filesystem::path{users_config_path}.is_relative() && std::filesystem::exists(config_dir + users_config_path)) + users_config_path = config_dir + users_config_path; + + if (users_config_path != config_path) + checkForUsersNotInMainConfig(config, config_path, users_config_path, getLogger()); + + addUsersConfigStorage(users_config_path, include_from_path, dbms_dir, get_zookeeper_function); + + String disk_storage_dir = config.getString("access_control_path", ""); + if (!disk_storage_dir.empty()) + addDiskStorage(disk_storage_dir); + } +} + + void AccessControlManager::setExternalAuthenticatorsConfig(const Poco::Util::AbstractConfiguration & config) { external_authenticators->setConfig(config, getLogger()); diff --git a/src/Access/AccessControlManager.h b/src/Access/AccessControlManager.h index 1de758c944e..ad9fb48d263 100644 --- a/src/Access/AccessControlManager.h +++ b/src/Access/AccessControlManager.h @@ -82,6 +82,19 @@ public: void addMemoryStorage(); void addMemoryStorage(const String & storage_name_); + /// Adds storages from config. + void addStoragesFromUserDirectoriesConfig(const Poco::Util::AbstractConfiguration & config, + const String & key, + const String & config_dir, + const String & dbms_dir, + const String & include_from_path, + const zkutil::GetZooKeeper & get_zookeeper_function); + + /// Adds storages from the main config. + void addStoragesFromMainConfig(const Poco::Util::AbstractConfiguration & config, + const String & config_path, + const zkutil::GetZooKeeper & get_zookeeper_function); + /// Sets the default profile's name. /// The default profile's settings are always applied before any other profile's. void setDefaultProfileName(const String & default_profile_name);