Skip to content

(MODULES-552) Add capability to specify column_privileges #570

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,16 @@ mysql_grant { 'root@localhost/*.*':
}
```

It is possible to specify privileges down to the column level:
```puppet
mysql_grant { 'root@localhost/mysql.user':
ensure => 'present',
privileges => ['SELECT (Host, User)'],
table => 'mysql.user',
user => 'root@localhost',
}
```

##Limitations

This module has been tested on:
Expand Down
17 changes: 13 additions & 4 deletions lib/puppet/provider/mysql_grant/mysql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,19 @@ def self.instances
# Matching: GRANT (SELECT, UPDATE) PRIVILEGES ON (*.*) TO ('root')@('127.0.0.1') (WITH GRANT OPTION)
if match = munged_grant.match(/^GRANT\s(.+)\sON\s(.+)\sTO\s(.*)@(.*?)(\s.*)$/)
privileges, table, user, host, rest = match.captures
# Once we split privileges up on the , we need to make sure we
# shortern ALL PRIVILEGES to just all.
stripped_privileges = privileges.split(',').map do |priv|
priv == 'ALL PRIVILEGES' ? 'ALL' : priv.lstrip.rstrip
# 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(/\s*,\s*(?![^(]*\))/).map do |priv|
# split and sort the column_privileges in the parentheses and rejoin
if priv.include?('(')
type, col=priv.strip.split(/\s+|\b/,2)
type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")"
else
# Once we split privileges up on the , we need to make sure we
# shortern ALL PRIVILEGES to just all.
priv == 'ALL PRIVILEGES' ? 'ALL' : priv.strip
end
end
# Same here, but to remove OPTION leaving just GRANT.
options = ['GRANT'] if rest.match(/WITH\sGRANT\sOPTION/)
Expand Down
14 changes: 9 additions & 5 deletions lib/puppet/type/mysql_grant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ def initialize(*args)
# Sort the privileges array in order to ensure the comparision in the provider
# self.instances method match. Otherwise this causes it to keep resetting the
# privileges.
self[:privileges] = Array(self[:privileges]).map(&:upcase).uniq.reject{|k| k == 'GRANT' or k == 'GRANT OPTION'}.sort!
self[:privileges] = Array(self[:privileges]).map{ |priv|
# split and sort the column_privileges in the parentheses and rejoin
if priv.include?('(')
type, col=priv.strip.split(/\s+|\b/,2)
type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")"
else
priv.strip.upcase
end
}.uniq.reject{|k| k == 'GRANT' or k == 'GRANT OPTION'}.sort!
end

validate do
Expand All @@ -37,10 +45,6 @@ def initialize(*args)

newproperty(:privileges, :array_matching => :all) do
desc 'Privileges for user'

munge do |value|
value.upcase
end
end

newproperty(:table) do
Expand Down
24 changes: 24 additions & 0 deletions spec/unit/puppet/type/mysql_grant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,28 @@
}.to raise_error /name must match user and table parameters/
end

describe 'it should munge privileges' do

it 'to just ALL' do
@user = Puppet::Type.type(:mysql_grant).new(
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
:privileges => ['ALL', 'PROXY'] )
expect(@user[:privileges]).to eq(['ALL'])
end

it 'to upcase and ordered' do
@user = Puppet::Type.type(:mysql_grant).new(
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
:privileges => ['select', 'Insert'] )
expect(@user[:privileges]).to eq(['INSERT', 'SELECT'])
end

it 'ordered including column privileges' do
@user = Puppet::Type.type(:mysql_grant).new(
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
:privileges => ['SELECT(Host,Address)', 'Insert'] )
expect(@user[:privileges]).to eq(['INSERT', 'SELECT (Address, Host)'])
end
end

end