diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/facter/couchdb_pwhash_alg.rb | 43 | ||||
-rw-r--r-- | lib/facter/couchdb_version.rb | 34 | ||||
-rw-r--r-- | lib/puppet/parser/functions/couchdblookup.rb | 55 | ||||
-rw-r--r-- | lib/puppet/parser/functions/pbkdf2.rb | 62 |
4 files changed, 194 insertions, 0 deletions
diff --git a/lib/facter/couchdb_pwhash_alg.rb b/lib/facter/couchdb_pwhash_alg.rb new file mode 100644 index 00000000..60ae701a --- /dev/null +++ b/lib/facter/couchdb_pwhash_alg.rb @@ -0,0 +1,43 @@ +require 'facter' + +def version_parts ( version ) + # gives back a hash containing major, minor and patch numbers + # of a give version string + + parts = Hash.new + first, *rest = version.split(".") + parts["major"] = first + parts["minor"] = rest[0] + parts["patch"] = rest[1] + return parts +end + +def couchdb_pwhash_alg + # couchdb uses sha1 as pw hash algorithm until v. 1.2, + # but pbkdf2 from v.1.3 on. + # see http://docs.couchdb.org/en/1.4.x/configuring.html for + # details + + couchdb_version = Facter.value(:couchdb_version) + version = version_parts(couchdb_version) + major = version["major"].to_i + alg = case major + when 0 then alg = 'n/a' + when 1 then + minor = version['minor'].to_i + if minor < 3 + alg = 'sha1' + else + alg = 'pbkdf2' + end + else + alg = 'pbkdf2' + end + return alg +end + +Facter.add(:couchdb_pwhash_alg) do + setcode do + couchdb_pwhash_alg + end +end diff --git a/lib/facter/couchdb_version.rb b/lib/facter/couchdb_version.rb new file mode 100644 index 00000000..3a721169 --- /dev/null +++ b/lib/facter/couchdb_version.rb @@ -0,0 +1,34 @@ +require 'facter' + +def deb_installed_version ( name ) + # returns an empty string if package is not installed, + # otherwise the version + + version = `apt-cache policy #{name} | grep Installed 2>&1` + version.slice! " Installed: " + version.slice! "(none)" + return version.strip.chomp +end + +def couchdb_version + bigcouch = deb_installed_version("bigcouch") + if bigcouch.empty? + couchdb = deb_installed_version("couchdb") + if couchdb.empty? + version = 'n/a' + else + version = couchdb + end + else + # bigcouch is currently only available in one version (0.4.2), + # which includes couchdb 1.1.1 + version = '1.1.1' + end + return version +end + +Facter.add(:couchdb_version) do + setcode do + couchdb_version + end +end diff --git a/lib/puppet/parser/functions/couchdblookup.rb b/lib/puppet/parser/functions/couchdblookup.rb new file mode 100644 index 00000000..b9067d2a --- /dev/null +++ b/lib/puppet/parser/functions/couchdblookup.rb @@ -0,0 +1,55 @@ +# +# A basic function to retrieve data in couchdb +# + + +module Puppet::Parser::Functions + newfunction(:couchdblookup, :type => :rvalue) do |args| + require 'json' + require 'open-uri' + + raise Puppet::ParseError, ("couchdblookup(): wrong number of arguments (#{args.length}; must be 2 or 3)") unless args.length.between?(2, 3) + + url = args[0] + key = args[1] + default = args[2] if args.length >= 3 + + begin + json = JSON.parse(open(URI.parse(url)).read) + rescue OpenURI::HTTPError => error + raise Puppet::ParseError, "couchdblookup(): fetching URL #{url} failed with status '#{error.message}'" + rescue Timeout::Error => error + raise Puppet::ParseError, "couchdblookup(): connection to couchdb server timed out: '#{error.message}'" + rescue Errno::ECONNREFUSED => error + raise Puppet::ParseError, "couchdblookup(): connection to couchdb server failed: '#{error.message}'" + rescue JSON::ParserError => error + raise Puppet::ParseError, "couchdblookup(): failed to parse JSON received from couchdb: '#{error.message}'" + rescue StandardError => error + raise Puppet::ParseError, "couchdblookup(): something unexpected happened: '#{error.inspect}'" + end + + result = nil + + if json.has_key?("rows") + + if json['rows'].length > 1 + arr = json['rows'].collect do |x| + x[key] if x.is_a?(Hash) and x.has_key?(key) + end + arr.compact! + result = arr unless arr.empty? + + elsif json['rows'].length == 1 + hash = json['rows'].pop + result = hash[key] if hash.is_a?(Hash) + end + + elsif json.has_key?(key) + result = json[key] + end + + result or default or raise Puppet::ParseError, "couchdblookup(): key '#{key}' not found in JSON object !" + + end +end + diff --git a/lib/puppet/parser/functions/pbkdf2.rb b/lib/puppet/parser/functions/pbkdf2.rb new file mode 100644 index 00000000..46400c9c --- /dev/null +++ b/lib/puppet/parser/functions/pbkdf2.rb @@ -0,0 +1,62 @@ +# +# pbkdf2.rb +# + +module Puppet::Parser::Functions + newfunction(:pbkdf2, :type => :rvalue, :doc => <<-EOS +This converts a password and a salt (and optional iterations and keylength +parameters) to a hash containing the salted SHA1 password hash, salt, +iterations and keylength. +pbkdf2 is used i.e. for couchdb passwords since v1.3. + +Example usage: + $pbkdf2 = pbkdf2($::couchdb::admin_pw, $::couchdb::admin_salt) + $sha1 = $pbkdf2['sha1'] +EOS + ) do |arguments| + require 'openssl' + require 'base64' + + raise(Puppet::ParseError, "pbkdf2(): Wrong number of arguments " + + "passed (#{arguments.size} but we require at least 2)") if arguments.size < 2 + + unless arguments.is_a?(Array) + raise(Puppet::ParseError, 'pbkdf2(): Requires a ' + + "Array argument, you passed: #{password.class}") + end + + password = arguments[0] + salt = arguments[1] + + if arguments.size > 2 + iterations = arguments[2].to_i + else + iterations = 1000 + end + + if arguments.size > 3 + keylength = arguments[3].to_i + else + keylength = 20 + end + + pbkdf2 = OpenSSL::PKCS5::pbkdf2_hmac_sha1( + password, + salt, + iterations, + keylength + ) + + return_hash = Hash.new() + # return hex encoded string + return_hash['sha1'] = pbkdf2.unpack('H*')[0] + return_hash['password'] = password + return_hash['salt'] = salt + return_hash['iterations'] = iterations + return_hash['keylength'] = keylength + + return return_hash + end +end + +# vim: set ts=2 sw=2 et : |