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,297 +0,0 @@
|
|
1
|
-
require 'puppet/provider/parsedfile'
|
2
|
-
|
3
|
-
Puppet::Type.type(:cron).provide(:crontab, :parent => Puppet::Provider::ParsedFile, :default_target => ENV["USER"] || "root") do
|
4
|
-
commands :crontab => "crontab"
|
5
|
-
|
6
|
-
text_line :comment, :match => %r{^\s*#}, :post_parse => proc { |record|
|
7
|
-
record[:name] = $1 if record[:line] =~ /Puppet Name: (.+)\s*$/
|
8
|
-
}
|
9
|
-
|
10
|
-
text_line :blank, :match => %r{^\s*$}
|
11
|
-
|
12
|
-
text_line :environment, :match => %r{^\s*\w+\s*=}
|
13
|
-
|
14
|
-
def self.filetype
|
15
|
-
tabname = case Facter.value(:osfamily)
|
16
|
-
when "Solaris"
|
17
|
-
:suntab
|
18
|
-
when "AIX"
|
19
|
-
:aixtab
|
20
|
-
else
|
21
|
-
:crontab
|
22
|
-
end
|
23
|
-
|
24
|
-
Puppet::Util::FileType.filetype(tabname)
|
25
|
-
end
|
26
|
-
|
27
|
-
self::TIME_FIELDS = [:minute, :hour, :monthday, :month, :weekday]
|
28
|
-
|
29
|
-
record_line :crontab,
|
30
|
-
:fields => %w{time command},
|
31
|
-
:match => %r{^\s*(@\w+|\S+\s+\S+\s+\S+\s+\S+\s+\S+)\s+(.+)$},
|
32
|
-
:absent => '*',
|
33
|
-
:block_eval => :instance do
|
34
|
-
|
35
|
-
def post_parse(record)
|
36
|
-
time = record.delete(:time)
|
37
|
-
if match = /@(\S+)/.match(time)
|
38
|
-
# is there another way to access the constant?
|
39
|
-
Puppet::Type::Cron::ProviderCrontab::TIME_FIELDS.each { |f| record[f] = :absent }
|
40
|
-
record[:special] = match.captures[0]
|
41
|
-
elsif match = /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/.match(time)
|
42
|
-
record[:special] = :absent
|
43
|
-
Puppet::Type::Cron::ProviderCrontab::TIME_FIELDS.zip(match.captures).each do |field,value|
|
44
|
-
if value == self.absent
|
45
|
-
record[field] = :absent
|
46
|
-
else
|
47
|
-
record[field] = value.split(",")
|
48
|
-
end
|
49
|
-
end
|
50
|
-
else
|
51
|
-
raise Puppet::Error, _("Line got parsed as a crontab entry but cannot be handled. Please file a bug with the contents of your crontab")
|
52
|
-
end
|
53
|
-
record
|
54
|
-
end
|
55
|
-
|
56
|
-
def pre_gen(record)
|
57
|
-
if record[:special] and record[:special] != :absent
|
58
|
-
record[:special] = "@#{record[:special]}"
|
59
|
-
end
|
60
|
-
|
61
|
-
Puppet::Type::Cron::ProviderCrontab::TIME_FIELDS.each do |field|
|
62
|
-
if vals = record[field] and vals.is_a?(Array)
|
63
|
-
record[field] = vals.join(",")
|
64
|
-
end
|
65
|
-
end
|
66
|
-
record
|
67
|
-
end
|
68
|
-
|
69
|
-
def to_line(record)
|
70
|
-
str = ""
|
71
|
-
record[:name] = nil if record[:unmanaged]
|
72
|
-
str = "# Puppet Name: #{record[:name]}\n" if record[:name]
|
73
|
-
if record[:environment] and record[:environment] != :absent
|
74
|
-
str += record[:environment].map {|line| "#{line}\n"}.join('')
|
75
|
-
end
|
76
|
-
if record[:special] and record[:special] != :absent
|
77
|
-
fields = [:special, :command]
|
78
|
-
else
|
79
|
-
fields = Puppet::Type::Cron::ProviderCrontab::TIME_FIELDS + [:command]
|
80
|
-
end
|
81
|
-
str += record.values_at(*fields).map do |field|
|
82
|
-
if field.nil? or field == :absent
|
83
|
-
self.absent
|
84
|
-
else
|
85
|
-
field
|
86
|
-
end
|
87
|
-
end.join(self.joiner)
|
88
|
-
str
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def create
|
93
|
-
if resource.should(:command) then
|
94
|
-
super
|
95
|
-
else
|
96
|
-
resource.err _("no command specified, cannot create")
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
# Look up a resource with a given name whose user matches a record target
|
101
|
-
#
|
102
|
-
# @api private
|
103
|
-
#
|
104
|
-
# @note This overrides the ParsedFile method for finding resources by name,
|
105
|
-
# so that only records for a given user are matched to resources of the
|
106
|
-
# same user so that orphaned records in other crontabs don't get falsely
|
107
|
-
# matched (#2251)
|
108
|
-
#
|
109
|
-
# @param [Hash<Symbol, Object>] record
|
110
|
-
# @param [Array<Puppet::Resource>] resources
|
111
|
-
#
|
112
|
-
# @return [Puppet::Resource, nil] The resource if found, else nil
|
113
|
-
def self.resource_for_record(record, resources)
|
114
|
-
resource = super
|
115
|
-
|
116
|
-
if resource
|
117
|
-
target = resource[:target] || resource[:user]
|
118
|
-
if record[:target] == target
|
119
|
-
resource
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# Return the header placed at the top of each generated file, warning
|
125
|
-
# users that modifying this file manually is probably a bad idea.
|
126
|
-
def self.header
|
127
|
-
%{# HEADER: This file was autogenerated at #{Time.now} by puppet.
|
128
|
-
# HEADER: While it can still be managed manually, it is definitely not recommended.
|
129
|
-
# HEADER: Note particularly that the comments starting with 'Puppet Name' should
|
130
|
-
# HEADER: not be deleted, as doing so could cause duplicate cron jobs.\n}
|
131
|
-
end
|
132
|
-
|
133
|
-
# Regex for finding one vixie cron header.
|
134
|
-
def self.native_header_regex
|
135
|
-
/# DO NOT EDIT THIS FILE.*?Cron version.*?vixie.*?\n/m
|
136
|
-
end
|
137
|
-
|
138
|
-
# If a vixie cron header is found, it should be dropped, cron will insert
|
139
|
-
# a new one in any case, so we need to avoid duplicates.
|
140
|
-
def self.drop_native_header
|
141
|
-
true
|
142
|
-
end
|
143
|
-
|
144
|
-
# See if we can match the record against an existing cron job.
|
145
|
-
def self.match(record, resources)
|
146
|
-
# if the record is named, do not even bother (#19876)
|
147
|
-
# except the resource name was implicitly generated (#3220)
|
148
|
-
return false if record[:name] and !record[:unmanaged]
|
149
|
-
resources.each do |name, resource|
|
150
|
-
# Match the command first, since it's the most important one.
|
151
|
-
next unless record[:target] == resource[:target]
|
152
|
-
next unless record[:command] == resource.value(:command)
|
153
|
-
|
154
|
-
# Now check the time fields
|
155
|
-
compare_fields = self::TIME_FIELDS + [:special]
|
156
|
-
|
157
|
-
matched = true
|
158
|
-
compare_fields.each do |field|
|
159
|
-
# If the resource does not manage a property (say monthday) it should
|
160
|
-
# always match. If it is the other way around (e.g. resource defines
|
161
|
-
# a should value for :special but the record does not have it, we do
|
162
|
-
# not match
|
163
|
-
next unless resource[field]
|
164
|
-
unless record.include?(field)
|
165
|
-
matched = false
|
166
|
-
break
|
167
|
-
end
|
168
|
-
|
169
|
-
if record_value = record[field] and resource_value = resource.value(field)
|
170
|
-
# The record translates '*' into absent in the post_parse hook and
|
171
|
-
# the resource type does exactly the opposite (alias :absent to *)
|
172
|
-
next if resource_value == '*' and record_value == :absent
|
173
|
-
next if resource_value == record_value
|
174
|
-
end
|
175
|
-
matched =false
|
176
|
-
break
|
177
|
-
end
|
178
|
-
return resource if matched
|
179
|
-
end
|
180
|
-
false
|
181
|
-
end
|
182
|
-
|
183
|
-
@name_index = 0
|
184
|
-
|
185
|
-
# Collapse name and env records.
|
186
|
-
def self.prefetch_hook(records)
|
187
|
-
name = nil
|
188
|
-
envs = nil
|
189
|
-
result = records.each { |record|
|
190
|
-
case record[:record_type]
|
191
|
-
when :comment
|
192
|
-
if record[:name]
|
193
|
-
name = record[:name]
|
194
|
-
record[:skip] = true
|
195
|
-
|
196
|
-
# Start collecting env values
|
197
|
-
envs = []
|
198
|
-
end
|
199
|
-
when :environment
|
200
|
-
# If we're collecting env values (meaning we're in a named cronjob),
|
201
|
-
# store the line and skip the record.
|
202
|
-
if envs
|
203
|
-
envs << record[:line]
|
204
|
-
record[:skip] = true
|
205
|
-
end
|
206
|
-
when :blank
|
207
|
-
# nothing
|
208
|
-
else
|
209
|
-
if name
|
210
|
-
record[:name] = name
|
211
|
-
name = nil
|
212
|
-
else
|
213
|
-
cmd_string = record[:command].gsub(/\s+/, "_")
|
214
|
-
index = ( @name_index += 1 )
|
215
|
-
record[:name] = "unmanaged:#{cmd_string}-#{ index.to_s }"
|
216
|
-
record[:unmanaged] = true
|
217
|
-
end
|
218
|
-
if envs.nil? or envs.empty?
|
219
|
-
record[:environment] = :absent
|
220
|
-
else
|
221
|
-
# Collect all of the environment lines, and mark the records to be skipped,
|
222
|
-
# since their data is included in our crontab record.
|
223
|
-
record[:environment] = envs
|
224
|
-
|
225
|
-
# And turn off env collection again
|
226
|
-
envs = nil
|
227
|
-
end
|
228
|
-
end
|
229
|
-
}.reject { |record| record[:skip] }
|
230
|
-
result
|
231
|
-
end
|
232
|
-
|
233
|
-
def self.to_file(records)
|
234
|
-
text = super
|
235
|
-
# Apparently Freebsd will "helpfully" add a new TZ line to every
|
236
|
-
# single cron line, but not in all cases (e.g., it doesn't do it
|
237
|
-
# on my machine). This is my attempt to fix it so the TZ lines don't
|
238
|
-
# multiply.
|
239
|
-
if text =~ /(^TZ=.+\n)/
|
240
|
-
tz = $1
|
241
|
-
text.sub!(tz, '')
|
242
|
-
text = tz + text
|
243
|
-
end
|
244
|
-
text
|
245
|
-
end
|
246
|
-
|
247
|
-
def user=(user)
|
248
|
-
# we have to mark the target as modified first, to make sure that if
|
249
|
-
# we move a cronjob from userA to userB, userA's crontab will also
|
250
|
-
# be rewritten
|
251
|
-
mark_target_modified
|
252
|
-
@property_hash[:user] = user
|
253
|
-
@property_hash[:target] = user
|
254
|
-
end
|
255
|
-
|
256
|
-
def user
|
257
|
-
@property_hash[:user] || @property_hash[:target]
|
258
|
-
end
|
259
|
-
|
260
|
-
CRONTAB_DIR = case Facter.value("osfamily")
|
261
|
-
when "Debian", "HP-UX"
|
262
|
-
"/var/spool/cron/crontabs"
|
263
|
-
when /BSD/
|
264
|
-
"/var/cron/tabs"
|
265
|
-
when "Darwin"
|
266
|
-
"/usr/lib/cron/tabs/"
|
267
|
-
else
|
268
|
-
"/var/spool/cron"
|
269
|
-
end
|
270
|
-
|
271
|
-
# Yield the names of all crontab files stored on the local system.
|
272
|
-
#
|
273
|
-
# @note Ignores files that are not writable for the puppet process.
|
274
|
-
#
|
275
|
-
# @api private
|
276
|
-
def self.enumerate_crontabs
|
277
|
-
Puppet.debug "looking for crontabs in #{CRONTAB_DIR}"
|
278
|
-
return unless File.readable?(CRONTAB_DIR)
|
279
|
-
Dir.foreach(CRONTAB_DIR) do |file|
|
280
|
-
path = "#{CRONTAB_DIR}/#{file}"
|
281
|
-
yield(file) if File.file?(path) and File.writable?(path)
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
|
286
|
-
# Include all plausible crontab files on the system
|
287
|
-
# in the list of targets (#11383 / PUP-1381)
|
288
|
-
def self.targets(resources = nil)
|
289
|
-
targets = super(resources)
|
290
|
-
enumerate_crontabs do |target|
|
291
|
-
targets << target
|
292
|
-
end
|
293
|
-
targets.uniq
|
294
|
-
end
|
295
|
-
|
296
|
-
end
|
297
|
-
|
@@ -1,475 +0,0 @@
|
|
1
|
-
require 'puppet/ssl/host'
|
2
|
-
require 'puppet/ssl/certificate_request'
|
3
|
-
require 'puppet/ssl/certificate_signer'
|
4
|
-
require 'puppet/util'
|
5
|
-
|
6
|
-
# The class that knows how to sign certificates. It creates
|
7
|
-
# a 'special' SSL::Host whose name is 'ca', thus indicating
|
8
|
-
# that, well, it's the CA. There's some magic in the
|
9
|
-
# indirector/ssl_file terminus base class that does that
|
10
|
-
# for us.
|
11
|
-
# This class mostly just signs certs for us, but
|
12
|
-
# it can also be seen as a general interface into all of the
|
13
|
-
# SSL stuff.
|
14
|
-
class Puppet::SSL::CertificateAuthority
|
15
|
-
# We will only sign extensions on this whitelist, ever. Any CSR with a
|
16
|
-
# requested extension that we don't recognize is rejected, against the risk
|
17
|
-
# that it will introduce some security issue through our ignorance of it.
|
18
|
-
#
|
19
|
-
# Adding an extension to this whitelist simply means we will consider it
|
20
|
-
# further, not that we will always accept a certificate with an extension
|
21
|
-
# requested on this list.
|
22
|
-
RequestExtensionWhitelist = %w{subjectAltName}
|
23
|
-
|
24
|
-
require 'puppet/ssl/certificate_factory'
|
25
|
-
require 'puppet/ssl/inventory'
|
26
|
-
require 'puppet/ssl/certificate_revocation_list'
|
27
|
-
require 'puppet/ssl/certificate_authority/interface'
|
28
|
-
require 'puppet/ssl/certificate_authority/autosign_command'
|
29
|
-
require 'puppet/network/authstore'
|
30
|
-
|
31
|
-
class CertificateVerificationError < RuntimeError
|
32
|
-
attr_accessor :error_code
|
33
|
-
|
34
|
-
def initialize(code)
|
35
|
-
@error_code = code
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.singleton_instance
|
40
|
-
@singleton_instance ||= new
|
41
|
-
end
|
42
|
-
|
43
|
-
class CertificateSigningError < RuntimeError
|
44
|
-
attr_accessor :host
|
45
|
-
|
46
|
-
def initialize(host)
|
47
|
-
@host = host
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.ca?
|
52
|
-
# running as ca? - ensure boolean answer
|
53
|
-
!!(Puppet[:ca] && Puppet.run_mode.master?)
|
54
|
-
end
|
55
|
-
|
56
|
-
# If this process can function as a CA, then return a singleton instance.
|
57
|
-
def self.instance
|
58
|
-
ca? ? singleton_instance : nil
|
59
|
-
end
|
60
|
-
|
61
|
-
attr_reader :name, :host
|
62
|
-
|
63
|
-
# If autosign is configured, autosign the csr we are passed.
|
64
|
-
# @param csr [Puppet::SSL::CertificateRequest] The csr to sign.
|
65
|
-
# @return [Void]
|
66
|
-
# @api private
|
67
|
-
def autosign(csr)
|
68
|
-
if autosign?(csr)
|
69
|
-
Puppet.info _("Autosigning %{csr}") % { csr: csr.name }
|
70
|
-
sign(csr.name)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Determine if a CSR can be autosigned by the autosign store or autosign command
|
75
|
-
#
|
76
|
-
# @param csr [Puppet::SSL::CertificateRequest] The CSR to check
|
77
|
-
# @return [true, false]
|
78
|
-
# @api private
|
79
|
-
def autosign?(csr)
|
80
|
-
auto = Puppet[:autosign]
|
81
|
-
|
82
|
-
decider = case auto
|
83
|
-
when false
|
84
|
-
AutosignNever.new
|
85
|
-
when true
|
86
|
-
AutosignAlways.new
|
87
|
-
else
|
88
|
-
file = Puppet::FileSystem.pathname(auto)
|
89
|
-
if Puppet::FileSystem.executable?(file)
|
90
|
-
Puppet::SSL::CertificateAuthority::AutosignCommand.new(auto)
|
91
|
-
elsif Puppet::FileSystem.exist?(file)
|
92
|
-
AutosignConfig.new(file)
|
93
|
-
else
|
94
|
-
AutosignNever.new
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
decider.allowed?(csr)
|
99
|
-
end
|
100
|
-
|
101
|
-
# Retrieves (or creates, if necessary) the certificate revocation list.
|
102
|
-
def crl
|
103
|
-
unless defined?(@crl)
|
104
|
-
unless @crl = Puppet::SSL::CertificateRevocationList.indirection.find(Puppet::SSL::CA_NAME)
|
105
|
-
@crl = Puppet::SSL::CertificateRevocationList.new(Puppet::SSL::CA_NAME)
|
106
|
-
@crl.generate(host.certificate.content, host.key.content)
|
107
|
-
Puppet::SSL::CertificateRevocationList.indirection.save(@crl)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
@crl
|
111
|
-
end
|
112
|
-
|
113
|
-
# Delegates this to our Host class.
|
114
|
-
def destroy(name)
|
115
|
-
Puppet::SSL::Host.destroy(name)
|
116
|
-
end
|
117
|
-
|
118
|
-
# Generates a new certificate.
|
119
|
-
# @return Puppet::SSL::Certificate
|
120
|
-
def generate(name, options = {})
|
121
|
-
raise ArgumentError, _("A Certificate already exists for %{name}") % { name: name } if Puppet::SSL::Certificate.indirection.find(name)
|
122
|
-
|
123
|
-
# Pass on any requested subjectAltName field.
|
124
|
-
san = options[:dns_alt_names]
|
125
|
-
|
126
|
-
host = Puppet::SSL::Host.new(name)
|
127
|
-
host.generate_certificate_request(:dns_alt_names => san)
|
128
|
-
# CSR may have been implicitly autosigned, generating a certificate
|
129
|
-
# Or sign explicitly
|
130
|
-
host.certificate || sign(name, {allow_dns_alt_names: !!san})
|
131
|
-
end
|
132
|
-
|
133
|
-
# Generate our CA certificate.
|
134
|
-
def generate_ca_certificate
|
135
|
-
generate_password unless password?
|
136
|
-
|
137
|
-
host.generate_key unless host.key
|
138
|
-
|
139
|
-
# Create a new cert request. We do this specially, because we don't want
|
140
|
-
# to actually save the request anywhere.
|
141
|
-
request = Puppet::SSL::CertificateRequest.new(host.name)
|
142
|
-
|
143
|
-
# We deliberately do not put any subjectAltName in here: the CA
|
144
|
-
# certificate absolutely does not need them. --daniel 2011-10-13
|
145
|
-
request.generate(host.key)
|
146
|
-
|
147
|
-
# Create a self-signed certificate.
|
148
|
-
@certificate = sign(host.name, {allow_dns_alt_names: false,
|
149
|
-
self_signing_csr: request})
|
150
|
-
|
151
|
-
# And make sure we initialize our CRL.
|
152
|
-
crl
|
153
|
-
end
|
154
|
-
|
155
|
-
def initialize
|
156
|
-
Puppet.settings.use :main, :ssl, :ca
|
157
|
-
|
158
|
-
@name = Puppet[:certname]
|
159
|
-
|
160
|
-
@host = Puppet::SSL::Host.new(Puppet::SSL::Host.ca_name)
|
161
|
-
|
162
|
-
setup
|
163
|
-
end
|
164
|
-
|
165
|
-
# Retrieve (or create, if necessary) our inventory manager.
|
166
|
-
def inventory
|
167
|
-
@inventory ||= Puppet::SSL::Inventory.new
|
168
|
-
end
|
169
|
-
|
170
|
-
# Generate a new password for the CA.
|
171
|
-
def generate_password
|
172
|
-
pass = ""
|
173
|
-
20.times { pass += (rand(74) + 48).chr }
|
174
|
-
|
175
|
-
begin
|
176
|
-
# random password is limited to ASCII characters 48 ('0') through 122 ('z')
|
177
|
-
Puppet.settings.setting(:capass).open('w:ASCII') { |f| f.print pass }
|
178
|
-
rescue Errno::EACCES => detail
|
179
|
-
raise Puppet::Error, _("Could not write CA password: %{detail}") % { detail: detail }, detail.backtrace
|
180
|
-
end
|
181
|
-
|
182
|
-
@password = pass
|
183
|
-
|
184
|
-
pass
|
185
|
-
end
|
186
|
-
|
187
|
-
# Lists the names of all signed certificates.
|
188
|
-
#
|
189
|
-
# @param name [Array<string>] filter to cerificate names
|
190
|
-
#
|
191
|
-
# @return [Array<String>]
|
192
|
-
def list(name='*')
|
193
|
-
Puppet::SSL::Certificate.indirection.search(name).collect { |c| c.name }
|
194
|
-
end
|
195
|
-
|
196
|
-
# Read the next serial from the serial file, and increment the
|
197
|
-
# file so this one is considered used.
|
198
|
-
def next_serial
|
199
|
-
serial = 1
|
200
|
-
# the serial is 4 hex digits - limited to ASCII
|
201
|
-
Puppet.settings.setting(:serial).exclusive_open('a+:ASCII') do |f|
|
202
|
-
f.rewind
|
203
|
-
serial = f.read.chomp.hex
|
204
|
-
if serial == 0
|
205
|
-
serial = 1
|
206
|
-
end
|
207
|
-
|
208
|
-
f.truncate(0)
|
209
|
-
f.rewind
|
210
|
-
|
211
|
-
# We store the next valid serial, not the one we just used.
|
212
|
-
f << "%04X" % (serial + 1)
|
213
|
-
end
|
214
|
-
|
215
|
-
serial
|
216
|
-
end
|
217
|
-
|
218
|
-
# Does the password file exist?
|
219
|
-
def password?
|
220
|
-
Puppet::FileSystem.exist?(Puppet[:capass])
|
221
|
-
end
|
222
|
-
|
223
|
-
# Print a given host's certificate as text.
|
224
|
-
def print(name)
|
225
|
-
(cert = Puppet::SSL::Certificate.indirection.find(name)) ? cert.to_text : nil
|
226
|
-
end
|
227
|
-
|
228
|
-
# Revoke a given certificate.
|
229
|
-
def revoke(name)
|
230
|
-
raise ArgumentError, _("Cannot revoke certificates when the CRL is disabled") unless crl
|
231
|
-
|
232
|
-
cert = Puppet::SSL::Certificate.indirection.find(name)
|
233
|
-
|
234
|
-
serials = if cert
|
235
|
-
[cert.content.serial]
|
236
|
-
elsif name =~ /^0x[0-9A-Fa-f]+$/
|
237
|
-
[name.hex]
|
238
|
-
else
|
239
|
-
inventory.serials(name)
|
240
|
-
end
|
241
|
-
|
242
|
-
if serials.empty?
|
243
|
-
raise ArgumentError, _("Could not find a serial number for %{name}") % { name: name }
|
244
|
-
end
|
245
|
-
|
246
|
-
serials.each do |s|
|
247
|
-
crl.revoke(s, host.key.content)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
# This initializes our CA so it actually works. This should be a private
|
252
|
-
# method, except that you can't any-instance stub private methods, which is
|
253
|
-
# *awesome*. This method only really exists to provide a stub-point during
|
254
|
-
# testing.
|
255
|
-
def setup
|
256
|
-
generate_ca_certificate unless @host.certificate
|
257
|
-
end
|
258
|
-
|
259
|
-
# Sign a given certificate request.
|
260
|
-
def sign(hostname, options={})
|
261
|
-
options[:allow_authorization_extensions] ||= false
|
262
|
-
options[:allow_dns_alt_names] ||= false
|
263
|
-
options[:self_signing_csr] ||= nil
|
264
|
-
|
265
|
-
self_signing_csr = options.delete(:self_signing_csr)
|
266
|
-
|
267
|
-
if self_signing_csr
|
268
|
-
# # This is a self-signed certificate, which is for the CA. Since this
|
269
|
-
# # forces the certificate to be self-signed, anyone who manages to trick
|
270
|
-
# # the system into going through this path gets a certificate they could
|
271
|
-
# # generate anyway. There should be no security risk from that.
|
272
|
-
csr = self_signing_csr
|
273
|
-
cert_type = :ca
|
274
|
-
issuer = csr.content
|
275
|
-
else
|
276
|
-
unless csr = Puppet::SSL::CertificateRequest.indirection.find(hostname)
|
277
|
-
raise ArgumentError, _("Could not find certificate request for %{hostname}") % { hostname: hostname }
|
278
|
-
end
|
279
|
-
|
280
|
-
cert_type = :server
|
281
|
-
issuer = host.certificate.content
|
282
|
-
|
283
|
-
# Make sure that the CSR conforms to our internal signing policies.
|
284
|
-
# This will raise if the CSR doesn't conform, but just in case...
|
285
|
-
check_internal_signing_policies(hostname, csr, options) or
|
286
|
-
raise CertificateSigningError.new(hostname), _("CSR had an unknown failure checking internal signing policies, will not sign!")
|
287
|
-
end
|
288
|
-
|
289
|
-
cert = Puppet::SSL::Certificate.new(hostname)
|
290
|
-
cert.content = Puppet::SSL::CertificateFactory.
|
291
|
-
build(cert_type, csr, issuer, next_serial)
|
292
|
-
|
293
|
-
signer = Puppet::SSL::CertificateSigner.new
|
294
|
-
signer.sign(cert.content, host.key.content)
|
295
|
-
|
296
|
-
Puppet.notice _("Signed certificate request for %{hostname}") % { hostname: hostname }
|
297
|
-
|
298
|
-
# Add the cert to the inventory before we save it, since
|
299
|
-
# otherwise we could end up with it being duplicated, if
|
300
|
-
# this is the first time we build the inventory file.
|
301
|
-
inventory.add(cert)
|
302
|
-
|
303
|
-
# Save the now-signed cert. This should get routed correctly depending
|
304
|
-
# on the certificate type.
|
305
|
-
Puppet::SSL::Certificate.indirection.save(cert)
|
306
|
-
|
307
|
-
# And remove the CSR if this wasn't self signed.
|
308
|
-
Puppet::SSL::CertificateRequest.indirection.destroy(csr.name) unless self_signing_csr
|
309
|
-
|
310
|
-
cert
|
311
|
-
end
|
312
|
-
|
313
|
-
def check_internal_signing_policies(hostname, csr, options = {})
|
314
|
-
options[:allow_authorization_extensions] ||= false
|
315
|
-
options[:allow_dns_alt_names] ||= false
|
316
|
-
# This allows for masters to bootstrap themselves in certain scenarios
|
317
|
-
options[:allow_dns_alt_names] = true if hostname == Puppet[:certname].downcase
|
318
|
-
|
319
|
-
# Reject unknown request extensions.
|
320
|
-
unknown_req = csr.request_extensions.reject do |x|
|
321
|
-
RequestExtensionWhitelist.include? x["oid"] or
|
322
|
-
Puppet::SSL::Oids.subtree_of?('ppRegCertExt', x["oid"], true) or
|
323
|
-
Puppet::SSL::Oids.subtree_of?('ppPrivCertExt', x["oid"], true) or
|
324
|
-
Puppet::SSL::Oids.subtree_of?('ppAuthCertExt', x["oid"], true)
|
325
|
-
end
|
326
|
-
|
327
|
-
if unknown_req and not unknown_req.empty?
|
328
|
-
names = unknown_req.map {|x| x["oid"] }.sort.uniq.join(", ")
|
329
|
-
raise CertificateSigningError.new(hostname), _("CSR has request extensions that are not permitted: %{names}") % { names: names }
|
330
|
-
end
|
331
|
-
|
332
|
-
# Do not sign misleading CSRs
|
333
|
-
cn = csr.content.subject.to_a.assoc("CN")[1]
|
334
|
-
if hostname != cn
|
335
|
-
raise CertificateSigningError.new(hostname), _("CSR subject common name %{name} does not match expected certname %{expected}") % { name: cn.inspect, expected: hostname.inspect }
|
336
|
-
end
|
337
|
-
|
338
|
-
if hostname !~ Puppet::SSL::Base::VALID_CERTNAME
|
339
|
-
raise CertificateSigningError.new(hostname), _("CSR %{hostname} subject contains unprintable or non-ASCII characters") % { hostname: hostname.inspect }
|
340
|
-
end
|
341
|
-
|
342
|
-
# Wildcards: we don't allow 'em at any point.
|
343
|
-
#
|
344
|
-
# The stringification here makes the content visible, and saves us having
|
345
|
-
# to scrobble through the content of the CSR subject field to make sure it
|
346
|
-
# is what we expect where we expect it.
|
347
|
-
if csr.content.subject.to_s.include? '*'
|
348
|
-
raise CertificateSigningError.new(hostname), _("CSR subject contains a wildcard, which is not allowed: %{subject}") % { subject: csr.content.subject.to_s }
|
349
|
-
end
|
350
|
-
|
351
|
-
unless csr.content.verify(csr.content.public_key)
|
352
|
-
raise CertificateSigningError.new(hostname), _("CSR contains a public key that does not correspond to the signing key")
|
353
|
-
end
|
354
|
-
|
355
|
-
auth_extensions = csr.request_extensions.select do |extension|
|
356
|
-
Puppet::SSL::Oids.subtree_of?('ppAuthCertExt', extension['oid'], true)
|
357
|
-
end
|
358
|
-
|
359
|
-
if auth_extensions.any? && !options[:allow_authorization_extensions]
|
360
|
-
ext_names = auth_extensions.map do |extension|
|
361
|
-
extension['oid']
|
362
|
-
end
|
363
|
-
|
364
|
-
raise CertificateSigningError.new(hostname), _("CSR '%{csr}' contains authorization extensions (%{extensions}), which are disallowed by default. Use `puppet cert --allow-authorization-extensions sign %{csr}` to sign this request.") % { csr: csr.name, extensions: ext_names.join(', ') }
|
365
|
-
end
|
366
|
-
|
367
|
-
unless csr.subject_alt_names.empty?
|
368
|
-
# If you alt names are allowed, they are required. Otherwise they are
|
369
|
-
# disallowed. Self-signed certs are implicitly trusted, however.
|
370
|
-
unless options[:allow_dns_alt_names]
|
371
|
-
raise CertificateSigningError.new(hostname), _("CSR '%{csr}' contains subject alternative names (%{alt_names}), which are disallowed. Use `puppet cert --allow-dns-alt-names sign %{csr}` to sign this request.") % { csr: csr.name, alt_names: csr.subject_alt_names.join(', ') }
|
372
|
-
end
|
373
|
-
|
374
|
-
# If subjectAltNames are present, validate that they are only for DNS
|
375
|
-
# labels, not any other kind.
|
376
|
-
unless csr.subject_alt_names.all? {|x| x =~ /^DNS:/ }
|
377
|
-
raise CertificateSigningError.new(hostname), _("CSR '%{csr}' contains a subjectAltName outside the DNS label space: %{alt_names}. To continue, this CSR needs to be cleaned.") % { csr: csr.name, alt_names: csr.subject_alt_names.join(', ') }
|
378
|
-
end
|
379
|
-
|
380
|
-
# Check for wildcards in the subjectAltName fields too.
|
381
|
-
if csr.subject_alt_names.any? {|x| x.include? '*' }
|
382
|
-
raise CertificateSigningError.new(hostname), _("CSR '%{csr}' subjectAltName contains a wildcard, which is not allowed: %{alt_names}. To continue, this CSR needs to be cleaned.") % { csr: csr.name, alt_names: csr.subject_alt_names.join(', ') }
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
return true # good enough for us!
|
387
|
-
end
|
388
|
-
|
389
|
-
# Creates a brand new OpenSSL::X509::Store with the appropriate
|
390
|
-
# Certificate Revocation List and flags
|
391
|
-
#
|
392
|
-
# @return [OpenSSL::X509::Store]
|
393
|
-
def create_x509_store(purpose)
|
394
|
-
store = OpenSSL::X509::Store.new
|
395
|
-
store.add_file(Puppet[:cacert])
|
396
|
-
store.add_crl(crl.content) if self.crl
|
397
|
-
store.purpose = purpose
|
398
|
-
if Puppet.settings[:certificate_revocation]
|
399
|
-
store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL | OpenSSL::X509::V_FLAG_CRL_CHECK
|
400
|
-
end
|
401
|
-
store
|
402
|
-
end
|
403
|
-
private :create_x509_store
|
404
|
-
|
405
|
-
# Verify a given host's certificate. The certname is passed in, and
|
406
|
-
# the indirector will be used to locate the actual contents of the
|
407
|
-
# certificate with that name.
|
408
|
-
#
|
409
|
-
# @param name [String] certificate name to verify
|
410
|
-
# @param purpose [Integer] bitwise combination of X509::PURPOSE_*
|
411
|
-
#
|
412
|
-
# @raise [ArgumentError] if the certificate name cannot be found
|
413
|
-
# (i.e. doesn't exist or is unsigned)
|
414
|
-
# @raise [CertificateVerficationError] if the certificate has been revoked
|
415
|
-
#
|
416
|
-
# @return [Boolean] true if signed, there are no cases where false is returned
|
417
|
-
def verify(name, purpose = OpenSSL::X509::PURPOSE_ANY)
|
418
|
-
unless cert = Puppet::SSL::Certificate.indirection.find(name)
|
419
|
-
raise ArgumentError, _("Could not find a certificate for %{name}") % { name: name }
|
420
|
-
end
|
421
|
-
store = create_x509_store(purpose)
|
422
|
-
|
423
|
-
raise CertificateVerificationError.new(store.error), store.error_string unless store.verify(cert.content)
|
424
|
-
end
|
425
|
-
|
426
|
-
def fingerprint(name, md = :SHA256)
|
427
|
-
unless cert = Puppet::SSL::Certificate.indirection.find(name) || Puppet::SSL::CertificateRequest.indirection.find(name)
|
428
|
-
raise ArgumentError, _("Could not find a certificate or csr for %{name}") % { name: name }
|
429
|
-
end
|
430
|
-
cert.fingerprint(md)
|
431
|
-
end
|
432
|
-
|
433
|
-
# List the waiting certificate requests.
|
434
|
-
def waiting?
|
435
|
-
Puppet::SSL::CertificateRequest.indirection.search("*").collect { |r| r.name }
|
436
|
-
end
|
437
|
-
|
438
|
-
# @api private
|
439
|
-
class AutosignAlways
|
440
|
-
def allowed?(csr)
|
441
|
-
true
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
# @api private
|
446
|
-
class AutosignNever
|
447
|
-
def allowed?(csr)
|
448
|
-
false
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
# @api private
|
453
|
-
class AutosignConfig
|
454
|
-
def initialize(config_file)
|
455
|
-
@config = config_file
|
456
|
-
end
|
457
|
-
|
458
|
-
def allowed?(csr)
|
459
|
-
autosign_store.allowed?(csr.name, '127.1.1.1')
|
460
|
-
end
|
461
|
-
|
462
|
-
private
|
463
|
-
|
464
|
-
def autosign_store
|
465
|
-
auth = Puppet::Network::AuthStore.new
|
466
|
-
Puppet::FileSystem.each_line(@config) do |line|
|
467
|
-
next if line =~ /^\s*#/
|
468
|
-
next if line =~ /^\s*$/
|
469
|
-
auth.allow(line.chomp)
|
470
|
-
end
|
471
|
-
|
472
|
-
auth
|
473
|
-
end
|
474
|
-
end
|
475
|
-
end
|