Change grant provider to ignore grants for non existing users.

In the grant provider users are fetched by querying mysql.user table. Grants
for those users are fetched using show grants for... syntax. This can lead to
errors, when some of the users in mysql.user table do not have currently
active grants.

This happens at least when MySQL is started with --skip-name-resolve option,
when there are users with the hostname part specified as a FQDN. Such users are
created by mysql_install_db. This leads to problems if mysql::account_security
is included for the node and skip-name-resolve is specified in override_options
hash for mysql::server.

Includes acceptance test for the change.
This commit is contained in:
Jaakko 2014-06-10 16:07:50 +02:00
parent 4f4c68767e
commit 3cfbb581cc
2 changed files with 92 additions and 1 deletions

View file

@ -8,7 +8,20 @@ Puppet::Type.type(:mysql_grant).provide(:mysql, :parent => Puppet::Provider::Mys
users.select{ |user| user =~ /.+@/ }.collect do |user|
user_string = self.cmd_user(user)
query = "SHOW GRANTS FOR #{user_string};"
grants = mysql([defaults_file, "-NBe", query].compact)
begin
grants = mysql([defaults_file, "-NBe", query].compact)
rescue Puppet::ExecutionFailure => e
# Silently ignore users with no grants. Can happen e.g. if user is
# defined with fqdn and server is run with skip-name-resolve. Example:
# Default root user created by mysql_install_db on a host with fqdn
# of myhost.mydomain.my: root@myhost.mydomain.my, when MySQL is started
# with --skip-name-resolve.
if e.inspect =~ /There is no such grant defined for user/
next
else
raise Puppet::Error, "#mysql had an error -> #{e.inspect}"
end
end
# Once we have the list of grants generate entries for each.
grants.each_line do |grant|
# Match the munges we do in the type.

View file

@ -320,4 +320,82 @@ describe 'mysql_grant', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatin
end
end
end
describe 'grants with skip-name-resolve specified' do
it 'setup mysql::server' do
pp = <<-EOS
class { 'mysql::server':
override_options => {
'mysqld' => {'skip-name-resolve' => true}
},
restart => true,
}
EOS
apply_manifest(pp, :catch_failures => true)
end
it 'should apply' do
pp = <<-EOS
mysql_grant { 'test@fqdn.com/test.*':
ensure => 'present',
table => 'test.*',
user => 'test@fqdn.com',
privileges => 'ALL',
}
mysql_grant { 'test@192.168.5.7/test.*':
ensure => 'present',
table => 'test.*',
user => 'test@192.168.5.7',
privileges => 'ALL',
}
EOS
apply_manifest(pp, :catch_failures => true)
end
it 'should have skip_name_resolve set' do
shell("mysql -NBe 'select @@skip_name_resolve'") do |r|
expect(r.stdout).to match(/1/)
expect(r.stderr).to be_empty
end
end
it 'should fail with fqdn' do
expect(shell("mysql -NBe \"SHOW GRANTS FOR test@fqdn.com\"", { :acceptable_exit_codes => 1}).stderr).to match(/There is no such grant defined for user 'test' on host 'fqdn.com'/)
end
it 'finds ipv4' do
shell("mysql -NBe \"SHOW GRANTS FOR 'test'@'192.168.5.7'\"") do |r|
expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'192.168.5.7'/)
expect(r.stderr).to be_empty
end
end
it 'should fail to execute while applying' do
pp = <<-EOS
mysql_grant { 'test@fqdn.com/test.*':
ensure => 'present',
table => 'test.*',
user => 'test@fqdn.com',
privileges => 'ALL',
}
EOS
mysql_cmd = shell('which mysql').stdout.chomp
shell("mv #{mysql_cmd} #{mysql_cmd}.bak")
expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/Command mysql is missing/)
shell("mv #{mysql_cmd}.bak #{mysql_cmd}")
end
it 'reset mysql::server config' do
pp = <<-EOS
class { 'mysql::server':
restart => true,
}
EOS
apply_manifest(pp, :catch_failures => true)
end
end
end