Skip to content

Commit

Permalink
PT-2247 - pt-show-grants does not CREATE USER
Browse files Browse the repository at this point in the history
- Removed option print_identified_with_as_hex, because it was already
  implemented in the PT-2190 fix
- Simplified patch
- Kept CREATE USER/ALTER USER sequence and extra DELETE from mysql.user
  table
- Added test case
  • Loading branch information
svetasmirnova committed May 16, 2024
1 parent bc23d08 commit f3f4943
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 50 deletions.
79 changes: 29 additions & 50 deletions bin/pt-show-grants
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2062,51 +2062,34 @@ 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 ) ||
( VersionCompare::cmp($version, '10.0.0') <= 0 )) {
if ( ( VersionCompare::cmp($version, '5.7.6') >= 0 ) ) {
eval {
if (!($version =~ m/MariaDB/) && ( VersionCompare::cmp($version, '8.0.17') >= 0 ) && ($o->get('print_identified_with_as_hex'))){
$dbh->do("SET print_identified_with_as_hex=1") or die();
print "-- Setting print_identified_with_as_hex as ACTIVE at session level for correct export/import\n";
}
@create_user = @{ $dbh->selectcol_arrayref("SHOW CREATE USER $user_host") };
};
if ( $EVAL_ERROR ) {
PTDEBUG && _d($EVAL_ERROR);
$exit_status = 1;
}
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 as sha2, convert(authentication_string using Binary) as bin from mysql.user where user='$u->{User}' and host='$u->{Host}'";
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
if ( $#create_user >= 0 ) {
PTDEBUG && _d('CREATE USER:', 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_user[0];
$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/ ) && !($o->get('print_identified_with_as_hex'))) {
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
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/;
}
@create_user = ( $create);
PTDEBUG && _d('AdjustedCreateUser:', Dumper(\@create_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};

# We need to cleanup MariaDB diversions
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/;
}

@create_user = ( $create, $alter );
PTDEBUG && _d('Adjusted CREATE USER:', Dumper(\@create_user));
}
}
my @grants;
Expand All @@ -2117,13 +2100,15 @@ sub main {
PTDEBUG && _d($EVAL_ERROR);
$exit_status = 1;
}
#IF is MariaDB we need to remove the password from the user
if (($version =~ m/MariaDB/)){
for my $i (0 .. $#grants){

# We need to remove password form the user grants when dump MariaDB
if ( $version =~ m/MariaDB/ ){
PTDEBUG && _d('Original Grants - MariaDB:', Dumper(\@grants));
for my $i (0 .. $#grants){
$grants[$i] =~ s{IDENTIFIED.*}{};
}
PTDEBUG && _d('Grants:', Dumper(\@grants));
}
}

PTDEBUG && _d('Grants:', Dumper(\@grants));
next unless @grants;

Expand Down Expand Up @@ -2204,7 +2189,7 @@ sub main {
if ( $o->get('drop') && !defined($u->{IsRole}) ) {
print join("\n",
"DROP USER IF EXISTS $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";
}

Expand Down Expand Up @@ -2492,13 +2477,7 @@ 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 --print_identified_with_as_hex
Enabling print_identified_with_as_hex causes SHOW CREATE USER to display such hash values as hexadecimal strings rather than as regular string literals.
Hash values that do not contain unprintable characters still display as regular string literals, even with this variable enabled.
Convert proprietary MariaDB syntax into valid MySQL form
=item --password
Expand Down
77 changes: 77 additions & 0 deletions t/pt-show-grants/pt-2247.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env perl

BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};

use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;

use PerconaTest;
use Sandbox;
use SqlModes;
use VersionParser;
require "$trunk/bin/pt-show-grants";

my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('master');

if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}

if ( VersionParser->new($dbh)->flavor !~ m/maria/i ) {
plan skip_all => "This test requires MariaDB";
}

$sb->wipe_clean($dbh);

my $output;
my $cnf = '/tmp/12345/my.sandbox.cnf';

diag(`/tmp/12345/use -u root -e "CREATE USER 'sally'\@'%' IDENTIFIED BY 'A005?>6LZe1'"`);

ok(
`/tmp/12345/use -s -u sally -p'A005?>6LZe1' -e "SELECT 1" 2>/dev/null`,
'User sally can log in before tests'
);

$output = output(
sub { pt_show_grants::main('-F', $cnf, qw(--only sally)); }
);

like(
$output,
qr/CREATE USER IF NOT EXISTS `sally`@`%`;/,
'CREATE USER printed'
) or diag($output);

like(
$output,
qr/ALTER USER `sally`@`%` IDENTIFIED BY PASSWORD '\*A5C09B5E9542E3C716E3E0A711336D9ABB48D89F';/,
'ALTER USER printed'
) or diag($output);

diag(`/tmp/12345/use -u root -e "DROP USER 'sally'\@'%'"`);
open(my $pipe, '|-', '/tmp/12345/use -u root');
print $pipe $output;
close($pipe);

ok(
`/tmp/12345/use -s -u sally -p'A005?>6LZe1' -e "SELECT 1" 2>/dev/null`,
'User sally can log in'
) or diag($output);

diag(`/tmp/12345/use -u root -e "DROP USER 'sally'\@'%'"`);

# #############################################################################
# Done.
# #############################################################################
$sb->wipe_clean($dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;

0 comments on commit f3f4943

Please sign in to comment.