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.
- checksums.yaml +4 -4
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +5 -2
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +5 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -8
- data/lib/bolt/applicator.rb +11 -8
- data/lib/bolt/boltdir.rb +13 -5
- data/lib/bolt/catalog.rb +22 -47
- data/lib/bolt/config.rb +1 -26
- data/lib/bolt/executor.rb +1 -1
- data/lib/bolt/outputter.rb +0 -9
- data/lib/bolt/outputter/human.rb +29 -14
- data/lib/bolt/outputter/json.rb +12 -1
- data/lib/bolt/pal.rb +12 -10
- data/lib/bolt/target.rb +0 -6
- data/lib/bolt/task.rb +53 -10
- data/lib/bolt/transport/base.rb +1 -6
- data/lib/bolt/transport/local.rb +11 -13
- data/lib/bolt/transport/local/shell.rb +2 -2
- data/lib/bolt/transport/ssh.rb +16 -11
- data/lib/bolt/transport/winrm.rb +8 -11
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_ext/schemas/task.json +12 -5
- data/libexec/apply_catalog.rb +3 -1
- data/libexec/bolt_catalog +4 -0
- data/vendored/puppet/lib/puppet.rb +2 -1
- data/vendored/puppet/lib/puppet/application/agent.rb +2 -6
- data/vendored/puppet/lib/puppet/application/apply.rb +100 -60
- data/vendored/puppet/lib/puppet/application/cert.rb +26 -291
- data/vendored/puppet/lib/puppet/application/device.rb +0 -5
- data/vendored/puppet/lib/puppet/application/lookup.rb +1 -1
- data/vendored/puppet/lib/puppet/application/ssl.rb +133 -0
- data/vendored/puppet/lib/puppet/application_support.rb +1 -2
- data/vendored/puppet/lib/puppet/configurer.rb +34 -50
- data/vendored/puppet/lib/puppet/configurer/downloader.rb +1 -1
- data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
- data/vendored/puppet/lib/puppet/daemon.rb +1 -1
- data/vendored/puppet/lib/puppet/defaults.rb +40 -117
- data/vendored/puppet/lib/puppet/face/epp.rb +2 -2
- data/vendored/puppet/lib/puppet/face/help.rb +21 -7
- data/vendored/puppet/lib/puppet/face/node/clean.rb +14 -10
- data/vendored/puppet/lib/puppet/feature/base.rb +7 -23
- data/vendored/puppet/lib/puppet/feature/eventlog.rb +1 -1
- data/vendored/puppet/lib/puppet/file_serving/base.rb +2 -2
- data/vendored/puppet/lib/puppet/file_serving/fileset.rb +1 -1
- data/vendored/puppet/lib/puppet/file_serving/metadata.rb +2 -2
- data/vendored/puppet/lib/puppet/functions.rb +133 -0
- data/vendored/puppet/lib/puppet/functions/eyaml_lookup_key.rb +4 -5
- data/vendored/puppet/lib/puppet/functions/filter.rb +7 -6
- data/vendored/puppet/lib/puppet/functions/new.rb +37 -53
- data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/yaml_data.rb +4 -5
- data/vendored/puppet/lib/puppet/gettext/config.rb +1 -1
- data/vendored/puppet/lib/puppet/graph.rb +0 -2
- data/vendored/puppet/lib/puppet/indirector/catalog/json.rb +14 -3
- data/vendored/puppet/lib/puppet/indirector/catalog/yaml.rb +0 -16
- data/vendored/puppet/lib/puppet/indirector/certificate/file.rb +0 -1
- data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +4 -2
- data/vendored/puppet/lib/puppet/indirector/key/file.rb +1 -6
- data/vendored/puppet/lib/puppet/indirector/node/exec.rb +1 -3
- data/vendored/puppet/lib/puppet/indirector/node/yaml.rb +0 -6
- data/vendored/puppet/lib/puppet/indirector/request.rb +1 -1
- data/vendored/puppet/lib/puppet/indirector/ssl_file.rb +3 -44
- data/vendored/puppet/lib/puppet/indirector/yaml.rb +4 -4
- data/vendored/puppet/lib/puppet/info_service/task_information_service.rb +7 -3
- data/vendored/puppet/lib/puppet/loaders.rb +1 -0
- data/vendored/puppet/lib/puppet/module/task.rb +198 -29
- data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
- data/vendored/puppet/lib/puppet/network/format_support.rb +13 -8
- data/vendored/puppet/lib/puppet/network/formats.rb +93 -2
- data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +10 -3
- data/vendored/puppet/lib/puppet/node/facts.rb +11 -1
- data/vendored/puppet/lib/puppet/parser/catalog_compiler.rb +56 -0
- data/vendored/puppet/lib/puppet/parser/compiler.rb +3 -1
- data/vendored/puppet/lib/puppet/parser/functions.rb +3 -1
- data/vendored/puppet/lib/puppet/parser/functions/filter.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/functions/generate.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +12 -1
- data/vendored/puppet/lib/puppet/parser/functions/tagged.rb +1 -4
- data/vendored/puppet/lib/puppet/parser/scope.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/script_compiler.rb +7 -2
- data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
- data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +23 -4
- data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +3 -4
- data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +4 -0
- data/vendored/puppet/lib/puppet/pops/issues.rb +8 -0
- data/vendored/puppet/lib/puppet/pops/loader/loader.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +3 -1
- data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +30 -9
- data/vendored/puppet/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +62 -0
- data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -1
- data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +13 -70
- data/vendored/puppet/lib/puppet/pops/loaders.rb +19 -29
- data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +4 -1
- data/vendored/puppet/lib/puppet/pops/pcore.rb +10 -33
- data/vendored/puppet/lib/puppet/pops/serialization.rb +2 -0
- data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +2 -1
- data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +11 -3
- data/vendored/puppet/lib/puppet/pops/serialization/to_stringified_converter.rb +226 -0
- data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
- data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +97 -47
- data/vendored/puppet/lib/puppet/pops/validation/validator_factory_4_0.rb +7 -8
- data/vendored/puppet/lib/puppet/property/keyvalue.rb +70 -8
- data/vendored/puppet/lib/puppet/provider/aix_object.rb +483 -0
- data/vendored/puppet/lib/puppet/provider/file/windows.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/group/aix.rb +51 -112
- data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/pip.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/puppet_gem.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/rpm.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/windows/package.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/zypper.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/service/windows.rb +37 -40
- data/vendored/puppet/lib/puppet/provider/user/aix.rb +142 -254
- data/vendored/puppet/lib/puppet/resource.rb +20 -3
- data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -12
- data/vendored/puppet/lib/puppet/rest/routes.rb +97 -34
- data/vendored/puppet/lib/puppet/settings.rb +1 -1
- data/vendored/puppet/lib/puppet/settings/file_setting.rb +1 -1
- data/vendored/puppet/lib/puppet/ssl/base.rb +1 -9
- data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +1 -13
- data/vendored/puppet/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
- data/vendored/puppet/lib/puppet/ssl/host.rb +114 -232
- data/vendored/puppet/lib/puppet/ssl/key.rb +1 -5
- data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
- data/vendored/puppet/lib/puppet/test/test_helper.rb +0 -4
- data/vendored/puppet/lib/puppet/transaction/event.rb +3 -7
- data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
- data/vendored/puppet/lib/puppet/type/exec.rb +18 -16
- data/vendored/puppet/lib/puppet/type/file.rb +3 -3
- data/vendored/puppet/lib/puppet/type/file/source.rb +20 -7
- data/vendored/puppet/lib/puppet/type/group.rb +3 -5
- data/vendored/puppet/lib/puppet/type/notify.rb +1 -1
- data/vendored/puppet/lib/puppet/type/package.rb +2 -5
- data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
- data/vendored/puppet/lib/puppet/type/service.rb +3 -6
- data/vendored/puppet/lib/puppet/type/tidy.rb +1 -1
- data/vendored/puppet/lib/puppet/type/user.rb +13 -20
- data/vendored/puppet/lib/puppet/util.rb +8 -9
- data/vendored/puppet/lib/puppet/util/execution.rb +3 -3
- data/vendored/puppet/lib/puppet/util/feature.rb +61 -39
- data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
- data/vendored/puppet/lib/puppet/util/rdoc.rb +1 -1
- data/vendored/puppet/lib/puppet/util/run_mode.rb +1 -1
- data/vendored/puppet/lib/puppet/util/storage.rb +1 -1
- data/vendored/puppet/lib/puppet/util/suidmanager.rb +7 -5
- data/vendored/puppet/lib/puppet/util/tag_set.rb +1 -1
- data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
- data/vendored/puppet/lib/puppet/util/windows.rb +18 -2
- data/vendored/puppet/lib/puppet/util/windows/adsi.rb +154 -205
- data/vendored/puppet/lib/puppet/util/windows/service.rb +770 -0
- data/vendored/puppet/lib/puppet/util/yaml.rb +41 -5
- data/vendored/puppet/lib/puppet/version.rb +1 -1
- data/vendored/puppet/lib/puppet_pal.rb +280 -24
- metadata +8 -38
- data/lib/bolt/catalog/compiler.rb +0 -48
- data/lib/bolt/catalog/loaders.rb +0 -19
- data/vendored/puppet/lib/puppet/application/ca.rb +0 -11
- data/vendored/puppet/lib/puppet/application/certificate.rb +0 -17
- data/vendored/puppet/lib/puppet/application/certificate_request.rb +0 -7
- data/vendored/puppet/lib/puppet/application/certificate_revocation_list.rb +0 -7
- data/vendored/puppet/lib/puppet/face/ca.rb +0 -266
- data/vendored/puppet/lib/puppet/face/certificate.rb +0 -167
- data/vendored/puppet/lib/puppet/face/certificate_request.rb +0 -56
- data/vendored/puppet/lib/puppet/face/certificate_revocation_list.rb +0 -56
- data/vendored/puppet/lib/puppet/graph/random_prioritizer.rb +0 -16
- data/vendored/puppet/lib/puppet/graph/title_hash_prioritizer.rb +0 -16
- data/vendored/puppet/lib/puppet/indirector/certificate/ca.rb +0 -9
- data/vendored/puppet/lib/puppet/indirector/certificate/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_request/ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_request/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/ca.rb +0 -8
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/file.rb +0 -8
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/rest.rb +0 -11
- data/vendored/puppet/lib/puppet/indirector/certificate_status.rb +0 -4
- data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +0 -91
- data/vendored/puppet/lib/puppet/indirector/certificate_status/rest.rb +0 -11
- data/vendored/puppet/lib/puppet/indirector/key/ca.rb +0 -16
- data/vendored/puppet/lib/puppet/indirector/key/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/ldap.rb +0 -86
- data/vendored/puppet/lib/puppet/indirector/node/ldap.rb +0 -275
- data/vendored/puppet/lib/puppet/provider/aixobject.rb +0 -392
- data/vendored/puppet/lib/puppet/provider/cron/crontab.rb +0 -297
- data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +0 -475
- data/vendored/puppet/lib/puppet/ssl/certificate_authority/autosign_command.rb +0 -45
- data/vendored/puppet/lib/puppet/ssl/certificate_authority/interface.rb +0 -324
- data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +0 -219
- data/vendored/puppet/lib/puppet/ssl/certificate_revocation_list.rb +0 -111
- data/vendored/puppet/lib/puppet/ssl/inventory.rb +0 -55
- 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
|