mysqloperator/controller/plugins.py (99 lines of code) (raw):
# Copyright (c) 2022, Oracle and/or its affiliates.
#
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
#
from typing import TYPE_CHECKING
import mysqlsh
from . import utils
if TYPE_CHECKING:
from mysqlsh.mysql import ClassicSession
SQL_INSTALL_MASKING_UDF = [
"INSTALL PLUGIN data_masking SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_blocklist RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_dictionary RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_dictionary_drop RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_dictionary_load RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_range RETURNS INTEGER SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_rnd_email RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_rnd_pan RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_rnd_ssn RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS gen_rnd_us_phone RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS mask_inner RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS mask_outer RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS mask_pan RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS mask_pan_relaxed RETURNS STRING SONAME 'data_masking.so'",
"CREATE FUNCTION IF NOT EXISTS mask_ssn RETURNS STRING SONAME 'data_masking.so'",
]
SQL_UNINSTALL_MASKING_UDF =[
"UNINSTALL PLUGIN data_masking",
"DROP FUNCTION gen_blocklist",
"DROP FUNCTION gen_dictionary",
"DROP FUNCTION gen_dictionary_drop",
"DROP FUNCTION gen_dictionary_load",
"DROP FUNCTION gen_range",
"DROP FUNCTION gen_rnd_email",
"DROP FUNCTION gen_rnd_pan",
"DROP FUNCTION gen_rnd_ssn",
"DROP FUNCTION gen_rnd_us_phone",
"DROP FUNCTION mask_inner",
"DROP FUNCTION mask_outer",
"DROP FUNCTION mask_pan",
"DROP FUNCTION mask_pan_relaxed",
"DROP FUNCTION mask_ssn",
]
SQL_INSTALL_KEYRING_UDF = [
"INSTALL PLUGIN keyring_udf SONAME 'keyring_udf.so'",
"CREATE FUNCTION IF NOT EXISTS keyring_key_generate RETURNS INTEGER SONAME 'keyring_udf.so'",
"CREATE FUNCTION IF NOT EXISTS keyring_key_fetch RETURNS STRING SONAME 'keyring_udf.so'",
"CREATE FUNCTION IF NOT EXISTS keyring_key_length_fetch RETURNS INTEGER SONAME 'keyring_udf.so'",
"CREATE FUNCTION IF NOT EXISTS keyring_key_type_fetch RETURNS STRING SONAME 'keyring_udf.so'",
"CREATE FUNCTION IF NOT EXISTS keyring_key_store RETURNS INTEGER SONAME 'keyring_udf.so'",
"CREATE FUNCTION IF NOT EXISTS keyring_key_remove RETURNS INTEGER SONAME 'keyring_udf.so'"
]
SQL_UNINSTALL_KEYRING_UDF = [
"DROP FUNCTION IF EXISTS keyring_key_generate",
"DROP FUNCTION IF EXISTS keyring_key_fetch",
"DROP FUNCTION IF EXISTS keyring_key_length_fetch",
"DROP FUNCTION IF EXISTS keyring_key_type_fetch",
"DROP FUNCTION IF EXISTS keyring_key_store",
"DROP FUNCTION IF EXISTS keyring_key_remove",
"UNINSTALL PLUGIN keyring_udf"
]
def run_plugin_sql(session: 'ClassicSession', stmts: list[str], logger) -> None:
"""
Install/Uninstall a plugin by running the defined SQL statements.
"""
for stmt in stmts:
try:
session.run_sql(stmt)
except mysqlsh.Error as e:
if e.code == mysqlsh.mysql.ErrorCode.ER_UDF_EXISTS:
logger.warn(f"UDF Already exists, ignored for \"{stmt}\"")
continue
logger.error(f"Failed to run plugin install statement \"{stmt}\": {e}")
raise
def install_enterprise_encryption(server_version: str, session: 'ClassicSession', logger) -> None:
min_version = utils.version_to_int("8.0.30")
installed_version = utils.version_to_int(server_version)
if installed_version < min_version:
logger.info(f"Deploying Enterprise Server {server_version}, older than 8.0.30, skipping encryption function installation")
return
res = session.run_sql("SELECT * FROM mysql.component WHERE component_urn = 'file://component_enterprise_encryption'")
row = res.fetch_one()
if row:
logger.warn("Enterprise Encryption Component already installed. Skipping.")
return
try:
session.run_sql("INSTALL COMPONENT 'file://component_enterprise_encryption'")
except mysqlsh.Error as e:
logger.error(f"Failed to install encryption component: {e}")
raise
def uninstall_enterprise_encryption(server_version: str, session: 'ClassicSession') -> None:
min_version = utils.version_to_int("8.0.30")
installed_version = utils.version_to_int(server_version)
if installed_version < min_version:
return
session.run_sql("UNINSTALL COMPONENT 'file://component_enterprise_encryption'")
def install_enterprise_plugins(server_version: str, session: 'ClassicSession', logger) -> None:
run_plugin_sql(session, SQL_INSTALL_MASKING_UDF, logger)
install_enterprise_encryption(server_version, session, logger)
def uninstall_enterprise_plugins(server_version: str, session: 'ClassicSession', logger) -> None:
run_plugin_sql(session, SQL_UNINSTALL_MASKING_UDF, logger)
uninstall_enterprise_plugins(server_version, session)
def install_keyring_udf(server_version: str, session: 'ClassicSession', logger) -> None:
run_plugin_sql(session, SQL_INSTALL_KEYRING_UDF, logger)
def uninstall_keyring_udf(server_version: str, session: 'ClassicSession', logger) -> None:
run_plugin_sql(session, SQL_UNINSTALL_KEYRING_UDF, logger)