From 3e595a6fc05bfde26d4de4bacd7eb55393ca1452 Mon Sep 17 00:00:00 2001 From: BrOt Date: Fri, 21 Oct 2022 10:19:26 +0200 Subject: [PATCH 1/3] fix for issue #1502 --- lib/puppet/provider/mysql_grant/mysql.rb | 41 ++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/puppet/provider/mysql_grant/mysql.rb b/lib/puppet/provider/mysql_grant/mysql.rb index 7f32e1d1f..0763f4b66 100644 --- a/lib/puppet/provider/mysql_grant/mysql.rb +++ b/lib/puppet/provider/mysql_grant/mysql.rb @@ -22,6 +22,16 @@ def self.instances next if %r{There is no such grant defined for user}.match?(e.inspect) raise Puppet::Error, _('#mysql had an error -> %{inspect}') % { inspect: e.inspect } end + + # initialize variables to be visible outside of the grants.each_line scope + stripped_privileges = [] + table = "" + options = [] + host = "" + + # we need to iterate over all grants rows, because on mysql 8+ there are static and dynamic privileges + # each on separate row of show grants + # Once we have the list of grants generate entries for each. grants.each_line do |grant| # Match the munges we do in the type. @@ -34,7 +44,7 @@ def self.instances # split on ',' if it is not a non-'('-containing string followed by a # closing parenthesis ')'-char - e.g. only split comma separated elements not in # parentheses - stripped_privileges = privileges.strip.split(%r{\s*,\s*(?![^(]*\))}).map do |priv| + local_stripped_privileges = privileges.strip.split(%r{\s*,\s*(?![^(]*\))}).map do |priv| # split and sort the column_privileges in the parentheses and rejoin if priv.include?('(') type, col = priv.strip.split(%r{\s+|\b}, 2) @@ -45,12 +55,14 @@ def self.instances (priv == 'ALL PRIVILEGES') ? 'ALL' : priv.strip end end + stripped_privileges.concat local_stripped_privileges # Same here, but to remove OPTION leaving just GRANT. - options = if %r{WITH\sGRANT\sOPTION}.match?(rest) + local_options = if %r{WITH\sGRANT\sOPTION}.match?(rest) ['GRANT'] else ['NONE'] end + options.concat local_options # fix double backslash that MySQL prints, so resources match table.gsub!('\\\\', '\\') # We need to return an array of instances so capture these @@ -62,10 +74,23 @@ def self.instances end sorted_privileges = stripped_privileges.uniq.sort - if newer_than('mysql' => '8.0.0') && sorted_privileges == ['ALTER', 'ALTER ROUTINE', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', - 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'EVENT', 'EXECUTE', 'FILE', 'INDEX', 'INSERT', 'LOCK TABLES', 'PROCESS', 'REFERENCES', - 'RELOAD', 'REPLICATION CLIENT', 'REPLICATION SLAVE', 'SELECT', 'SHOW DATABASES', 'SHOW VIEW', 'SHUTDOWN', 'SUPER', 'TRIGGER', - 'UPDATE'] + if newer_than('mysql' => '8.0.0') && ( + sorted_privileges == ['ALTER', 'ALTER ROUTINE', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', + 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'EVENT', 'EXECUTE', 'FILE', 'INDEX', 'INSERT', 'LOCK TABLES', 'PROCESS', 'REFERENCES', + 'RELOAD', 'REPLICATION CLIENT', 'REPLICATION SLAVE', 'SELECT', 'SHOW DATABASES', 'SHOW VIEW', 'SHUTDOWN', 'SUPER', 'TRIGGER', + 'UPDATE'] || + sorted_privileges == ['ALTER', 'ALTER ROUTINE', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', + 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', + 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'ENCRYPTION_KEY_ADMIN', + 'EVENT', 'EXECUTE', 'FILE', 'FIREWALL_EXEMPT', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', + 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INDEX', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'INSERT', + 'LOCK TABLES', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'PROCESS', 'REFERENCES', 'RELOAD', 'REPLICATION CLIENT', + 'REPLICATION SLAVE', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', + 'SELECT', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW DATABASES', + 'SHOW VIEW', 'SHOW_ROUTINE', 'SHUTDOWN', 'SUPER', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'TRIGGER', 'UPDATE', + 'XA_RECOVER_ADMIN'] || + sorted_privileges == ['ALL', 'USAGE'] + ) sorted_privileges = ['ALL'] # The following two elsif blocks of code are a workaround for issue #1474. @@ -83,6 +108,10 @@ def self.instances 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN'] sorted_privileges = ['ALL'] + + # the following elsif is there to mitigate problems with redundant ALL and USAGE, issue #1502 + elsif sorted_privileges == ['ALL', 'USAGE'] + sorted_privileges = ['ALL'] end instance_configs[name] = { From d0c03efd13c8a812b32c41c348bcf8d9083da837 Mon Sep 17 00:00:00 2001 From: BrOt Date: Mon, 24 Oct 2022 14:23:40 +0200 Subject: [PATCH 2/3] (ISSUE-1502) MySQL 8.0 privileges no longer changed each run * Even after issue #1474 we encounter changes of privileges each puppet run. This behavior is fixed by addition of another expanded privilege list * fix trailing whitespaces --- lib/puppet/provider/mysql_grant/mysql.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/puppet/provider/mysql_grant/mysql.rb b/lib/puppet/provider/mysql_grant/mysql.rb index 0763f4b66..45672c87d 100644 --- a/lib/puppet/provider/mysql_grant/mysql.rb +++ b/lib/puppet/provider/mysql_grant/mysql.rb @@ -22,16 +22,15 @@ def self.instances next if %r{There is no such grant defined for user}.match?(e.inspect) raise Puppet::Error, _('#mysql had an error -> %{inspect}') % { inspect: e.inspect } end - + # initialize variables to be visible outside of the grants.each_line scope stripped_privileges = [] table = "" options = [] host = "" - + # we need to iterate over all grants rows, because on mysql 8+ there are static and dynamic privileges # each on separate row of show grants - # Once we have the list of grants generate entries for each. grants.each_line do |grant| # Match the munges we do in the type. From dc1f4b887373522059c1693998a30a2521f51a90 Mon Sep 17 00:00:00 2001 From: BrOt Date: Mon, 24 Oct 2022 14:56:44 +0200 Subject: [PATCH 3/3] (ISSUE-1502) MySQL 8.0 privileges no longer changed each run * Even after issue #1474 we encounter changes of privileges each puppet run. This behavior is fixed by addition of another expanded privilege list * fix validation errors --- lib/puppet/provider/mysql_grant/mysql.rb | 44 +++++++++++------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/lib/puppet/provider/mysql_grant/mysql.rb b/lib/puppet/provider/mysql_grant/mysql.rb index 45672c87d..2868246fe 100644 --- a/lib/puppet/provider/mysql_grant/mysql.rb +++ b/lib/puppet/provider/mysql_grant/mysql.rb @@ -25,9 +25,9 @@ def self.instances # initialize variables to be visible outside of the grants.each_line scope stripped_privileges = [] - table = "" + table = '' options = [] - host = "" + host = '' # we need to iterate over all grants rows, because on mysql 8+ there are static and dynamic privileges # each on separate row of show grants @@ -57,10 +57,10 @@ def self.instances stripped_privileges.concat local_stripped_privileges # Same here, but to remove OPTION leaving just GRANT. local_options = if %r{WITH\sGRANT\sOPTION}.match?(rest) - ['GRANT'] - else - ['NONE'] - end + ['GRANT'] + else + ['NONE'] + end options.concat local_options # fix double backslash that MySQL prints, so resources match table.gsub!('\\\\', '\\') @@ -73,23 +73,21 @@ def self.instances end sorted_privileges = stripped_privileges.uniq.sort - if newer_than('mysql' => '8.0.0') && ( - sorted_privileges == ['ALTER', 'ALTER ROUTINE', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', - 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'EVENT', 'EXECUTE', 'FILE', 'INDEX', 'INSERT', 'LOCK TABLES', 'PROCESS', 'REFERENCES', - 'RELOAD', 'REPLICATION CLIENT', 'REPLICATION SLAVE', 'SELECT', 'SHOW DATABASES', 'SHOW VIEW', 'SHUTDOWN', 'SUPER', 'TRIGGER', - 'UPDATE'] || - sorted_privileges == ['ALTER', 'ALTER ROUTINE', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', - 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', - 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'ENCRYPTION_KEY_ADMIN', - 'EVENT', 'EXECUTE', 'FILE', 'FIREWALL_EXEMPT', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', - 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INDEX', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'INSERT', - 'LOCK TABLES', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'PROCESS', 'REFERENCES', 'RELOAD', 'REPLICATION CLIENT', - 'REPLICATION SLAVE', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', - 'SELECT', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW DATABASES', - 'SHOW VIEW', 'SHOW_ROUTINE', 'SHUTDOWN', 'SUPER', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'TRIGGER', 'UPDATE', - 'XA_RECOVER_ADMIN'] || - sorted_privileges == ['ALL', 'USAGE'] - ) + if newer_than('mysql' => '8.0.0') && + [['ALTER', 'ALTER ROUTINE', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', + 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'EVENT', 'EXECUTE', 'FILE', 'INDEX', 'INSERT', 'LOCK TABLES', 'PROCESS', 'REFERENCES', + 'RELOAD', 'REPLICATION CLIENT', 'REPLICATION SLAVE', 'SELECT', 'SHOW DATABASES', 'SHOW VIEW', 'SHUTDOWN', 'SUPER', 'TRIGGER', + 'UPDATE'], ['ALTER', 'ALTER ROUTINE', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', + 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', + 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'ENCRYPTION_KEY_ADMIN', + 'EVENT', 'EXECUTE', 'FILE', 'FIREWALL_EXEMPT', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', + 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INDEX', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'INSERT', + 'LOCK TABLES', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'PROCESS', 'REFERENCES', 'RELOAD', 'REPLICATION CLIENT', + 'REPLICATION SLAVE', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', + 'SELECT', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW DATABASES', + 'SHOW VIEW', 'SHOW_ROUTINE', 'SHUTDOWN', 'SUPER', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'TRIGGER', 'UPDATE', + 'XA_RECOVER_ADMIN'], ['ALL', 'USAGE']].include?(sorted_privileges) + sorted_privileges = ['ALL'] # The following two elsif blocks of code are a workaround for issue #1474.