From f2019755fd724fb1020cb2d97cdf82b751450ebc Mon Sep 17 00:00:00 2001
From: Micah <micah@leap.se>
Date: Tue, 12 Jul 2016 16:45:54 -0400
Subject: git subrepo clone https://leap.se/git/puppet_couchdb
 puppet/modules/couchdb

subrepo:
  subdir:   "puppet/modules/couchdb"
  merged:   "76ff149"
upstream:
  origin:   "https://leap.se/git/puppet_couchdb"
  branch:   "master"
  commit:   "76ff149"
git-subrepo:
  version:  "0.3.0"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "1e79595"

Change-Id: I9ccb1a9dfdaa083814ea395132c42a778052f59b
---
 .../couchdb/lib/facter/couchdb_pwhash_alg.rb       | 43 +++++++++++++++
 .../modules/couchdb/lib/facter/couchdb_version.rb  | 34 ++++++++++++
 .../lib/puppet/parser/functions/couchdblookup.rb   | 55 +++++++++++++++++++
 .../couchdb/lib/puppet/parser/functions/pbkdf2.rb  | 62 ++++++++++++++++++++++
 4 files changed, 194 insertions(+)
 create mode 100644 puppet/modules/couchdb/lib/facter/couchdb_pwhash_alg.rb
 create mode 100644 puppet/modules/couchdb/lib/facter/couchdb_version.rb
 create mode 100644 puppet/modules/couchdb/lib/puppet/parser/functions/couchdblookup.rb
 create mode 100644 puppet/modules/couchdb/lib/puppet/parser/functions/pbkdf2.rb

(limited to 'puppet/modules/couchdb/lib')

diff --git a/puppet/modules/couchdb/lib/facter/couchdb_pwhash_alg.rb b/puppet/modules/couchdb/lib/facter/couchdb_pwhash_alg.rb
new file mode 100644
index 00000000..60ae701a
--- /dev/null
+++ b/puppet/modules/couchdb/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/puppet/modules/couchdb/lib/facter/couchdb_version.rb b/puppet/modules/couchdb/lib/facter/couchdb_version.rb
new file mode 100644
index 00000000..3a721169
--- /dev/null
+++ b/puppet/modules/couchdb/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/puppet/modules/couchdb/lib/puppet/parser/functions/couchdblookup.rb b/puppet/modules/couchdb/lib/puppet/parser/functions/couchdblookup.rb
new file mode 100644
index 00000000..b9067d2a
--- /dev/null
+++ b/puppet/modules/couchdb/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/puppet/modules/couchdb/lib/puppet/parser/functions/pbkdf2.rb b/puppet/modules/couchdb/lib/puppet/parser/functions/pbkdf2.rb
new file mode 100644
index 00000000..46400c9c
--- /dev/null
+++ b/puppet/modules/couchdb/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 :
-- 
cgit v1.2.3