Support authentication plugins
This uses CREATE USER xxx IDENTIFIED WITH yyy For tests: unix_socket is not loaded by default, so this might require: install plugin unix_socket soname 'auth_socket.so'; The mysql_native_password plugin is available by default and allows you to also set a password.
This commit is contained in:
parent
23c192df9f
commit
305b0d2a87
4 changed files with 37 additions and 10 deletions
|
@ -12,13 +12,14 @@ Puppet::Type.type(:mysql_user).provide(:mysql, :parent => Puppet::Provider::Mysq
|
||||||
# To reduce the number of calls to MySQL we collect all the properties in
|
# To reduce the number of calls to MySQL we collect all the properties in
|
||||||
# one big swoop.
|
# one big swoop.
|
||||||
users.collect do |name|
|
users.collect do |name|
|
||||||
query = "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD FROM mysql.user WHERE CONCAT(user, '@', host) = '#{name}'"
|
query = "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD, PLUGIN FROM mysql.user WHERE CONCAT(user, '@', host) = '#{name}'"
|
||||||
@max_user_connections, @max_connections_per_hour, @max_queries_per_hour,
|
@max_user_connections, @max_connections_per_hour, @max_queries_per_hour,
|
||||||
@max_updates_per_hour, @password = mysql([defaults_file, "-NBe", query].compact).split(/\s/)
|
@max_updates_per_hour, @password, @plugin = mysql([defaults_file, "-NBe", query].compact).split(/\s/)
|
||||||
|
|
||||||
new(:name => name,
|
new(:name => name,
|
||||||
:ensure => :present,
|
:ensure => :present,
|
||||||
:password_hash => @password,
|
:password_hash => @password,
|
||||||
|
:plugin => @plugin,
|
||||||
:max_user_connections => @max_user_connections,
|
:max_user_connections => @max_user_connections,
|
||||||
:max_connections_per_hour => @max_connections_per_hour,
|
:max_connections_per_hour => @max_connections_per_hour,
|
||||||
:max_queries_per_hour => @max_queries_per_hour,
|
:max_queries_per_hour => @max_queries_per_hour,
|
||||||
|
@ -39,17 +40,26 @@ Puppet::Type.type(:mysql_user).provide(:mysql, :parent => Puppet::Provider::Mysq
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
merged_name = @resource[:name].sub('@', "'@'")
|
merged_name = @resource[:name].sub('@', "'@'")
|
||||||
password_hash = @resource.value(:password_hash)
|
password_hash = @resource.value(:password_hash)
|
||||||
|
plugin = @resource.value(:plugin)
|
||||||
max_user_connections = @resource.value(:max_user_connections) || 0
|
max_user_connections = @resource.value(:max_user_connections) || 0
|
||||||
max_connections_per_hour = @resource.value(:max_connections_per_hour) || 0
|
max_connections_per_hour = @resource.value(:max_connections_per_hour) || 0
|
||||||
max_queries_per_hour = @resource.value(:max_queries_per_hour) || 0
|
max_queries_per_hour = @resource.value(:max_queries_per_hour) || 0
|
||||||
max_updates_per_hour = @resource.value(:max_updates_per_hour) || 0
|
max_updates_per_hour = @resource.value(:max_updates_per_hour) || 0
|
||||||
|
|
||||||
mysql([defaults_file, '-e', "GRANT USAGE ON *.* TO '#{merged_name}' IDENTIFIED BY PASSWORD '#{password_hash}' WITH MAX_USER_CONNECTIONS #{max_user_connections} MAX_CONNECTIONS_PER_HOUR #{max_connections_per_hour} MAX_QUERIES_PER_HOUR #{max_queries_per_hour} MAX_UPDATES_PER_HOUR #{max_updates_per_hour}"].compact)
|
# Use CREATE USER to be compatible with NO_AUTO_CREATE_USER sql_mode
|
||||||
|
# This is also required if you want to specify a authentication plugin
|
||||||
@property_hash[:ensure] = :present
|
if !plugin.nil?
|
||||||
@property_hash[:password_hash] = password_hash
|
mysql([defaults_file, '-e', "CREATE USER '#{merged_name}' IDENTIFIED WITH '#{plugin}'"].compact)
|
||||||
|
@property_hash[:ensure] = :present
|
||||||
|
@property_hash[:plugin] = plugin
|
||||||
|
else
|
||||||
|
mysql([defaults_file, '-e', "CREATE USER '#{merged_name}' IDENTIFIED BY PASSWORD '#{password_hash}'"].compact)
|
||||||
|
@property_hash[:ensure] = :present
|
||||||
|
@property_hash[:password_hash] = password_hash
|
||||||
|
end
|
||||||
|
mysql([defaults_file, '-e', "GRANT USAGE ON *.* TO '#{merged_name}' WITH MAX_USER_CONNECTIONS #{max_user_connections} MAX_CONNECTIONS_PER_HOUR #{max_connections_per_hour} MAX_QUERIES_PER_HOUR #{max_queries_per_hour} MAX_UPDATES_PER_HOUR #{max_updates_per_hour}"].compact)
|
||||||
@property_hash[:max_user_connections] = max_user_connections
|
@property_hash[:max_user_connections] = max_user_connections
|
||||||
@property_hash[:max_connections_per_hour] = max_connections_per_hour
|
@property_hash[:max_connections_per_hour] = max_connections_per_hour
|
||||||
@property_hash[:max_queries_per_hour] = max_queries_per_hour
|
@property_hash[:max_queries_per_hour] = max_queries_per_hour
|
||||||
|
|
|
@ -40,6 +40,11 @@ Puppet::Type.newtype(:mysql_user) do
|
||||||
newvalue(/\w+/)
|
newvalue(/\w+/)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
newproperty(:plugin) do
|
||||||
|
desc 'The authentication plugin of the user.'
|
||||||
|
newvalue(/\w+/)
|
||||||
|
end
|
||||||
|
|
||||||
newproperty(:max_user_connections) do
|
newproperty(:max_user_connections) do
|
||||||
desc "Max concurrent connections for the user. 0 means no (or global) limit."
|
desc "Max concurrent connections for the user. 0 means no (or global) limit."
|
||||||
newvalue(/\d+/)
|
newvalue(/\d+/)
|
||||||
|
|
|
@ -37,7 +37,7 @@ usvn_user@localhost
|
||||||
Puppet::Util.stubs(:which).with('mysql').returns('/usr/bin/mysql')
|
Puppet::Util.stubs(:which).with('mysql').returns('/usr/bin/mysql')
|
||||||
File.stubs(:file?).with('/root/.my.cnf').returns(true)
|
File.stubs(:file?).with('/root/.my.cnf').returns(true)
|
||||||
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"]).returns('joe@localhost')
|
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"]).returns('joe@localhost')
|
||||||
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD FROM mysql.user WHERE CONCAT(user, '@', host) = 'joe@localhost'"]).returns('10 10 10 10 *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4')
|
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD, PLUGIN FROM mysql.user WHERE CONCAT(user, '@', host) = 'joe@localhost'"]).returns('10 10 10 10 *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4')
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:instance) { provider.class.instances.first }
|
let(:instance) { provider.class.instances.first }
|
||||||
|
@ -46,7 +46,7 @@ usvn_user@localhost
|
||||||
it 'returns an array of users' do
|
it 'returns an array of users' do
|
||||||
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"]).returns(raw_users)
|
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"]).returns(raw_users)
|
||||||
parsed_users.each do |user|
|
parsed_users.each do |user|
|
||||||
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'"]).returns('10 10 10 10 ')
|
provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD, PLUGIN FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'"]).returns('10 10 10 10 ')
|
||||||
end
|
end
|
||||||
|
|
||||||
usernames = provider.class.instances.collect {|x| x.name }
|
usernames = provider.class.instances.collect {|x| x.name }
|
||||||
|
@ -63,7 +63,8 @@ usvn_user@localhost
|
||||||
|
|
||||||
describe 'create' do
|
describe 'create' do
|
||||||
it 'makes a user' do
|
it 'makes a user' do
|
||||||
provider.expects(:mysql).with([defaults_file, '-e', "GRANT USAGE ON *.* TO 'joe'@'localhost' IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4' WITH MAX_USER_CONNECTIONS 10 MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 10"])
|
provider.expects(:mysql).with([defaults_file, '-e', "CREATE USER 'joe'@'localhost' IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'"])
|
||||||
|
provider.expects(:mysql).with([defaults_file, '-e', "GRANT USAGE ON *.* TO 'joe'@'localhost' WITH MAX_USER_CONNECTIONS 10 MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 10"])
|
||||||
provider.expects(:exists?).returns(true)
|
provider.expects(:exists?).returns(true)
|
||||||
expect(provider.create).to be_truthy
|
expect(provider.create).to be_truthy
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,3 +19,14 @@ mysql_user{ 'dan@%':
|
||||||
ensure => present,
|
ensure => present,
|
||||||
password_hash => mysql_password('blah'),
|
password_hash => mysql_password('blah'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mysql_user{ 'socketplugin@%':
|
||||||
|
ensure => present,
|
||||||
|
plugin => 'unix_socket',
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_user{ 'socketplugin@%':
|
||||||
|
ensure => present,
|
||||||
|
password_hash => mysql_password('blah'),
|
||||||
|
plugin => 'mysql_native_password',
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue