From 8ad0bc0827faeae5d2ef6eeffa6695a20b9de184 Mon Sep 17 00:00:00 2001 From: Marco Tusa Date: Mon, 18 Sep 2023 15:16:56 +0200 Subject: [PATCH 1/6] I had to correct few things in the script to have it working correctly: 1) OR instead and in the if line 2042 2) evaluate array create_user if it has some value 3) filter out the user creation in Mariadb inside the Grants --- bin/pt-show-grants | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) mode change 100755 => 100644 bin/pt-show-grants diff --git a/bin/pt-show-grants b/bin/pt-show-grants old mode 100755 new mode 100644 index 4a0655ce..8564e3b1 --- a/bin/pt-show-grants +++ b/bin/pt-show-grants @@ -2039,7 +2039,7 @@ sub main { # If MySQL 5.7.6+ then we need to use SHOW CREATE USER my @create_user; - if (( VersionCompare::cmp($version, '5.7.6') >= 0 ) && + if (( VersionCompare::cmp($version, '5.7.6') >= 0 ) || ( VersionCompare::cmp($version, '10.0.0') <= 0 )) { eval { @create_user = @{ $dbh->selectcol_arrayref("SHOW CREATE USER $user_host") }; @@ -2048,16 +2048,18 @@ sub main { PTDEBUG && _d($EVAL_ERROR); $exit_status = 1; } - PTDEBUG && _d('CreateUser:', Dumper(\@create_user)); - # make this replication safe converting the CREATE USER into - # CREATE USER IF NOT EXISTS and then doing an ALTER USER - my $create = $create_user[0]; - my $alter = $create; - $create =~ s{CREATE USER}{CREATE USER IF NOT EXISTS}; - $create =~ s{ IDENTIFIED .*}{}; - $alter =~ s{CREATE USER}{ALTER USER}; - @create_user = ( $create, $alter ); - PTDEBUG && _d('AdjustedCreateUser:', Dumper(\@create_user)); + if ($#create_user > 0){ + PTDEBUG && _d('CreateUser:', Dumper(\@create_user)); + # make this replication safe converting the CREATE USER into + # CREATE USER IF NOT EXISTS and then doing an ALTER USER + my $create = $create_user[0]; + my $alter = $create; + $create =~ s{CREATE USER}{CREATE USER IF NOT EXISTS}; + $create =~ s{ IDENTIFIED .*}{}; + $alter =~ s{CREATE USER}{ALTER USER}; + @create_user = ( $create, $alter ); + PTDEBUG && _d('AdjustedCreateUser:', Dumper(\@create_user)); + } } my @grants; eval { @@ -2067,6 +2069,13 @@ sub main { PTDEBUG && _d($EVAL_ERROR); $exit_status = 1; } + #IF is MariaDB we need to remove the password from the user + if ( VersionCompare::cmp($version, 'MariaDB') >= 0 ){ + for my $i (0 .. $#grants){ + $grants[$i] =~ s{IDENTIFIED.*}{}; + } + PTDEBUG && _d('Grants:', Dumper(\@grants)); + } PTDEBUG && _d('Grants:', Dumper(\@grants)); next unless @grants; From 275ceb0051f022bfbeec7a9e55b70ae333e71916 Mon Sep 17 00:00:00 2001 From: Marco Tusa Date: Thu, 21 Sep 2023 16:35:57 +0200 Subject: [PATCH 2/6] Fixing other small things and MariaDB specific, - Use of VIA - Use of USING - Incompatible syntax with MySQL - ADD IF NOT EXISTS - convert the script to us AS to maintain the hash as they are Add a parameter --convert-MariaDB as parameter (default false) --- bin/pt-show-grants | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/bin/pt-show-grants b/bin/pt-show-grants index 8564e3b1..70dea38c 100644 --- a/bin/pt-show-grants +++ b/bin/pt-show-grants @@ -2048,16 +2048,25 @@ sub main { PTDEBUG && _d($EVAL_ERROR); $exit_status = 1; } - if ($#create_user > 0){ + if ($#create_user >= 0){ PTDEBUG && _d('CreateUser:', Dumper(\@create_user)); # make this replication safe converting the CREATE USER into # CREATE USER IF NOT EXISTS and then doing an ALTER USER my $create = $create_user[0]; - my $alter = $create; + my $alter = $create_user[0]; $create =~ s{CREATE USER}{CREATE USER IF NOT EXISTS}; - $create =~ s{ IDENTIFIED .*}{}; + $create =~ s{ IDENTIFIED VIA }{ IDENTIFIED AS }; + $create =~ s{ BY }{ AS }; + $create =~ s{ AS.*PASSWORD }{ AS }; $alter =~ s{CREATE USER}{ALTER USER}; - @create_user = ( $create, $alter ); + # Alter user should not be pass in the latest MySQL version + #we need to cleanup other MariaDB diversions + if ( VersionCompare::cmp($version, 'MariaDB') >= 0 && + $o->get('convert-MariaDB')){ + $create =~ s/IDENTIFIED.*USING.*unix_socket.*/IDENTIFIED WITH auth_socket/; + $create =~ s/IDENTIFIED AS/IDENTIFIED WITH mysql_native_password AS/; + } + @create_user = ( $create); PTDEBUG && _d('AdjustedCreateUser:', Dumper(\@create_user)); } } @@ -2442,6 +2451,10 @@ type: array Only show grants for this comma-separated list of users. +=item --convert-MariaDB + +When set it convert some of the proprietary MariaDB syntax into valid MySQL form + =item --password short form: -p; type: string From 3be972e51802031fcc19baf94dca6a55629b06ec Mon Sep 17 00:00:00 2001 From: Marco Tusa Date: Thu, 21 Sep 2023 17:03:49 +0200 Subject: [PATCH 3/6] Fixed one issue (I introduced filtering the PASSWORD keyword) correct an IF condition removed a delete action on mysql.user. Always use DROP not delete --- bin/pt-show-grants | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bin/pt-show-grants b/bin/pt-show-grants index 70dea38c..5a2e798f 100644 --- a/bin/pt-show-grants +++ b/bin/pt-show-grants @@ -2057,12 +2057,11 @@ sub main { $create =~ s{CREATE USER}{CREATE USER IF NOT EXISTS}; $create =~ s{ IDENTIFIED VIA }{ IDENTIFIED AS }; $create =~ s{ BY }{ AS }; - $create =~ s{ AS.*PASSWORD }{ AS }; $alter =~ s{CREATE USER}{ALTER USER}; # Alter user should not be pass in the latest MySQL version #we need to cleanup other MariaDB diversions - if ( VersionCompare::cmp($version, 'MariaDB') >= 0 && - $o->get('convert-MariaDB')){ + if ( ($version =~ m/MariaDB/) && $o->get('convert-MariaDB')){ + $create =~ s{ AS.*PASSWORD }{ AS }; $create =~ s/IDENTIFIED.*USING.*unix_socket.*/IDENTIFIED WITH auth_socket/; $create =~ s/IDENTIFIED AS/IDENTIFIED WITH mysql_native_password AS/; } @@ -2079,7 +2078,7 @@ sub main { $exit_status = 1; } #IF is MariaDB we need to remove the password from the user - if ( VersionCompare::cmp($version, 'MariaDB') >= 0 ){ + if (($version =~ m/MariaDB/)){ for my $i (0 .. $#grants){ $grants[$i] =~ s{IDENTIFIED.*}{}; } @@ -2165,7 +2164,7 @@ sub main { if ( $o->get('drop') && !defined($u->{IsRole}) ) { print join("\n", "DROP USER $user_host;", - "DELETE FROM `mysql`.`user` WHERE `User`='$u->{User}' AND `Host`='$u->{Host}';", + #"DELETE FROM `mysql`.`user` WHERE `User`='$u->{User}' AND `Host`='$u->{Host}';", ), "\n"; } From b9be38d3a09ef76c8058f12dff9a79bfb0539f29 Mon Sep 17 00:00:00 2001 From: Marco Tusa Date: Fri, 22 Sep 2023 17:18:23 +0200 Subject: [PATCH 4/6] Significant refactor of the create in case of MySQL 8 and caching_sha2_password plugin. The problem is that when caching_sha2_password is used the character utilised in the string may be invalid for MySQL itself to process during creation time. Given that the password must be converted to HEX and then pushed as binary using the AS format --- bin/pt-show-grants | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bin/pt-show-grants b/bin/pt-show-grants index 5a2e798f..96574ce7 100644 --- a/bin/pt-show-grants +++ b/bin/pt-show-grants @@ -2050,6 +2050,14 @@ sub main { } if ($#create_user >= 0){ PTDEBUG && _d('CreateUser:', Dumper(\@create_user)); + #given caching_sha2_password issue we need to select the password in binary format and replace the one coming from the create + my $query = "SELECT authentication_string sha2 from mysql.user where user='$u->{User}' and host='$u->{Host}'"; + PTDEBUG && _d('get password:', Dumper($query)); + my ( $pw_sha2) = $dbh->selectrow_array($query); + my $pw_bin = $pw_sha2; + $pw_bin =~ s/(.)/sprintf '%02X', ord $1/seg; + $pw_bin = "0x".$pw_bin; + # make this replication safe converting the CREATE USER into # CREATE USER IF NOT EXISTS and then doing an ALTER USER my $create = $create_user[0]; @@ -2057,6 +2065,10 @@ sub main { $create =~ s{CREATE USER}{CREATE USER IF NOT EXISTS}; $create =~ s{ IDENTIFIED VIA }{ IDENTIFIED AS }; $create =~ s{ BY }{ AS }; + if ( $create =~ m/caching_sha2_password/ ) { + print "-- Converting $user_host caching_sha2_password to binary for correct export/import\n"; + $create =~ s/\sAS\s.*'\s|$/ AS $pw_bin /g; + } $alter =~ s{CREATE USER}{ALTER USER}; # Alter user should not be pass in the latest MySQL version #we need to cleanup other MariaDB diversions From b9675c56b6606eba5e0c7c28fb9acd6e461cf3d7 Mon Sep 17 00:00:00 2001 From: Marco Tusa Date: Fri, 22 Sep 2023 17:32:27 +0200 Subject: [PATCH 5/6] small bug in regex --- bin/pt-show-grants | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/pt-show-grants b/bin/pt-show-grants index 96574ce7..8ffd2b13 100644 --- a/bin/pt-show-grants +++ b/bin/pt-show-grants @@ -2067,7 +2067,7 @@ sub main { $create =~ s{ BY }{ AS }; if ( $create =~ m/caching_sha2_password/ ) { print "-- Converting $user_host caching_sha2_password to binary for correct export/import\n"; - $create =~ s/\sAS\s.*'\s|$/ AS $pw_bin /g; + $create =~ s/\sAS\s.*'\s/ AS $pw_bin /g; } $alter =~ s{CREATE USER}{ALTER USER}; # Alter user should not be pass in the latest MySQL version From 6f767a9d1d0aad9198df38fc3858670d6b3b1354 Mon Sep 17 00:00:00 2001 From: Marco Tusa Date: Fri, 22 Sep 2023 17:40:00 +0200 Subject: [PATCH 6/6] Adding replication safe condition for drop --- bin/pt-show-grants | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/pt-show-grants b/bin/pt-show-grants index 8ffd2b13..d7207ba6 100644 --- a/bin/pt-show-grants +++ b/bin/pt-show-grants @@ -2175,7 +2175,7 @@ sub main { if ( $o->get('drop') && !defined($u->{IsRole}) ) { print join("\n", - "DROP USER $user_host;", + "DROP USER IF EXISTS $user_host;", #"DELETE FROM `mysql`.`user` WHERE `User`='$u->{User}' AND `Host`='$u->{Host}';", ), "\n"; }