WL#6667: Reimplement the password validation plugin API and plugin as a component
Affects: Server-8.0
—
Status: Complete
This worklog implements the password validation plugin API and plugin as a component in the new services infrastructure.
Functional Requirements: ----------------------- 1. Create a password validation component containing the existing password validation plugin. 2. Expose the validate_password() and get_password_strength() as a service API and register it as a default implementation. 3. Convert the SQL functions so that they call the default implementation of the service API from #2 4. Make the other plugins call the same service API via the bridge from WL#4989. 5. The packaging script should be installing the component by default for new installs Non-Functional Requirements: --------------------------- The way it currently works with deprecations and removals is the following: a. We add a deprecation warning to using the old way and we switch the server to use the new way by default for new installations. b. We expect that people will upgrade their existing installations too to avoid the warning. c. In the next major release we remove the old way and hope that people did #b.
WL#4102: Service registry and component infrastructure
WL#9424: Configuration system variables as a service for mysql_server component
WL#9503: mysql string functionalities as a service for mysql_server component
WL#10806: Component status variables as a service for mysql_server component (sub-worklog for wl6667)
WL#9424: Configuration system variables as a service for mysql_server component
WL#9503: mysql string functionalities as a service for mysql_server component
WL#10806: Component status variables as a service for mysql_server component (sub-worklog for wl6667)
Benefits of the migration: -------------------------- Currently the validate_password service needs to define both a plugin API and a plugin service API so that other plugins can talk to it. Also the server component can only use one plugin as it loads it by name and the names of plugins are unique. A single component service has the potential to fix all of the above problems and provide natural extensibility vs. the compiled in one that we currently have. Prerequisites: -------------- To properly validate passwords the component will need to be able to deal with strings in a particular character set: convert them to lower case, iterate over the characters in them, convert them to const char * pointers in a specific character set etc. Currently this code resides into the server component (strings/ directory and the String class). So we will make the server component provide a number of services that cover the operations needed. The details of that service and its implementation are to be found in WL#9503 The password validation component will need a way to persist the password policy variables, like e.g. required number of upper case characters, required number of numeric characters, the location of the dictionary file, the type of checks to enforce etc. These are currently implemented as component system variables. The system variables code is located inside the server component. So it will provide a new service allowing components to register and unregister new component variables similarly to what the plugin API provides to plugins. The details of that service and its implementation are to be found in WL#9424. Parts being removed: -------------------- 1. The password validation plugin API: replaced by the new component service 2. The password validation plugin service: replaced by the new component service 3. The password validation plugin. Parts being added: ------------------ 1. A new component service that matches the (extended version of) password_validation plugin API 2. A new, clean, component that implements the password_validation service and consumes the newly added string service(s) and component system variables service(s). it will also have (most of) the password validation plugin code that implements the actual checking logic. Parts being altered: -------------------- 1. The validate_password_strength() and validate_password()will use the new component service instead 2. The SQL statements that add new passwords will call the new component service instead. These are: 2.1. SET PASSWORD FOR 'base_user'@'localhost'= PASSWORD('password'); 2.2. CREATE USER 'base_user'@'localhost' IDENTIFIED BY 'password'; 2.3. ALTER USER ... IDENTIFIED BY ... 2.4. UPDATE mysql.user SET PASSWORD= PASSWORD('password') WHERE user='base_user'; 2.5. GRANT USAGE ON *.* TO 'base_user'@'localhost' IDENTIFIED BY 'password'; 2.6. SET PASSWORD FOR 'base_user'@'localhost'= 'password'; 3. The password_validation plugin variables will be converted into component variables for the new password_validation component as follows: 3.1 At password_validation component initilization time the configuration_system_variable::register_varible() api will be called. 3.2 At variable update time check() and update() functions of the register_variable() will be called. 3.3 At password_validation component deinitialization time the configuration_system_variable::unregister_varible() api will be called 4. Make the other plugins call the same service API via the bridge from WL#4989 Implementation sequence: ------------------------ We will replace the plugin API and the plugin service API with a single component service that can have multiple implementations and a dynamically specifiable default. The details of that are in WL#9324. Once we do that the relevant hooks inside the server will be changed to call the component service instead of the plugin based one. Thanks to the component service bridge in WL#4989 the plugins will be able to use the component service, but they'll need to start fetching a reference to the service from the component registry in their init()/deinit() methods and then calling the received reference instead.
A new folder(password_validation) is created in components. components/password_validation/validate_password.cc ======================================== /* This component provides an implementation for password_validation_service only. */ BEGIN_SERVICE_IMPLEMENTATION(password_validation, password_validation_service) password_validation_service_imp::validate_password, password_validation_service_imp::get_password_strength, END_SERVICE_IMPLEMENTATION() BEGIN_COMPONENT_PROVIDES(password_validation) PROVIDES_SERVICE(password_validation, password_validation_service) END_COMPONENT_PROVIDES() /* A block for specifying dependencies of this Component. Note that for each dependency we need to have a placeholder, a extern to placeholder in header file of the Component, and an entry on requires list below. */ REQUIRES_SERVICE_PLACEHOLDER(string_service); REQUIRES_SERVICE_PLACEHOLDER(plugin_registry_service); /* A list of dependencies. */ BEGIN_COMPONENT_REQUIRES(password_validation) REQUIRES_SERVICE(string_service) REQUIRES_SERVICE(plugin_registry_service) END_COMPONENT_REQUIRES() /* A list of metadata to describe the Component. */ BEGIN_COMPONENT_METADATA(password_validation) METADATA("mysql.author", "Oracle Corporation") METADATA("mysql.license", "GPL") METADATA("password_validation", "1") END_COMPONENT_METADATA() /* Declaration of the Component, this is the case when we don't need initialization/de-initialization methods */ DECLARE_COMPONENT(password_validation, "mysql:password_validation") validate_password_init, validate_password_deinit END_DECLARE_COMPONENT() /* Defines list of Components contained in this library. */ DECLARE_LIBRARY_COMPONENTS &COMPONENT_REF(password_validation) END_DECLARE_LIBRARY_COMPONENTS sql/auth/password_policy_ser vice.cc ========================== changes in my_validate_password_policy() function with the below in the place of plugin serice code. /* Retrieve a default Service Implementation for the password_validation_service Service. */ my_serviceservice("password_validation_service", mysql_service_registry); if (service) { return true; } service->validate_password(&password_str); similarly for my_calculate_password_strength() function /* Retrieve a default Service Implementation for the password_validation_service Service. */ my_service service("password_validation_service", mysql_service_registry); if (service) { return true; } service->get_password_strength(&password_str); And for other plugins like sql_authentication and item_strfunc, use the same default service API via the bridge from WL#9324.
Copyright (c) 2000, 2024, Oracle Corporation and/or its affiliates. All rights reserved.