diff --git a/lib/puppet/type/mysql_grant.rb b/lib/puppet/type/mysql_grant.rb index 8262e1e53..d6e354345 100644 --- a/lib/puppet/type/mysql_grant.rb +++ b/lib/puppet/type/mysql_grant.rb @@ -60,13 +60,24 @@ def initialize(*args) newproperty(:user) do desc 'User to operate on.' validate do |value| - # https://dev.mysql.com/doc/refman/5.1/en/account-names.html - # Regex should problably be more like this: /^[`'"]?[^`'"]*[`'"]?@[`'"]?[\w%\.]+[`'"]?$/ - raise(ArgumentError, "Invalid user #{value}") unless value =~ /[\w-]*@[\w%\.:]+/ - username = value.split('@')[0] - if username.size > 16 - raise ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters' + # http://dev.mysql.com/doc/refman/5.5/en/identifiers.html + # If at least one special char is used, string must be quoted + + # http://stackoverflow.com/questions/8055727/negating-a-backreference-in-regular-expressions/8057827#8057827 + if matches = /^(['`"])((?!\1).)+\1@([\w%\.:]+)$/.match(value) + user_part = matches[2] + host_part = matches[3] + elsif matches = /^([0-9a-zA-Z$_]+)@([\w%\.:]+)$/.match(value) + user_part = matches[1] + host_part = matches[2] + elsif matches = /^(?:(?!['`"]).*)([^0-9a-zA-Z$_]).*@.+$/.match(value) + # does not start with a quote, but contains a special character + raise(ArgumentError, "Database user #{value} must be properly quoted, invalid character: '#{matches[1]}'") + else + raise(ArgumentError, "Invalid database user #{value}") end + + raise(ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters') unless user_part.size <= 16 end end diff --git a/lib/puppet/type/mysql_user.rb b/lib/puppet/type/mysql_user.rb index 5078649de..271baac24 100644 --- a/lib/puppet/type/mysql_user.rb +++ b/lib/puppet/type/mysql_user.rb @@ -10,19 +10,28 @@ desc "The name of the user. This uses the 'username@hostname' or username@hostname." validate do |value| # http://dev.mysql.com/doc/refman/5.5/en/identifiers.html - # Regex should problably be more like this: /^[`'"]?[^`'"]*[`'"]?@[`'"]?[\w%\.]+[`'"]?$/ # If at least one special char is used, string must be quoted - raise(ArgumentError, "Database user #{value} must be quotted as it contains special characters") if value =~ /^[^'`"].*[^0-9a-zA-Z$_].*[^'`"]@[\w%\.:]+/ - raise(ArgumentError, "Invalid database user #{value}") unless value =~ /^(?:['`"][^'`"]*['`"]|[0-9a-zA-Z$_]*)@[\w%\.:]+/ - username = value.split('@')[0] - if not ((username =~ /['"`]*['"`]$/ and username.size <= 18) or username.size <= 16) - raise ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters' + + # http://stackoverflow.com/questions/8055727/negating-a-backreference-in-regular-expressions/8057827#8057827 + if matches = /^(['`"])((?:(?!\1).)+)\1@([\w%\.:]+)$/.match(value) + user_part = matches[2] + host_part = matches[3] + elsif matches = /^([0-9a-zA-Z$_]+)@([\w%\.:]+)$/.match(value) + user_part = matches[1] + host_part = matches[2] + elsif matches = /^(?:(?!['`"]).*)([^0-9a-zA-Z$_]).*@.+$/.match(value) + # does not start with a quote, but contains a special character + raise(ArgumentError, "Database user #{value} must be properly quoted, invalid character: '#{matches[1]}'") + else + raise(ArgumentError, "Invalid database user #{value}") end + + raise(ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters') if user_part.size > 16 end munge do |value| - user_part, host_part = value.split('@') - "#{user_part}@#{host_part.downcase}" + matches = /^((['`"]?).+\2)@([\w%\.:]+)$/.match(value) + "#{matches[1]}@#{matches[3].downcase}" end end diff --git a/spec/unit/puppet/type/mysql_user_spec.rb b/spec/unit/puppet/type/mysql_user_spec.rb index 86d56d7cd..52439f468 100644 --- a/spec/unit/puppet/type/mysql_user_spec.rb +++ b/spec/unit/puppet/type/mysql_user_spec.rb @@ -81,7 +81,15 @@ it 'should fail with an unquotted username with special char' do expect { Puppet::Type.type(:mysql_user).new(:name => 'in-valid@localhost', :password_hash => 'pass') - }.to raise_error /Database user in-valid@localhost must be quotted/ + }.to raise_error /Database user in-valid@localhost must be properly quoted, invalid character: '-'/ + end + end + + context 'using "misquoted@localhost' do + it 'should fail with a misquoted username is used' do + expect { + Puppet::Type.type(:mysql_user).new(:name => '"misquoted@localhost', :password_hash => 'pass') + }.to raise_error /Invalid database user "misquoted@localhost/ end end end