Implement split_grants() instead of split(',', $grants) to handle spliting grants with column-level privs.

This commit is contained in:
Daniel Nichter
2012-10-31 14:20:43 -06:00
parent 0453d7dd82
commit 0fd9239500
5 changed files with 81 additions and 7 deletions

View File

@@ -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; }

View File

@@ -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'\@'%'"`);
# #############################################################################

View 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'@'%';

View 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'@'%';

View File

@@ -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'@'%';