mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-10 05:00:45 +00:00
Implement split_grants() instead of split(',', $grants) to handle spliting grants with column-level privs.
This commit is contained in:
@@ -1766,11 +1766,14 @@ sub main {
|
||||
PTDEBUG && _d('Grants:', Dumper(\@grants));
|
||||
next unless @grants;
|
||||
|
||||
if ( $o->get('separate') ) { # List each grant separately.
|
||||
if ( $o->get('separate') ) {
|
||||
# List each grant separately.
|
||||
@grants = map {
|
||||
my ( $grants, $on_what ) = $_ =~ m/GRANT (.*?) ON (.*)$/;
|
||||
map { "GRANT $_ ON $on_what" } split(', ', $grants);
|
||||
map { "GRANT $_ ON $on_what" } split_grants($grants);
|
||||
} @grants;
|
||||
PTDEBUG && _d('Grants separated:', Dumper(\@grants));
|
||||
|
||||
my $count;
|
||||
# If the row with IDENTIFIED BY has multiple grants, this will
|
||||
# create many such rows; strip it from all but the first.
|
||||
@@ -1782,12 +1785,15 @@ sub main {
|
||||
}
|
||||
$_;
|
||||
} @grants;
|
||||
PTDEBUG && _d('Grants separated:', Dumper(\@grants));
|
||||
}
|
||||
else { # Sort the actual grants lexically within each row for consistency.
|
||||
else {
|
||||
# Sort the actual grants lexically within each row for consistency.
|
||||
@grants = map {
|
||||
$_ =~ s/GRANT (.*?) ON (`|\*)/"GRANT " . join(', ', sort(split(', ', $1))) . " ON $2"/e;
|
||||
$_ =~ s/GRANT (.*?) ON (`|\*)/"GRANT " . join(', ', sort(split_grants($1))) . " ON $2"/e;
|
||||
$_;
|
||||
} @grants;
|
||||
PTDEBUG && _d('Grants grouped:', Dumper(\@grants));
|
||||
}
|
||||
|
||||
# Sort the grant rows for consistency too, but the one with the password
|
||||
@@ -1795,6 +1801,7 @@ sub main {
|
||||
@grants = sort {
|
||||
$b =~ m/IDENTIFIED BY/ <=> $a =~ m/IDENTIFIED BY/ || $a cmp $b
|
||||
} @grants;
|
||||
PTDEBUG && _d('Grants sorted:', Dumper(\@grants));
|
||||
|
||||
# Print REVOKE statements.
|
||||
if ( $o->get('revoke') ) {
|
||||
@@ -1809,7 +1816,7 @@ sub main {
|
||||
my @result;
|
||||
if ( $o->get('separate') ) {
|
||||
@result = map { "REVOKE $_ ON $on_what FROM $user" }
|
||||
split(', ', $grants);
|
||||
split_grants($grants);
|
||||
}
|
||||
else {
|
||||
@result = "REVOKE $grants ON $on_what FROM $user";
|
||||
@@ -1874,6 +1881,35 @@ sub parse_user {
|
||||
return ( $user, $host );
|
||||
}
|
||||
|
||||
sub split_grants {
|
||||
my ($grants) = @_;
|
||||
return unless $grants;
|
||||
my @grants;
|
||||
if ( $grants =~ m/(?:INSERT|SELECT|UPDATE) \(/ ) {
|
||||
PTDEBUG && _d('Splitting grants on keywords:', $grants);
|
||||
@grants = map {
|
||||
my $grant = $_;
|
||||
$grant =~ s/^\s+//;
|
||||
$grant =~ s/,\s*$//;
|
||||
$grant;
|
||||
} $grants =~ m/
|
||||
\G # Start matching after the previous match
|
||||
\s? # Space after previous match's separating comma
|
||||
(?: # Either match...
|
||||
(?: (?:INSERT|SELECT|UPDATE)\s\(.+?\) ) # a column grant
|
||||
| (?: [A-Z\s]+ ) # or a table grant
|
||||
)
|
||||
,? # Separted from the next grant, if any, by a comma
|
||||
/xg;
|
||||
}
|
||||
else {
|
||||
PTDEBUG && _d('Splitting grants on comma:', $grants);
|
||||
@grants = split(', ', $grants);
|
||||
}
|
||||
PTDEBUG && _d('Grants split:', Dumper(\@grants));
|
||||
return @grants;
|
||||
}
|
||||
|
||||
sub _d {
|
||||
my ($package, undef, $line) = caller 0;
|
||||
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
|
||||
|
@@ -101,13 +101,33 @@ diag(`/tmp/12345/use -u root -e "GRANT SELECT(city_id), INSERT(city) ON sakila.c
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_show_grants::main('-F', $cnf, qw(--only sally)) },
|
||||
sub { pt_show_grants::main('-F', $cnf, qw(--only sally --no-header)) },
|
||||
"t/pt-show-grants/samples/column-grants.txt",
|
||||
stderr => 1,
|
||||
),
|
||||
"Column-level grants (bug 866075)"
|
||||
);
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_show_grants::main('-F', $cnf, qw(--only sally --no-header),
|
||||
qw(--separate)) },
|
||||
"t/pt-show-grants/samples/column-grants-separate.txt",
|
||||
stderr => 1,
|
||||
),
|
||||
"Column-level grants --separate (bug 866075)"
|
||||
);
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_show_grants::main('-F', $cnf, qw(--only sally --no-header),
|
||||
qw(--separate --revoke)) },
|
||||
"t/pt-show-grants/samples/column-grants-separate-revoke.txt",
|
||||
stderr => 1,
|
||||
),
|
||||
"Column-level grants --separate --revoke (bug 866075)"
|
||||
);
|
||||
|
||||
diag(`/tmp/12345/use -u root -e "DROP USER 'sally'\@'%'"`);
|
||||
|
||||
# #############################################################################
|
||||
|
10
t/pt-show-grants/samples/column-grants-separate-revoke.txt
Normal file
10
t/pt-show-grants/samples/column-grants-separate-revoke.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
-- Revoke statements for 'sally'@'%'
|
||||
REVOKE INSERT (city) ON `sakila`.`city` FROM 'sally'@'%';
|
||||
REVOKE SELECT (SANumber, DateCreated, PaymentStat, PckPrice) ON `test`.`t` FROM 'sally'@'%';
|
||||
REVOKE SELECT (city_id) ON `sakila`.`city` FROM 'sally'@'%';
|
||||
REVOKE USAGE ON *.* FROM 'sally'@'%';
|
||||
-- Grants for 'sally'@'%'
|
||||
GRANT INSERT (city) ON `sakila`.`city` TO 'sally'@'%';
|
||||
GRANT SELECT (SANumber, DateCreated, PaymentStat, PckPrice) ON `test`.`t` TO 'sally'@'%';
|
||||
GRANT SELECT (city_id) ON `sakila`.`city` TO 'sally'@'%';
|
||||
GRANT USAGE ON *.* TO 'sally'@'%';
|
5
t/pt-show-grants/samples/column-grants-separate.txt
Normal file
5
t/pt-show-grants/samples/column-grants-separate.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
-- Grants for 'sally'@'%'
|
||||
GRANT INSERT (city) ON `sakila`.`city` TO 'sally'@'%';
|
||||
GRANT SELECT (SANumber, DateCreated, PaymentStat, PckPrice) ON `test`.`t` TO 'sally'@'%';
|
||||
GRANT SELECT (city_id) ON `sakila`.`city` TO 'sally'@'%';
|
||||
GRANT USAGE ON *.* TO 'sally'@'%';
|
@@ -1 +1,4 @@
|
||||
--
|
||||
-- Grants for 'sally'@'%'
|
||||
GRANT INSERT (city), SELECT (city_id) ON `sakila`.`city` TO 'sally'@'%';
|
||||
GRANT SELECT (SANumber, DateCreated, PaymentStat, PckPrice) ON `test`.`t` TO 'sally'@'%';
|
||||
GRANT USAGE ON *.* TO 'sally'@'%';
|
||||
|
Reference in New Issue
Block a user