Puppet Function: openldap_password

Defined in:
lib/puppet/functions/openldap_password.rb
Function type:
Ruby 4.x API

Overview

openldap_password(String $secret, Optional[Enum["PBKDF2","CRYPT","MD5","SMD5","SSHA","SHA"]] $scheme, Optional[Integer] $iterations, Optional[Enum["SHA256", "SHA512"]] $hash_type) ⇒ String

Parameters:

  • secret (String) —

    The secret to be hashed.

  • scheme (Optional[Enum["PBKDF2","CRYPT","MD5","SMD5","SSHA","SHA"]]) —

    The optional scheme to use (defaults to SSHA).

  • iterations (Optional[Integer]) —

    The number of iterations to use for the hashing (defaults to 60000). Only applicable for PBKDF2.

  • hash_type (Optional[Enum["SHA256", "SHA512"]]) —

    The hash algorithm to use: ‘SHA256’ (32 bytes) or ‘SHA512’ (64 bytes). Defaults to ‘SHA512’. Only applicable for PBKDF2.

Returns:

  • (String) —

    The hashed secret.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/puppet/functions/openldap_password.rb', line 11

Puppet::Functions.create_function(:openldap_password) do
  # @param secret
  #   The secret to be hashed.
  #
  # @param scheme
  #   The optional scheme to use (defaults to SSHA).
  #
  # @param iterations
  #   The number of iterations to use for the hashing (defaults to 60000).
  #   Only applicable for PBKDF2.
  #
  # @param hash_type
  #    The hash algorithm to use: 'SHA256' (32 bytes) or 'SHA512' (64 bytes).
  #    Defaults to 'SHA512'. Only applicable for PBKDF2.
  #
  # @return [String]
  #   The hashed secret.
  #
  dispatch :generate_password do
    required_param 'String', :secret
    optional_param 'Enum["PBKDF2","CRYPT","MD5","SMD5","SSHA","SHA"]', :scheme
    optional_param 'Integer', :iterations
    optional_param 'Enum["SHA256", "SHA512"]', :hash_type

    return_type 'String'
  end

  def ab64_encode(data)
    Base64.strict_encode64(data).tr('+', '.').delete('=')
  end

  def generate_password(secret, scheme = 'SSHA', iterations = 60_000, hash_type = 'SHA512')
    case scheme[%r{([A-Z,0-9]+)}, 1]
    when 'PBKDF2'
      salt = OpenSSL::Random.random_bytes(16)

      digest_map = {
        'SHA256' => { name: 'SHA256', length: 32, obj: OpenSSL::Digest.new('SHA256') },
        'SHA512' => { name: 'SHA512', length: 64, obj: OpenSSL::Digest.new('SHA512') },
      }

      config = digest_map[hash_type]

      derived_key = OpenSSL::PKCS5.pbkdf2_hmac(
        secret,
        salt,
        iterations,
        config[:length],
        config[:obj],
      )

      password = "{PBKDF2-#{config[:name]}}#{iterations}$#{ab64_encode(salt)}$#{ab64_encode(derived_key)}"
    when 'CRYPT'
      salt = call_function('fqdn_rand_string', 2)
      password = "{CRYPT}#{secret.crypt(salt)}"
    when 'MD5'
      password = "{MD5}#{Digest::MD5.hexdigest(secret)}"
    when 'SMD5'
      salt = call_function('fqdn_rand_string', 8)
      md5_hash_with_salt = "#{Digest::MD5.digest(secret + salt)}#{salt}"
      password = "{SMD5}#{[md5_hash_with_salt].pack('m').delete("\n")}"
    when 'SSHA'
      salt = call_function('fqdn_rand_string', 8)
      password = "{SSHA}#{Base64.encode64("#{Digest::SHA1.digest(secret + salt)}#{salt}").chomp}"
    when 'SHA'
      password = "{SHA}#{Digest::SHA1.hexdigest(secret)}"
    else
      raise(Puppet::ParseError, "openldap_password(): Unrecognized scheme #{scheme}")
    end

    password
  end
end