WL#6667: Reimplement the password validation plugin API and plugin as a component

Affects: Server-8.0   —   Status: Complete   —   Priority: Medium

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.
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_service<SERVICE_TYPE(password_validation_service)>
service("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_TYPE(password_validation_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.