File: java_ks.rb

package info (click to toggle)
puppet-module-puppetlabs-java-ks 5.1.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 464 kB
  • sloc: ruby: 1,810; sh: 10; makefile: 4
file content (253 lines) | stat: -rw-r--r-- 7,772 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# frozen_string_literal: true

Puppet::Type.newtype(:java_ks) do
  @doc = 'Manages the entries in a java keystore, and uses composite namevars to
  accomplish the same alias spread across multiple target keystores.'

  ensurable do
    desc 'Has three states: present, absent, and latest.  Latest
      will compare the on disk SHA1 fingerprint of the certificate to that
      in keytool to determine if insync? returns true or false.  We redefine
      insync? for this parameter to accomplish this.'

    newvalue(:present) do
      provider.create
    end

    newvalue(:absent) do
      provider.destroy
    end

    newvalue(:latest) do
      if provider.exists?
        provider.update
      else
        provider.create
      end
    end

    def insync?(is)
      @should.each do |should|
        case should
        when :present
          return true if is == :present
        when :absent
          return true if is == :absent
        when :latest
          unless is == :absent
            current = provider.current.split('/')
            latest = provider.latest.split('/')
            return true if latest.to_set.subset?(current.to_set)
          end
        end
      end

      false
    end

    defaultto :present
  end

  newparam(:name) do
    desc 'The alias that is used to identify the entry in the keystore. This will be
    converted to lowercase.'

    isnamevar

    munge(&:downcase)
  end

  newparam(:target) do
    desc 'Destination file for the keystore.  This will autorequire the parent directory of the file.'

    isnamevar
  end

  newparam(:certificate) do
    desc 'A file containing a server certificate, followed by zero or more intermediate certificate authorities.
      All certificates will be placed in the keystore. This will autorequire the specified file.'
  end

  newparam(:certificate_content) do
    desc 'A string containing a server certificate, followed by zero or more intermediate certificate authorities.
      All certificates will be placed in the keystore.'
  end

  newparam(:storetype) do
    desc 'Optional storetype
      Valid options: <jceks>, <pkcs12>, <jks>'

    newvalues(:jceks, :pkcs12, :jks)
  end

  newparam(:private_key) do
    desc 'If you want an application to be a server and encrypt traffic,
      you will need a private key.  Private key entries in a keystore must be
      accompanied by a signed certificate for the keytool provider. This parameter
      allows you to specify the file name containing the private key. This will autorequire
      the specified file.'
  end

  newparam(:private_key_content) do
    desc 'If you want an application to be a server and encrypt traffic,
      you will need a private key.  Private key entries in a keystore must be
      accompanied by a signed certificate for the keytool provider. This parameter allows you to specify the content
      of the private key.'
  end

  newparam(:private_key_type) do
    desc 'The type of the private key. Usually the private key is of type RSA
      key but it can also be an Elliptic Curve key (EC) or DSA.
      Valid options: <rsa>, <dsa>, <ec>. Defaults to <rsa>'

    newvalues(:rsa, :dsa, :ec)

    defaultto :rsa
  end

  newparam(:chain) do
    desc 'The intermediate certificate authorities, if they are to be taken
      from a file separate from the server certificate. This will autorequire the specified file.'
  end

  newproperty(:password) do
    desc 'The password used to protect the keystore.  If private keys are
      subsequently also protected this password will be used to attempt
      unlocking. Must be six or more characters in length. Cannot be used
      together with :password_file, but you must pass at least one of these parameters.'

    munge do |value|
      value = value.unwrap if value.respond_to?(:unwrap)
      super(value)
    end

    validate do |value|
      value = value.unwrap if value.respond_to?(:unwrap)
      raise Puppet::Error, "password is #{value.length} characters long; must be 6 characters or greater in length" if value.length < 6
    end
  end

  newparam(:password_file) do
    desc 'The path to a file containing the password used to protect the
      keystore. This cannot be used together with :password, but you must pass at least one of these parameters.'
  end

  newparam(:password_fail_reset) do
    desc "If the supplied password does not succeed in unlocking the
      keystore file, then delete the keystore file and create a new one.
      Default: false."

    newvalues(true, false)

    defaultto false
  end

  newparam(:destkeypass) do
    desc 'The password used to protect the key in keystore.'

    munge do |value|
      value = value.unwrap if value.respond_to?(:unwrap)
      super(value)
    end

    validate do |value|
      value = value.unwrap if value.respond_to?(:unwrap)
      raise Puppet::Error, "destkeypass is #{value.length} characters long; must be of length 6 or greater" if value.length < 6
    end
  end

  newparam(:trustcacerts) do
    desc "Certificate authorities aren't by default trusted so if you are adding a CA you need to set this to true.
     Defaults to :false."

    newvalues(true, false)

    defaultto false
  end

  newparam(:path) do
    desc "The search path used for command (keytool, openssl) execution.
      Paths can be specified as an array or as a '#{File::PATH_SEPARATOR}' separated list."

    # Support both arrays and colon-separated fields.
    def value=(*values)
      @value = values.flatten.map { |val|
        val.split(File::PATH_SEPARATOR)
      }.flatten
    end
  end

  newparam(:keytool_timeout) do
    desc 'Timeout for the keytool command in seconds.'

    defaultto 120
  end

  newparam(:source_password) do
    munge do |value|
      value = value.unwrap if value.respond_to?(:unwrap)
      super(value)
    end

    desc 'The source keystore password'
  end

  newparam(:source_alias) do
    desc 'The source certificate alias'
  end

  # Where we setup autorequires.
  autorequire(:file) do
    auto_requires = []
    [:private_key, :certificate, :chain].each do |param|
      auto_requires << @parameters[param].value if @parameters.include?(param)
    end
    auto_requires << File.dirname(@parameters[:target].value) if @parameters.include?(:target)
    auto_requires
  end

  # Our title_patterns method for mapping titles to namevars for supporting
  # composite namevars.
  def self.title_patterns
    [
      [
        %r{^([^:]+)$},
        [
          [:name],
        ],
      ],
      [
        %r{^(.*):([a-z]:(/|\\).*)$}i,
        [
          [:name],
          [:target],
        ],
      ],
      [
        %r{^(.*):(.*)$},
        [
          [:name],
          [:target],
        ],
      ],
    ]
  end

  validate do
    if self[:ensure] != :absent
      raise Puppet::Error, "You must pass one of 'certificate' or 'certificate_content'" unless value(:certificate) || value(:certificate_content)

      raise Puppet::Error, "You must pass either 'certificate' or 'certificate_content', not both." if value(:certificate) && value(:certificate_content)

      raise Puppet::Error, "You must pass either 'private_key' or 'private_key_content', not both." if value(:private_key) && value(:private_key_content)
    end

    raise Puppet::Error, "You must pass either 'password' or 'password_file', not both." if value(:password) && value(:password_file)

    raise Puppet::Error, "You must pass one of 'password' or 'password_file'." unless value(:password) || value(:password_file)

    if value(:storetype) == :pkcs12 && value(:source_password).nil?
      fail "You must provide 'source_password' when using a 'pkcs12' storetype." # rubocop:disable Style/SignalException : Associated test fails if 'raise' is used
    end
  end
end