bolt 0.23.0 → 0.24.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +5 -2
  3. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +5 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -8
  5. data/lib/bolt/applicator.rb +11 -8
  6. data/lib/bolt/boltdir.rb +13 -5
  7. data/lib/bolt/catalog.rb +22 -47
  8. data/lib/bolt/config.rb +1 -26
  9. data/lib/bolt/executor.rb +1 -1
  10. data/lib/bolt/outputter.rb +0 -9
  11. data/lib/bolt/outputter/human.rb +29 -14
  12. data/lib/bolt/outputter/json.rb +12 -1
  13. data/lib/bolt/pal.rb +12 -10
  14. data/lib/bolt/target.rb +0 -6
  15. data/lib/bolt/task.rb +53 -10
  16. data/lib/bolt/transport/base.rb +1 -6
  17. data/lib/bolt/transport/local.rb +11 -13
  18. data/lib/bolt/transport/local/shell.rb +2 -2
  19. data/lib/bolt/transport/ssh.rb +16 -11
  20. data/lib/bolt/transport/winrm.rb +8 -11
  21. data/lib/bolt/version.rb +1 -1
  22. data/lib/bolt_ext/schemas/task.json +12 -5
  23. data/libexec/apply_catalog.rb +3 -1
  24. data/libexec/bolt_catalog +4 -0
  25. data/vendored/puppet/lib/puppet.rb +2 -1
  26. data/vendored/puppet/lib/puppet/application/agent.rb +2 -6
  27. data/vendored/puppet/lib/puppet/application/apply.rb +100 -60
  28. data/vendored/puppet/lib/puppet/application/cert.rb +26 -291
  29. data/vendored/puppet/lib/puppet/application/device.rb +0 -5
  30. data/vendored/puppet/lib/puppet/application/lookup.rb +1 -1
  31. data/vendored/puppet/lib/puppet/application/ssl.rb +133 -0
  32. data/vendored/puppet/lib/puppet/application_support.rb +1 -2
  33. data/vendored/puppet/lib/puppet/configurer.rb +34 -50
  34. data/vendored/puppet/lib/puppet/configurer/downloader.rb +1 -1
  35. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
  36. data/vendored/puppet/lib/puppet/daemon.rb +1 -1
  37. data/vendored/puppet/lib/puppet/defaults.rb +40 -117
  38. data/vendored/puppet/lib/puppet/face/epp.rb +2 -2
  39. data/vendored/puppet/lib/puppet/face/help.rb +21 -7
  40. data/vendored/puppet/lib/puppet/face/node/clean.rb +14 -10
  41. data/vendored/puppet/lib/puppet/feature/base.rb +7 -23
  42. data/vendored/puppet/lib/puppet/feature/eventlog.rb +1 -1
  43. data/vendored/puppet/lib/puppet/file_serving/base.rb +2 -2
  44. data/vendored/puppet/lib/puppet/file_serving/fileset.rb +1 -1
  45. data/vendored/puppet/lib/puppet/file_serving/metadata.rb +2 -2
  46. data/vendored/puppet/lib/puppet/functions.rb +133 -0
  47. data/vendored/puppet/lib/puppet/functions/eyaml_lookup_key.rb +4 -5
  48. data/vendored/puppet/lib/puppet/functions/filter.rb +7 -6
  49. data/vendored/puppet/lib/puppet/functions/new.rb +37 -53
  50. data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
  51. data/vendored/puppet/lib/puppet/functions/yaml_data.rb +4 -5
  52. data/vendored/puppet/lib/puppet/gettext/config.rb +1 -1
  53. data/vendored/puppet/lib/puppet/graph.rb +0 -2
  54. data/vendored/puppet/lib/puppet/indirector/catalog/json.rb +14 -3
  55. data/vendored/puppet/lib/puppet/indirector/catalog/yaml.rb +0 -16
  56. data/vendored/puppet/lib/puppet/indirector/certificate/file.rb +0 -1
  57. data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +4 -2
  58. data/vendored/puppet/lib/puppet/indirector/key/file.rb +1 -6
  59. data/vendored/puppet/lib/puppet/indirector/node/exec.rb +1 -3
  60. data/vendored/puppet/lib/puppet/indirector/node/yaml.rb +0 -6
  61. data/vendored/puppet/lib/puppet/indirector/request.rb +1 -1
  62. data/vendored/puppet/lib/puppet/indirector/ssl_file.rb +3 -44
  63. data/vendored/puppet/lib/puppet/indirector/yaml.rb +4 -4
  64. data/vendored/puppet/lib/puppet/info_service/task_information_service.rb +7 -3
  65. data/vendored/puppet/lib/puppet/loaders.rb +1 -0
  66. data/vendored/puppet/lib/puppet/module/task.rb +198 -29
  67. data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  68. data/vendored/puppet/lib/puppet/network/format_support.rb +13 -8
  69. data/vendored/puppet/lib/puppet/network/formats.rb +93 -2
  70. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +10 -3
  71. data/vendored/puppet/lib/puppet/node/facts.rb +11 -1
  72. data/vendored/puppet/lib/puppet/parser/catalog_compiler.rb +56 -0
  73. data/vendored/puppet/lib/puppet/parser/compiler.rb +3 -1
  74. data/vendored/puppet/lib/puppet/parser/functions.rb +3 -1
  75. data/vendored/puppet/lib/puppet/parser/functions/filter.rb +1 -1
  76. data/vendored/puppet/lib/puppet/parser/functions/generate.rb +1 -1
  77. data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +12 -1
  78. data/vendored/puppet/lib/puppet/parser/functions/tagged.rb +1 -4
  79. data/vendored/puppet/lib/puppet/parser/scope.rb +1 -1
  80. data/vendored/puppet/lib/puppet/parser/script_compiler.rb +7 -2
  81. data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  82. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +23 -4
  83. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +3 -4
  84. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +4 -0
  85. data/vendored/puppet/lib/puppet/pops/issues.rb +8 -0
  86. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +2 -2
  87. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +3 -1
  88. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +30 -9
  89. data/vendored/puppet/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +62 -0
  90. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -1
  91. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +13 -70
  92. data/vendored/puppet/lib/puppet/pops/loaders.rb +19 -29
  93. data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +1 -1
  94. data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +4 -1
  95. data/vendored/puppet/lib/puppet/pops/pcore.rb +10 -33
  96. data/vendored/puppet/lib/puppet/pops/serialization.rb +2 -0
  97. data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +2 -1
  98. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +11 -3
  99. data/vendored/puppet/lib/puppet/pops/serialization/to_stringified_converter.rb +226 -0
  100. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
  101. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +97 -47
  102. data/vendored/puppet/lib/puppet/pops/validation/validator_factory_4_0.rb +7 -8
  103. data/vendored/puppet/lib/puppet/property/keyvalue.rb +70 -8
  104. data/vendored/puppet/lib/puppet/provider/aix_object.rb +483 -0
  105. data/vendored/puppet/lib/puppet/provider/file/windows.rb +1 -1
  106. data/vendored/puppet/lib/puppet/provider/group/aix.rb +51 -112
  107. data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
  108. data/vendored/puppet/lib/puppet/provider/package/pip.rb +1 -1
  109. data/vendored/puppet/lib/puppet/provider/package/puppet_gem.rb +1 -1
  110. data/vendored/puppet/lib/puppet/provider/package/rpm.rb +1 -1
  111. data/vendored/puppet/lib/puppet/provider/package/windows/package.rb +1 -1
  112. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +1 -1
  113. data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
  114. data/vendored/puppet/lib/puppet/provider/service/windows.rb +37 -40
  115. data/vendored/puppet/lib/puppet/provider/user/aix.rb +142 -254
  116. data/vendored/puppet/lib/puppet/resource.rb +20 -3
  117. data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -12
  118. data/vendored/puppet/lib/puppet/rest/routes.rb +97 -34
  119. data/vendored/puppet/lib/puppet/settings.rb +1 -1
  120. data/vendored/puppet/lib/puppet/settings/file_setting.rb +1 -1
  121. data/vendored/puppet/lib/puppet/ssl/base.rb +1 -9
  122. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +1 -13
  123. data/vendored/puppet/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
  124. data/vendored/puppet/lib/puppet/ssl/host.rb +114 -232
  125. data/vendored/puppet/lib/puppet/ssl/key.rb +1 -5
  126. data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
  127. data/vendored/puppet/lib/puppet/test/test_helper.rb +0 -4
  128. data/vendored/puppet/lib/puppet/transaction/event.rb +3 -7
  129. data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
  130. data/vendored/puppet/lib/puppet/type/exec.rb +18 -16
  131. data/vendored/puppet/lib/puppet/type/file.rb +3 -3
  132. data/vendored/puppet/lib/puppet/type/file/source.rb +20 -7
  133. data/vendored/puppet/lib/puppet/type/group.rb +3 -5
  134. data/vendored/puppet/lib/puppet/type/notify.rb +1 -1
  135. data/vendored/puppet/lib/puppet/type/package.rb +2 -5
  136. data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
  137. data/vendored/puppet/lib/puppet/type/service.rb +3 -6
  138. data/vendored/puppet/lib/puppet/type/tidy.rb +1 -1
  139. data/vendored/puppet/lib/puppet/type/user.rb +13 -20
  140. data/vendored/puppet/lib/puppet/util.rb +8 -9
  141. data/vendored/puppet/lib/puppet/util/execution.rb +3 -3
  142. data/vendored/puppet/lib/puppet/util/feature.rb +61 -39
  143. data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
  144. data/vendored/puppet/lib/puppet/util/rdoc.rb +1 -1
  145. data/vendored/puppet/lib/puppet/util/run_mode.rb +1 -1
  146. data/vendored/puppet/lib/puppet/util/storage.rb +1 -1
  147. data/vendored/puppet/lib/puppet/util/suidmanager.rb +7 -5
  148. data/vendored/puppet/lib/puppet/util/tag_set.rb +1 -1
  149. data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
  150. data/vendored/puppet/lib/puppet/util/windows.rb +18 -2
  151. data/vendored/puppet/lib/puppet/util/windows/adsi.rb +154 -205
  152. data/vendored/puppet/lib/puppet/util/windows/service.rb +770 -0
  153. data/vendored/puppet/lib/puppet/util/yaml.rb +41 -5
  154. data/vendored/puppet/lib/puppet/version.rb +1 -1
  155. data/vendored/puppet/lib/puppet_pal.rb +280 -24
  156. metadata +8 -38
  157. data/lib/bolt/catalog/compiler.rb +0 -48
  158. data/lib/bolt/catalog/loaders.rb +0 -19
  159. data/vendored/puppet/lib/puppet/application/ca.rb +0 -11
  160. data/vendored/puppet/lib/puppet/application/certificate.rb +0 -17
  161. data/vendored/puppet/lib/puppet/application/certificate_request.rb +0 -7
  162. data/vendored/puppet/lib/puppet/application/certificate_revocation_list.rb +0 -7
  163. data/vendored/puppet/lib/puppet/face/ca.rb +0 -266
  164. data/vendored/puppet/lib/puppet/face/certificate.rb +0 -167
  165. data/vendored/puppet/lib/puppet/face/certificate_request.rb +0 -56
  166. data/vendored/puppet/lib/puppet/face/certificate_revocation_list.rb +0 -56
  167. data/vendored/puppet/lib/puppet/graph/random_prioritizer.rb +0 -16
  168. data/vendored/puppet/lib/puppet/graph/title_hash_prioritizer.rb +0 -16
  169. data/vendored/puppet/lib/puppet/indirector/certificate/ca.rb +0 -9
  170. data/vendored/puppet/lib/puppet/indirector/certificate/disabled_ca.rb +0 -22
  171. data/vendored/puppet/lib/puppet/indirector/certificate_request/ca.rb +0 -22
  172. data/vendored/puppet/lib/puppet/indirector/certificate_request/disabled_ca.rb +0 -22
  173. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/ca.rb +0 -8
  174. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/disabled_ca.rb +0 -22
  175. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/file.rb +0 -8
  176. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/rest.rb +0 -11
  177. data/vendored/puppet/lib/puppet/indirector/certificate_status.rb +0 -4
  178. data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +0 -91
  179. data/vendored/puppet/lib/puppet/indirector/certificate_status/rest.rb +0 -11
  180. data/vendored/puppet/lib/puppet/indirector/key/ca.rb +0 -16
  181. data/vendored/puppet/lib/puppet/indirector/key/disabled_ca.rb +0 -22
  182. data/vendored/puppet/lib/puppet/indirector/ldap.rb +0 -86
  183. data/vendored/puppet/lib/puppet/indirector/node/ldap.rb +0 -275
  184. data/vendored/puppet/lib/puppet/provider/aixobject.rb +0 -392
  185. data/vendored/puppet/lib/puppet/provider/cron/crontab.rb +0 -297
  186. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +0 -475
  187. data/vendored/puppet/lib/puppet/ssl/certificate_authority/autosign_command.rb +0 -45
  188. data/vendored/puppet/lib/puppet/ssl/certificate_authority/interface.rb +0 -324
  189. data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +0 -219
  190. data/vendored/puppet/lib/puppet/ssl/certificate_revocation_list.rb +0 -111
  191. data/vendored/puppet/lib/puppet/ssl/inventory.rb +0 -55
  192. data/vendored/puppet/lib/puppet/type/cron.rb +0 -480
@@ -1,45 +0,0 @@
1
- require 'puppet/ssl/certificate_authority'
2
- require 'puppet/file_system/uniquefile'
3
-
4
- # This class wraps a given command and invokes it with a CSR name and body to
5
- # determine if the given CSR should be autosigned
6
- #
7
- # @api private
8
- class Puppet::SSL::CertificateAuthority::AutosignCommand
9
-
10
- class CheckFailure < Puppet::Error; end
11
-
12
- def initialize(path)
13
- @path = path
14
- end
15
-
16
- # Run the autosign command with the given CSR name as an argument and the
17
- # CSR body on stdin.
18
- #
19
- # @param csr [String] The CSR name to check for autosigning
20
- # @return [true, false] If the CSR should be autosigned
21
- def allowed?(csr)
22
- name = csr.name
23
- cmd = [@path, name]
24
-
25
- output = Puppet::FileSystem::Uniquefile.open_tmp('puppet-csr') do |csr_file|
26
- csr_file.write(csr.to_s)
27
- csr_file.flush
28
-
29
- execute_options = {:stdinfile => csr_file.path, :combine => true, :failonfail => false}
30
- Puppet::Util::Execution.execute(cmd, execute_options)
31
- end
32
-
33
- output.chomp!
34
-
35
- Puppet.debug "Autosign command '#{@path}' exit status: #{output.exitstatus}"
36
- Puppet.debug "Autosign command '#{@path}' output: #{output}"
37
-
38
- case output.exitstatus
39
- when 0
40
- true
41
- else
42
- false
43
- end
44
- end
45
- end
@@ -1,324 +0,0 @@
1
- module Puppet
2
- module SSL
3
- class CertificateAuthority
4
- # This class is basically a hidden class that knows how to act on the
5
- # CA. Its job is to provide a CLI-like interface to the CA class.
6
- class Interface
7
- INTERFACE_METHODS = [:destroy, :list, :revoke, :generate, :sign, :print, :verify, :fingerprint, :reinventory]
8
- DESTRUCTIVE_METHODS = [:destroy, :revoke]
9
- SUBJECTLESS_METHODS = [:list, :reinventory]
10
-
11
- CERT_STATUS_GLYPHS = {:signed => '+', :request => ' ', :invalid => '-'}
12
- VALID_CONFIRMATION_VALUES = %w{y Y yes Yes YES}
13
-
14
- class InterfaceError < ArgumentError; end
15
-
16
- attr_reader :method, :subjects, :digest, :options
17
-
18
- # Actually perform the work.
19
- def apply(ca)
20
- unless subjects || SUBJECTLESS_METHODS.include?(method)
21
- raise ArgumentError, _("You must provide hosts or --all when using %{method}") % { method: method }
22
- end
23
-
24
- destructive_subjects = [:signed, :all].include?(subjects)
25
- if DESTRUCTIVE_METHODS.include?(method) && destructive_subjects
26
- subject_text = (subjects == :all ? subjects : _("all signed"))
27
- raise ArgumentError, _("Refusing to %{method} %{subject_text} certs, provide an explicit list of certs to %{method}") % { method: method, subject_text: subject_text }
28
- end
29
-
30
- # if the interface implements the method, use it instead of the ca's method
31
- if respond_to?(method)
32
- send(method, ca)
33
- else
34
- (subjects == :all ? ca.list : subjects).each do |host|
35
- ca.send(method, host)
36
- end
37
- end
38
- end
39
-
40
- def generate(ca)
41
- raise InterfaceError, _("It makes no sense to generate all hosts; you must specify a list") if subjects == :all
42
-
43
- subjects.each do |host|
44
- ca.generate(host, options)
45
- end
46
- end
47
-
48
- def initialize(method, options)
49
- self.method = method
50
- self.subjects = options.delete(:to)
51
- @digest = options.delete(:digest)
52
- @options = options
53
- end
54
-
55
- # List the hosts.
56
- def list(ca)
57
- signed = ca.list if [:signed, :all].include?(subjects)
58
- requests = ca.waiting?
59
-
60
- case subjects
61
- when :all
62
- hosts = [signed, requests].flatten
63
- when :signed
64
- hosts = signed.flatten
65
- when nil
66
- hosts = requests
67
- else
68
- hosts = subjects
69
- signed = ca.list(hosts)
70
- end
71
-
72
- certs = {:signed => {}, :invalid => {}, :request => {}}
73
-
74
- return if hosts.empty?
75
-
76
- hosts.uniq.sort.each do |host|
77
- verify_error = nil
78
-
79
- begin
80
- ca.verify(host) unless requests.include?(host)
81
- rescue Puppet::SSL::CertificateAuthority::CertificateVerificationError => details
82
- verify_error = "(#{details.to_s})"
83
- end
84
-
85
- if verify_error
86
- type = :invalid
87
- cert = Puppet::SSL::Certificate.indirection.find(host)
88
- elsif (signed and signed.include?(host))
89
- type = :signed
90
- cert = Puppet::SSL::Certificate.indirection.find(host)
91
- else
92
- type = :request
93
- cert = Puppet::SSL::CertificateRequest.indirection.find(host)
94
- end
95
-
96
- certs[type][host] = {
97
- :cert => cert,
98
- :type => type,
99
- :verify_error => verify_error,
100
- }
101
- end
102
-
103
- names = certs.values.map(&:keys).flatten
104
-
105
- name_width = names.sort_by(&:length).last.length rescue 0
106
- # We quote these names, so account for those characters
107
- name_width += 2
108
-
109
- output = [:request, :signed, :invalid].map do |type|
110
- next if certs[type].empty?
111
-
112
- certs[type].map do |host, info|
113
- format_host(host, info, name_width, options[:format])
114
- end
115
- end.flatten.compact.sort.join("\n")
116
-
117
- puts output
118
- end
119
-
120
- def format_host(host, info, width, format)
121
- case format
122
- when :machine
123
- machine_host_formatting(host, info)
124
- when :human
125
- human_host_formatting(host, info)
126
- else
127
- if options[:verbose]
128
- machine_host_formatting(host, info)
129
- else
130
- legacy_host_formatting(host, info, width)
131
- end
132
- end
133
- end
134
-
135
- def machine_host_formatting(host, info)
136
- type = info[:type]
137
- verify_error = info[:verify_error]
138
- cert = info[:cert]
139
- alt_names = cert.subject_alt_names - [host]
140
- extensions = format_attrs_and_exts(cert)
141
-
142
- glyph = CERT_STATUS_GLYPHS[type]
143
- name = host.inspect
144
- fingerprint = cert.digest(@digest).to_s
145
-
146
- expiration = cert.expiration.iso8601 if type == :signed
147
-
148
- if type != :invalid
149
- if !alt_names.empty?
150
- extensions.unshift("alt names: #{alt_names.map(&:inspect).join(', ')}")
151
- end
152
-
153
- if !extensions.empty?
154
- metadata_string = "(#{extensions.join(', ')})" unless extensions.empty?
155
- end
156
- end
157
-
158
- [glyph, name, fingerprint, expiration, metadata_string, verify_error].compact.join(' ')
159
- end
160
-
161
- def human_host_formatting(host, info)
162
- type = info[:type]
163
- verify_error = info[:verify_error]
164
- cert = info[:cert]
165
- alt_names = cert.subject_alt_names - [host]
166
- extensions = format_attrs_and_exts(cert)
167
-
168
- glyph = CERT_STATUS_GLYPHS[type]
169
- fingerprint = cert.digest(@digest).to_s
170
-
171
- if type == :invalid || (extensions.empty? && alt_names.empty?)
172
- extension_string = ''
173
- else
174
- if !alt_names.empty?
175
- extensions.unshift("alt names: #{alt_names.map(&:inspect).join(', ')}")
176
- end
177
-
178
- extension_string = "\n Extensions:\n "
179
- extension_string << extensions.join("\n ")
180
- end
181
-
182
- if type == :signed
183
- expiration_string = "\n Expiration: #{cert.expiration.iso8601}"
184
- else
185
- expiration_string = ''
186
- end
187
-
188
- status = case type
189
- when :invalid then "Invalid - #{verify_error}"
190
- when :request then "Request Pending"
191
- when :signed then "Signed"
192
- end
193
-
194
- output = "#{glyph} #{host.inspect}"
195
- output << "\n #{fingerprint}"
196
- output << "\n Status: #{status}"
197
- output << expiration_string
198
- output << extension_string
199
- output << "\n"
200
-
201
- output
202
- end
203
-
204
- def legacy_host_formatting(host, info, width)
205
- type = info[:type]
206
- verify_error = info[:verify_error]
207
- cert = info[:cert]
208
- alt_names = cert.subject_alt_names - [host]
209
- extensions = format_attrs_and_exts(cert)
210
-
211
- glyph = CERT_STATUS_GLYPHS[type]
212
- name = host.inspect.ljust(width)
213
- fingerprint = cert.digest(@digest).to_s
214
-
215
- if type != :invalid
216
- if alt_names.empty?
217
- alt_name_string = nil
218
- else
219
- alt_name_string = "(alt names: #{alt_names.map(&:inspect).join(', ')})"
220
- end
221
-
222
- if extensions.empty?
223
- extension_string = nil
224
- else
225
- extension_string = "**"
226
- end
227
- end
228
-
229
- [glyph, name, fingerprint, alt_name_string, verify_error, extension_string].compact.join(' ')
230
- end
231
-
232
- def format_attrs_and_exts(cert)
233
- exts = []
234
- exts += cert.custom_extensions if cert.respond_to?(:custom_extensions)
235
- exts += cert.custom_attributes if cert.respond_to?(:custom_attributes)
236
- exts += cert.request_extensions if cert.respond_to?(:request_extensions)
237
-
238
- exts.map {|e| "#{e['oid']}: #{e['value'].inspect}" }.sort
239
- end
240
-
241
- # Set the method to apply.
242
- def method=(method)
243
- raise ArgumentError, "Invalid method #{method} to apply" unless INTERFACE_METHODS.include?(method)
244
- @method = method
245
- end
246
-
247
- # Print certificate information.
248
- def print(ca)
249
- (subjects == :all ? ca.list : subjects).each do |host|
250
- if value = ca.print(host)
251
- puts value
252
- else
253
- raise ArgumentError, _("Could not find certificate for %{host}") % { host: host }
254
- end
255
- end
256
- end
257
-
258
- # Print certificate information.
259
- def fingerprint(ca)
260
- (subjects == :all ? ca.list + ca.waiting?: subjects).each do |host|
261
- if cert = (Puppet::SSL::Certificate.indirection.find(host) || Puppet::SSL::CertificateRequest.indirection.find(host))
262
- puts "#{host} #{cert.digest(@digest)}"
263
- else
264
- raise ArgumentError, _("Could not find certificate for %{host}") % { host: host }
265
- end
266
- end
267
- end
268
-
269
- # Signs given certificates or all waiting if subjects == :all
270
- def sign(ca)
271
- list = subjects == :all ? ca.waiting? : subjects
272
- raise InterfaceError, _("No waiting certificate requests to sign") if list.empty?
273
-
274
- signing_options = options.select { |k,_|
275
- [:allow_authorization_extensions, :allow_dns_alt_names].include?(k)
276
- }
277
-
278
- list.each do |host|
279
- cert = Puppet::SSL::CertificateRequest.indirection.find(host)
280
-
281
- raise InterfaceError, _("Could not find CSR for: %{host}.") % { host: host.inspect } unless cert
282
-
283
- # ca.sign will also do this - and it should if it is called
284
- # elsewhere - but we want to reject an attempt to sign a
285
- # problematic csr as early as possible for usability concerns.
286
- ca.check_internal_signing_policies(host, cert, signing_options)
287
-
288
- name_width = host.inspect.length
289
- info = {:type => :request, :cert => cert}
290
- host_string = format_host(host, info, name_width, options[:format])
291
- puts _("Signing Certificate Request for:\n%{host_string}") % { host_string: host_string }
292
-
293
- if options[:interactive]
294
- STDOUT.print _("Sign Certificate Request? [y/N] ")
295
-
296
- if !options[:yes]
297
- input = STDIN.gets.chomp
298
- raise InterfaceError, _("NOT Signing Certificate Request") unless VALID_CONFIRMATION_VALUES.include?(input)
299
- else
300
- puts _("Assuming YES from `-y' or `--assume-yes' flag")
301
- end
302
- end
303
-
304
- ca.sign(host, signing_options)
305
- end
306
- end
307
-
308
- def reinventory(ca)
309
- ca.inventory.rebuild
310
- end
311
-
312
- # Set the list of hosts we're operating on. Also supports keywords.
313
- def subjects=(value)
314
- unless value == :all || value == :signed || value.is_a?(Array)
315
- raise ArgumentError, _("Subjects must be an array or :all; not %{value}") % { value: value }
316
- end
317
-
318
- @subjects = (value == []) ? nil : value
319
- end
320
- end
321
- end
322
- end
323
- end
324
-
@@ -1,219 +0,0 @@
1
- require 'puppet/ssl'
2
-
3
- # This class encapsulates the logic of creating and adding extensions to X509
4
- # certificates.
5
- #
6
- # @api private
7
- module Puppet::SSL::CertificateFactory
8
-
9
- # Create a new X509 certificate and add any needed extensions to the cert.
10
- #
11
- # @param cert_type [Symbol] The certificate type to create, which specifies
12
- # what extensions are added to the certificate.
13
- # One of (:ca, :terminalsubca, :server, :ocsp, :client)
14
- # @param csr [Puppet::SSL::CertificateRequest] The signing request associated with
15
- # the certificate being created.
16
- # @param issuer [OpenSSL::X509::Certificate, OpenSSL::X509::Request] An X509 CSR
17
- # if this is a self signed certificate, or the X509 certificate of the CA if
18
- # this is a CA signed certificate.
19
- # @param serial [Integer] The serial number for the given certificate, which
20
- # MUST be unique for the given CA.
21
- # @param ttl [String] The duration of the validity for the given certificate.
22
- # defaults to Puppet[:ca_ttl]
23
- #
24
- # @api public
25
- #
26
- # @return [OpenSSL::X509::Certificate]
27
- def self.build(cert_type, csr, issuer, serial, ttl = nil)
28
- # Work out if we can even build the requested type of certificate.
29
- build_extensions = "build_#{cert_type.to_s}_extensions"
30
- respond_to?(build_extensions) or
31
- raise ArgumentError, _("%{cert_type} is an invalid certificate type!") % { cert_type: cert_type.to_s }
32
-
33
- raise ArgumentError, _("Certificate TTL must be an integer") unless ttl.nil? || ttl.is_a?(Integer)
34
-
35
- # set up the certificate, and start building the content.
36
- cert = OpenSSL::X509::Certificate.new
37
-
38
- cert.version = 2 # X509v3
39
- cert.subject = csr.content.subject
40
- cert.issuer = issuer.subject
41
- cert.public_key = csr.content.public_key
42
- cert.serial = serial
43
-
44
- # Make the certificate valid as of yesterday, because so many people's
45
- # clocks are out of sync. This gives one more day of validity than people
46
- # might expect, but is better than making every person who has a messed up
47
- # clock fail, and better than having every cert we generate expire a day
48
- # before the user expected it to when they asked for "one year".
49
- cert.not_before = Time.now - (60*60*24)
50
- cert.not_after = Time.now + (ttl || Puppet[:ca_ttl])
51
-
52
- add_extensions_to(cert, csr, issuer, send(build_extensions))
53
-
54
- return cert
55
- end
56
-
57
- # Add X509v3 extensions to the given certificate.
58
- #
59
- # @param cert [OpenSSL::X509::Certificate] The certificate to add the
60
- # extensions to.
61
- # @param csr [OpenSSL::X509::Request] The CSR associated with the given
62
- # certificate, which may specify requested extensions for the given cert.
63
- # See https://tools.ietf.org/html/rfc2985 Section 5.4.2 Extension request
64
- # @param issuer [OpenSSL::X509::Certificate, OpenSSL::X509::Request] An X509 CSR
65
- # if this is a self signed certificate, or the X509 certificate of the CA if
66
- # this is a CA signed certificate.
67
- # @param extensions [Hash<String, Array<String> | String>] The extensions to
68
- # add to the certificate, based on the certificate type being created (CA,
69
- # server, client, etc)
70
- #
71
- # @api private
72
- #
73
- # @return [void]
74
- def self.add_extensions_to(cert, csr, issuer, extensions)
75
- ef = OpenSSL::X509::ExtensionFactory.new
76
- ef.subject_certificate = cert
77
- ef.issuer_certificate = issuer.is_a?(OpenSSL::X509::Request) ? cert : issuer
78
-
79
- # Extract the requested extensions from the CSR.
80
- requested_exts = csr.request_extensions.inject({}) do |hash, re|
81
- hash[re["oid"]] = [re["value"], re["critical"]]
82
- hash
83
- end
84
-
85
- # Produce our final set of extensions. We deliberately order these to
86
- # build the way we want:
87
- # 1. "safe" default values, like the comment, that no one cares about.
88
- # 2. request extensions, from the CSR
89
- # 3. extensions based on the type we are generating
90
- # 4. overrides, which we always want to have in their form
91
- #
92
- # This ordering *is* security-critical, but we want to allow the user
93
- # enough rope to shoot themselves in the foot, if they want to ignore our
94
- # advice and externally approve a CSR that sets the basicConstraints.
95
- #
96
- # Swapping the order of 2 and 3 would ensure that you couldn't slip a
97
- # certificate through where the CA constraint was true, though, if
98
- # something went wrong up there. --daniel 2011-10-11
99
- defaults = { "nsComment" => "Puppet Ruby/OpenSSL Internal Certificate" }
100
-
101
- # See https://www.openssl.org/docs/apps/x509v3_config.html
102
- # for information about the special meanings of 'hash', 'keyid', 'issuer'
103
- override = {
104
- "subjectKeyIdentifier" => "hash",
105
- "authorityKeyIdentifier" => "keyid,issuer"
106
- }
107
-
108
- exts = [defaults, requested_exts, extensions, override].
109
- inject({}) {|ret, val| ret.merge(val) }
110
-
111
- cert.extensions = exts.map do |oid, val|
112
- generate_extension(ef, oid, *val)
113
- end
114
- end
115
- private_class_method :add_extensions_to
116
-
117
- # Woot! We're a CA.
118
- def self.build_ca_extensions
119
- {
120
- # This was accidentally omitted in the previous version of this code: an
121
- # effort was made to add it last, but that actually managed to avoid
122
- # adding it to the certificate at all.
123
- #
124
- # We have some sort of bug, which means that when we add it we get a
125
- # complaint that the issuer keyid can't be fetched, which breaks all
126
- # sorts of things in our test suite and, e.g., bootstrapping the CA.
127
- #
128
- # https://tools.ietf.org/html/rfc5280#section-4.2.1.1 says that, to be a
129
- # conforming CA we MAY omit the field if we are self-signed, which I
130
- # think gives us a pass in the specific case.
131
- #
132
- # It also notes that we MAY derive the ID from the subject and serial
133
- # number of the issuer, or from the key ID, and we definitely have the
134
- # former data, should we want to restore this...
135
- #
136
- # Anyway, preserving this bug means we don't risk breaking anything in
137
- # the field, even though it would be nice to have. --daniel 2011-10-11
138
- #
139
- # "authorityKeyIdentifier" => "keyid:always,issuer:always",
140
- "keyUsage" => [%w{cRLSign keyCertSign}, true],
141
- "basicConstraints" => ["CA:TRUE", true],
142
- }
143
- end
144
-
145
- # We're a terminal CA, probably not self-signed.
146
- def self.build_terminalsubca_extensions
147
- {
148
- "keyUsage" => [%w{cRLSign keyCertSign}, true],
149
- "basicConstraints" => ["CA:TRUE,pathlen:0", true],
150
- }
151
- end
152
-
153
- # We're a normal server.
154
- def self.build_server_extensions
155
- {
156
- "keyUsage" => [%w{digitalSignature keyEncipherment}, true],
157
- "extendedKeyUsage" => [%w{serverAuth clientAuth}, true],
158
- "basicConstraints" => ["CA:FALSE", true],
159
- }
160
- end
161
-
162
- # Um, no idea.
163
- def self.build_ocsp_extensions
164
- {
165
- "keyUsage" => [%w{nonRepudiation digitalSignature}, true],
166
- "extendedKeyUsage" => [%w{serverAuth OCSPSigning}, true],
167
- "basicConstraints" => ["CA:FALSE", true],
168
- }
169
- end
170
-
171
- # Normal client.
172
- def self.build_client_extensions
173
- {
174
- "keyUsage" => [%w{nonRepudiation digitalSignature keyEncipherment}, true],
175
- # We don't seem to use this, but that seems much more reasonable here...
176
- "extendedKeyUsage" => [%w{clientAuth emailProtection}, true],
177
- "basicConstraints" => ["CA:FALSE", true],
178
- "nsCertType" => "client,email",
179
- }
180
- end
181
-
182
- # Generate an extension with the given OID, value, and critical state
183
- #
184
- # @param oid [String] The numeric value or short name of a given OID. X509v3
185
- # extensions must be passed by short name or long name, while custom
186
- # extensions may be passed by short name, long name, oid numeric OID.
187
- # @param ef [OpenSSL::X509::ExtensionFactory] The extension factory to use
188
- # when generating the extension.
189
- # @param val [String, Array<String>] The extension value.
190
- # @param crit [true, false] Whether the given extension is critical, defaults
191
- # to false.
192
- #
193
- # @return [OpenSSL::X509::Extension]
194
- #
195
- # @api private
196
- def self.generate_extension(ef, oid, val, crit = false)
197
-
198
- val = val.join(', ') unless val.is_a? String
199
-
200
- # Enforce the X509v3 rules about subjectAltName being critical:
201
- # specifically, it SHOULD NOT be critical if we have a subject, which we
202
- # always do. --daniel 2011-10-18
203
- crit = false if oid == "subjectAltName"
204
-
205
- if Puppet::SSL::Oids.subtree_of?('id-ce', oid) or Puppet::SSL::Oids.subtree_of?('id-pkix', oid)
206
- # Attempt to create a X509v3 certificate extension. Standard certificate
207
- # extensions may need access to the associated subject certificate and
208
- # issuing certificate, so must be created by the OpenSSL::X509::ExtensionFactory
209
- # which provides that context.
210
- ef.create_ext(oid, val, crit)
211
- else
212
- # This is not an X509v3 extension which means that the extension
213
- # factory cannot generate it. We need to generate the extension
214
- # manually.
215
- OpenSSL::X509::Extension.new(oid, OpenSSL::ASN1::UTF8String.new(val).to_der, crit)
216
- end
217
- end
218
- private_class_method :generate_extension
219
- end