Skip to content

Commit fbb2c8f

Browse files
jhriggswilson208
authored andcommitted
Add PROXY grant support to mysql_grant (#934)
1 parent 9ccbe3b commit fbb2c8f

File tree

4 files changed

+134
-19
lines changed

4 files changed

+134
-19
lines changed

lib/puppet/provider/mysql_grant/mysql.rb

+10-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
def self.instances
77
instances = []
8-
users.select{ |user| user =~ /.+@/ }.collect do |user|
8+
users.collect do |user|
99
user_string = self.cmd_user(user)
1010
query = "SHOW GRANTS FOR #{user_string};"
1111
begin
@@ -46,7 +46,7 @@ def self.instances
4646
end
4747
end
4848
# Same here, but to remove OPTION leaving just GRANT.
49-
if rest.match(/WITH\sGRANT\sOPTION/)
49+
if rest.match(/WITH\sGRANT\sOPTION/)
5050
options = ['GRANT']
5151
else
5252
options = ['NONE']
@@ -80,7 +80,7 @@ def self.prefetch(resources)
8080
def grant(user, table, privileges, options)
8181
user_string = self.class.cmd_user(user)
8282
priv_string = self.class.cmd_privs(privileges)
83-
table_string = self.class.cmd_table(table)
83+
table_string = privileges.include?('PROXY') ? self.class.cmd_user(table) : self.class.cmd_table(table)
8484
query = "GRANT #{priv_string}"
8585
query << " ON #{table_string}"
8686
query << " TO #{user_string}"
@@ -102,14 +102,14 @@ def create
102102

103103
def revoke(user, table, revoke_privileges = ['ALL'])
104104
user_string = self.class.cmd_user(user)
105-
table_string = self.class.cmd_table(table)
105+
table_string = revoke_privileges.include?('PROXY') ? self.class.cmd_user(table) : self.class.cmd_table(table)
106106
priv_string = self.class.cmd_privs(revoke_privileges)
107107
# revoke grant option needs to be a extra query, because
108108
# "REVOKE ALL PRIVILEGES, GRANT OPTION [..]" is only valid mysql syntax
109109
# if no ON clause is used.
110110
# It hast to be executed before "REVOKE ALL [..]" since a GRANT has to
111111
# exist to be executed successfully
112-
if revoke_privileges.include? 'ALL'
112+
if revoke_privileges.include? 'ALL' and !revoke_privileges.include?('PROXY')
113113
query = "REVOKE GRANT OPTION ON #{table_string} FROM #{user_string}"
114114
mysql([defaults_file, system_database, '-e', query].compact)
115115
end
@@ -121,7 +121,11 @@ def destroy
121121
# if the user was dropped, it'll have been removed from the user hash
122122
# as the grants are alraedy removed by the DROP statement
123123
if self.class.users.include? @property_hash[:user]
124-
revoke(@property_hash[:user], @property_hash[:table])
124+
if @property_hash[:privileges].include?('PROXY')
125+
revoke(@property_hash[:user], @property_hash[:table], @property_hash[:privileges])
126+
else
127+
revoke(@property_hash[:user], @property_hash[:table])
128+
end
125129
end
126130
@property_hash.clear
127131

lib/puppet/type/mysql_grant.rb

+8-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def initialize(*args)
3131

3232
validate do
3333
fail('privileges parameter is required.') if self[:ensure] == :present and self[:privileges].nil?
34+
fail('PROXY must be the only privilege specified.') if Array(self[:privileges]).count > 1 and Array(self[:privileges]).include?('PROXY')
3435
fail('table parameter is required.') if self[:ensure] == :present and self[:table].nil?
3536
fail('user parameter is required.') if self[:ensure] == :present and self[:user].nil?
3637
fail('name must match user and table parameters') if self[:name] != "#{self[:user]}/#{self[:table]}"
@@ -51,11 +52,17 @@ def initialize(*args)
5152
newproperty(:table) do
5253
desc 'Table to apply privileges to.'
5354

55+
validate do |value|
56+
if Array(@resource[:privileges]).include?('PROXY') and !/^[0-9a-zA-Z$_]*@[\w%\.:\-\/]*$/.match(value)
57+
raise(ArgumentError, '"table" for PROXY should be specified as proxy_user@proxy_host')
58+
end
59+
end
60+
5461
munge do |value|
5562
value.delete("`")
5663
end
5764

58-
newvalues(/.*\..*/,/@/)
65+
newvalues(/.*\..*/,/^[0-9a-zA-Z$_]*@[\w%\.:\-\/]*$/)
5966
end
6067

6168
newproperty(:user) do

spec/acceptance/types/mysql_grant_spec.rb

+99-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class { 'mysql::server':
1616
describe 'missing privileges for user' do
1717
it 'should fail' do
1818
pp = <<-EOS
19-
mysql_user { 'test1@tester':
19+
mysql_user { 'test1@tester':
2020
ensure => present,
2121
}
2222
mysql_grant { 'test1@tester/test.*':
@@ -443,6 +443,104 @@ class { 'mysql::server':
443443
end
444444
end
445445

446+
describe 'adding proxy privileges' do
447+
it 'should work without errors' do
448+
pp = <<-EOS
449+
mysql_user { 'proxy1@tester':
450+
ensure => present,
451+
}
452+
mysql_grant { 'proxy1@tester/proxy_user@proxy_host':
453+
ensure => 'present',
454+
table => 'proxy_user@proxy_host',
455+
user => 'proxy1@tester',
456+
privileges => ['PROXY'],
457+
require => Mysql_user['proxy1@tester'],
458+
}
459+
EOS
460+
461+
apply_manifest(pp, :catch_failures => true)
462+
end
463+
464+
it 'should find the user' do
465+
shell("mysql -NBe \"SHOW GRANTS FOR proxy1@tester\"") do |r|
466+
expect(r.stdout).to match(/GRANT PROXY ON 'proxy_user'@'proxy_host' TO 'proxy1'@'tester'/)
467+
expect(r.stderr).to be_empty
468+
end
469+
end
470+
end
471+
472+
describe 'removing proxy privileges' do
473+
it 'should work without errors' do
474+
pp = <<-EOS
475+
mysql_user { 'proxy1@tester':
476+
ensure => present,
477+
}
478+
mysql_grant { 'proxy1@tester/proxy_user@proxy_host':
479+
ensure => 'absent',
480+
table => 'proxy_user@proxy_host',
481+
user => 'proxy1@tester',
482+
privileges => ['PROXY'],
483+
require => Mysql_user['proxy1@tester'],
484+
}
485+
EOS
486+
487+
apply_manifest(pp, :catch_failures => true)
488+
end
489+
490+
it 'should find the user' do
491+
shell("mysql -NBe \"SHOW GRANTS FOR proxy1@tester\"") do |r|
492+
expect(r.stdout).to_not match(/GRANT PROXY ON 'proxy_user'@'proxy_host' TO 'proxy1'@'tester'/)
493+
expect(r.stderr).to be_empty
494+
end
495+
end
496+
end
497+
498+
describe 'adding proxy privileges with other privileges' do
499+
it 'should fail' do
500+
pp = <<-EOS
501+
mysql_user { 'proxy2@tester':
502+
ensure => present,
503+
}
504+
mysql_grant { 'proxy2@tester/proxy_user@proxy_host':
505+
ensure => 'present',
506+
table => 'proxy_user@proxy_host',
507+
user => 'proxy2@tester',
508+
privileges => ['PROXY', 'SELECT'],
509+
require => Mysql_user['proxy2@tester'],
510+
}
511+
EOS
512+
513+
expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/PROXY must be the only privilege specified/)
514+
end
515+
516+
it 'should not find the user' do
517+
expect(shell("mysql -NBe \"SHOW GRANTS FOR proxy2@tester\"", { :acceptable_exit_codes => 1}).stderr).to match(/There is no such grant defined for user 'proxy2' on host 'tester'/)
518+
end
519+
end
520+
521+
describe 'adding proxy privileges with invalid proxy user' do
522+
it 'should fail' do
523+
pp = <<-EOS
524+
mysql_user { 'proxy3@tester':
525+
ensure => present,
526+
}
527+
mysql_grant { 'proxy3@tester/invalid_proxy_user':
528+
ensure => 'present',
529+
table => 'invalid_proxy_user',
530+
user => 'proxy3@tester',
531+
privileges => ['PROXY'],
532+
require => Mysql_user['proxy3@tester'],
533+
}
534+
EOS
535+
536+
expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/"table" for PROXY should be specified as proxy_user@proxy_host/)
537+
end
538+
539+
it 'should not find the user' do
540+
expect(shell("mysql -NBe \"SHOW GRANTS FOR proxy3@tester\"", { :acceptable_exit_codes => 1}).stderr).to match(/There is no such grant defined for user 'proxy3' on host 'tester'/)
541+
end
542+
end
543+
446544
describe 'grants with skip-name-resolve specified' do
447545
it 'setup mysql::server' do
448546
pp = <<-EOS

spec/unit/puppet/type/mysql_grant_spec.rb

+17-11
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,44 @@
33
describe Puppet::Type.type(:mysql_grant) do
44

55
before :each do
6-
@user = Puppet::Type.type(:mysql_grant).new(:name => 'foo@localhost/*.*', :privileges => ['ALL', 'PROXY'], :table => ['*.*','@'], :user => 'foo@localhost')
6+
@user = Puppet::Type.type(:mysql_grant).new(:name => 'foo@localhost/*.*', :privileges => ['ALL'], :table => ['*.*'], :user => 'foo@localhost')
77
end
88

99
it 'should accept a grant name' do
1010
expect(@user[:name]).to eq('foo@localhost/*.*')
1111
end
12-
12+
1313
it 'should accept ALL privileges' do
1414
@user[:privileges] = 'ALL'
1515
expect(@user[:privileges]).to eq(['ALL'])
1616
end
1717

1818
it 'should accept PROXY privilege' do
1919
@user[:privileges] = 'PROXY'
20+
@user[:table] = 'proxy_user@proxy_host'
2021
expect(@user[:privileges]).to eq(['PROXY'])
2122
end
22-
23+
2324
it 'should accept a table' do
2425
@user[:table] = '*.*'
2526
expect(@user[:table]).to eq('*.*')
2627
end
27-
28+
2829
it 'should accept @ for table' do
2930
@user[:table] = '@'
3031
expect(@user[:table]).to eq('@')
3132
end
32-
33+
34+
it 'should accept proxy user for table' do
35+
@user[:table] = 'proxy_user@proxy_host'
36+
expect(@user[:table]).to eq('proxy_user@proxy_host')
37+
end
38+
3339
it 'should accept a user' do
3440
@user[:user] = 'foo@localhost'
3541
expect(@user[:user]).to eq('foo@localhost')
3642
end
37-
43+
3844
it 'should require a name' do
3945
expect {
4046
Puppet::Type.type(:mysql_grant).new({})
@@ -43,29 +49,29 @@
4349

4450
it 'should require the name to match the user and table' do
4551
expect {
46-
Puppet::Type.type(:mysql_grant).new(:name => 'foo', :privileges => ['ALL', 'PROXY'], :table => ['*.*','@'], :user => 'foo@localhost')
52+
Puppet::Type.type(:mysql_grant).new(:name => 'foo', :privileges => ['ALL'], :table => ['*.*'], :user => 'foo@localhost')
4753
}.to raise_error /name must match user and table parameters/
4854
end
4955

5056
describe 'it should munge privileges' do
5157

5258
it 'to just ALL' do
5359
@user = Puppet::Type.type(:mysql_grant).new(
54-
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
55-
:privileges => ['ALL', 'PROXY'] )
60+
:name => 'foo@localhost/*.*', :table => ['*.*'], :user => 'foo@localhost',
61+
:privileges => ['ALL'] )
5662
expect(@user[:privileges]).to eq(['ALL'])
5763
end
5864

5965
it 'to upcase and ordered' do
6066
@user = Puppet::Type.type(:mysql_grant).new(
61-
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
67+
:name => 'foo@localhost/*.*', :table => ['*.*'], :user => 'foo@localhost',
6268
:privileges => ['select', 'Insert'] )
6369
expect(@user[:privileges]).to eq(['INSERT', 'SELECT'])
6470
end
6571

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

0 commit comments

Comments
 (0)