puppet 2.7.5 → 2.7.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +121 -0
- data/conf/redhat/puppet.spec +16 -7
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/cert.rb +17 -3
- data/lib/puppet/application/device.rb +1 -0
- data/lib/puppet/application/kick.rb +0 -2
- data/lib/puppet/application/resource.rb +73 -66
- data/lib/puppet/configurer/plugin_handler.rb +6 -2
- data/lib/puppet/defaults.rb +60 -5
- data/lib/puppet/face/ca.rb +11 -2
- data/lib/puppet/face/certificate.rb +33 -4
- data/lib/puppet/file_serving/fileset.rb +1 -1
- data/lib/puppet/file_serving/indirection_hooks.rb +2 -2
- data/lib/puppet/file_serving/metadata.rb +43 -4
- data/lib/puppet/indirector.rb +0 -1
- data/lib/puppet/indirector/request.rb +3 -4
- data/lib/puppet/indirector/resource/active_record.rb +3 -10
- data/lib/puppet/indirector/resource/ral.rb +2 -2
- data/lib/puppet/indirector/rest.rb +1 -1
- data/lib/puppet/network/handler/ca.rb +16 -106
- data/lib/puppet/network/handler/master.rb +0 -3
- data/lib/puppet/network/handler/runner.rb +1 -0
- data/lib/puppet/parser/scope.rb +10 -0
- data/lib/puppet/provider/file/posix.rb +72 -34
- data/lib/puppet/provider/file/windows.rb +100 -0
- data/lib/puppet/provider/group/windows_adsi.rb +2 -2
- data/lib/puppet/provider/user/windows_adsi.rb +19 -4
- data/lib/puppet/resource.rb +16 -0
- data/lib/puppet/resource/catalog.rb +1 -1
- data/lib/puppet/ssl/certificate.rb +2 -2
- data/lib/puppet/ssl/certificate_authority.rb +86 -10
- data/lib/puppet/ssl/certificate_authority/interface.rb +64 -19
- data/lib/puppet/ssl/certificate_factory.rb +112 -91
- data/lib/puppet/ssl/certificate_request.rb +88 -1
- data/lib/puppet/ssl/host.rb +20 -3
- data/lib/puppet/type/file.rb +15 -34
- data/lib/puppet/type/file/group.rb +11 -91
- data/lib/puppet/type/file/mode.rb +11 -41
- data/lib/puppet/type/file/owner.rb +18 -34
- data/lib/puppet/type/file/source.rb +22 -7
- data/lib/puppet/type/group.rb +4 -3
- data/lib/puppet/type/user.rb +4 -1
- data/lib/puppet/util.rb +59 -6
- data/lib/puppet/util/adsi.rb +11 -0
- data/lib/puppet/util/log.rb +4 -0
- data/lib/puppet/util/log/destinations.rb +7 -1
- data/lib/puppet/util/monkey_patches.rb +19 -0
- data/lib/puppet/util/network_device/config.rb +4 -5
- data/lib/puppet/util/settings.rb +5 -0
- data/lib/puppet/util/suidmanager.rb +0 -1
- data/lib/puppet/util/windows.rb +4 -0
- data/lib/puppet/util/windows/error.rb +16 -0
- data/lib/puppet/util/windows/security.rb +593 -0
- data/spec/integration/defaults_spec.rb +27 -0
- data/spec/integration/network/handler_spec.rb +1 -1
- data/spec/integration/type/file_spec.rb +382 -145
- data/spec/integration/util/windows/security_spec.rb +468 -0
- data/spec/shared_behaviours/file_serving.rb +4 -3
- data/spec/unit/application/agent_spec.rb +1 -0
- data/spec/unit/application/device_spec.rb +5 -0
- data/spec/unit/application/resource_spec.rb +62 -101
- data/spec/unit/configurer/downloader_spec.rb +2 -2
- data/spec/unit/configurer/plugin_handler_spec.rb +15 -8
- data/spec/unit/configurer_spec.rb +2 -2
- data/spec/unit/face/ca_spec.rb +34 -0
- data/spec/unit/face/certificate_spec.rb +168 -1
- data/spec/unit/file_serving/fileset_spec.rb +1 -1
- data/spec/unit/file_serving/indirection_hooks_spec.rb +1 -1
- data/spec/unit/file_serving/metadata_spec.rb +151 -107
- data/spec/unit/indirector/certificate_request/ca_spec.rb +0 -3
- data/spec/unit/indirector/direct_file_server_spec.rb +10 -9
- data/spec/unit/indirector/file_metadata/file_spec.rb +6 -4
- data/spec/unit/indirector/request_spec.rb +13 -3
- data/spec/unit/indirector/resource/active_record_spec.rb +4 -10
- data/spec/unit/indirector/resource/ral_spec.rb +6 -4
- data/spec/unit/indirector/rest_spec.rb +5 -6
- data/spec/unit/network/handler/ca_spec.rb +86 -0
- data/spec/unit/parser/collector_spec.rb +7 -7
- data/spec/unit/parser/scope_spec.rb +20 -0
- data/spec/unit/provider/file/posix_spec.rb +226 -0
- data/spec/unit/provider/file/windows_spec.rb +136 -0
- data/spec/unit/provider/group/windows_adsi_spec.rb +7 -2
- data/spec/unit/provider/user/windows_adsi_spec.rb +36 -3
- data/spec/unit/resource/catalog_spec.rb +20 -10
- data/spec/unit/resource_spec.rb +55 -8
- data/spec/unit/ssl/certificate_authority/interface_spec.rb +97 -54
- data/spec/unit/ssl/certificate_authority_spec.rb +133 -23
- data/spec/unit/ssl/certificate_factory_spec.rb +90 -70
- data/spec/unit/ssl/certificate_request_spec.rb +62 -1
- data/spec/unit/ssl/certificate_spec.rb +20 -14
- data/spec/unit/ssl/host_spec.rb +52 -6
- data/spec/unit/type/file/content_spec.rb +4 -4
- data/spec/unit/type/file/group_spec.rb +34 -96
- data/spec/unit/type/file/mode_spec.rb +88 -0
- data/spec/unit/type/file/owner_spec.rb +32 -123
- data/spec/unit/type/file/source_spec.rb +120 -41
- data/spec/unit/type/file_spec.rb +1033 -753
- data/spec/unit/type_spec.rb +19 -1
- data/spec/unit/util/adsi_spec.rb +19 -0
- data/spec/unit/util/log/destinations_spec.rb +75 -0
- data/spec/unit/util/log_spec.rb +15 -0
- data/spec/unit/util/network_device/config_spec.rb +7 -0
- data/spec/unit/util/settings_spec.rb +10 -0
- data/spec/unit/util_spec.rb +126 -13
- data/test/language/functions.rb +0 -1
- data/test/language/snippets.rb +0 -9
- data/test/lib/puppettest/exetest.rb +1 -1
- data/test/lib/puppettest/servertest.rb +0 -1
- data/test/rails/rails.rb +0 -1
- data/test/ral/type/filesources.rb +0 -60
- metadata +13 -33
- data/lib/puppet/network/client.rb +0 -174
- data/lib/puppet/network/client/ca.rb +0 -56
- data/lib/puppet/network/client/file.rb +0 -6
- data/lib/puppet/network/client/proxy.rb +0 -27
- data/lib/puppet/network/client/report.rb +0 -26
- data/lib/puppet/network/client/runner.rb +0 -10
- data/lib/puppet/network/client/status.rb +0 -4
- data/lib/puppet/network/http_server.rb +0 -3
- data/lib/puppet/network/http_server/mongrel.rb +0 -130
- data/lib/puppet/network/http_server/webrick.rb +0 -155
- data/lib/puppet/network/xmlrpc/client.rb +0 -211
- data/lib/puppet/provider/file/win32.rb +0 -72
- data/lib/puppet/sslcertificates.rb +0 -146
- data/lib/puppet/sslcertificates/ca.rb +0 -375
- data/lib/puppet/sslcertificates/certificate.rb +0 -255
- data/lib/puppet/sslcertificates/inventory.rb +0 -38
- data/lib/puppet/sslcertificates/support.rb +0 -146
- data/spec/integration/network/client_spec.rb +0 -18
- data/spec/unit/network/xmlrpc/client_spec.rb +0 -172
- data/spec/unit/sslcertificates/ca_spec.rb +0 -106
- data/test/certmgr/certmgr.rb +0 -308
- data/test/certmgr/inventory.rb +0 -69
- data/test/certmgr/support.rb +0 -105
- data/test/network/client/ca.rb +0 -69
- data/test/network/client/dipper.rb +0 -34
- data/test/network/handler/ca.rb +0 -273
- data/test/network/server/mongrel_test.rb +0 -99
- data/test/network/server/webrick.rb +0 -111
- data/test/network/xmlrpc/client.rb +0 -45
data/lib/puppet/defaults.rb
CHANGED
@@ -112,9 +112,15 @@ module Puppet
|
|
112
112
|
:show_diff => [false, "Whether to print a contextual diff when files are being replaced. The diff
|
113
113
|
is printed on stdout, so this option is meaningless unless you are running Puppet interactively.
|
114
114
|
This feature currently requires the `diff/lcs` Ruby library."],
|
115
|
-
:daemonize => {
|
115
|
+
:daemonize => {
|
116
|
+
:default => (Puppet.features.microsoft_windows? ? false : true),
|
116
117
|
:desc => "Send the process into the background. This is the default.",
|
117
|
-
:short => "D"
|
118
|
+
:short => "D",
|
119
|
+
:hook => proc do |value|
|
120
|
+
if value and Puppet.features.microsoft_windows?
|
121
|
+
raise "Cannot daemonize on Windows"
|
122
|
+
end
|
123
|
+
end
|
118
124
|
},
|
119
125
|
:maximum_uid => [4294967290, "The maximum allowed UID. Some platforms use negative UIDs
|
120
126
|
but then ship with tools that do not know how to handle signed ints, so the UIDs show up as
|
@@ -210,9 +216,58 @@ module Puppet
|
|
210
216
|
to the fully qualified domain name.",
|
211
217
|
:call_on_define => true, # Call our hook with the default value, so we're always downcased
|
212
218
|
:hook => proc { |value| raise(ArgumentError, "Certificate names must be lower case; see #1168") unless value == value.downcase }},
|
213
|
-
:certdnsnames =>
|
214
|
-
|
215
|
-
|
219
|
+
:certdnsnames => {
|
220
|
+
:default => '',
|
221
|
+
:hook => proc do |value|
|
222
|
+
unless value.nil? or value == '' then
|
223
|
+
Puppet.warning <<WARN
|
224
|
+
The `certdnsnames` setting is no longer functional,
|
225
|
+
after CVE-2011-3872. We ignore the value completely.
|
226
|
+
|
227
|
+
For your own certificate request you can set `dns_alt_names` in the
|
228
|
+
configuration and it will apply locally. There is no configuration option to
|
229
|
+
set DNS alt names, or any other `subjectAltName` value, for another nodes
|
230
|
+
certificate.
|
231
|
+
|
232
|
+
Alternately you can use the `--dns_alt_names` command line option to set the
|
233
|
+
labels added while generating your own CSR.
|
234
|
+
WARN
|
235
|
+
end
|
236
|
+
end,
|
237
|
+
:desc => <<EOT
|
238
|
+
The `certdnsnames` setting is no longer functional,
|
239
|
+
after CVE-2011-3872. We ignore the value completely.
|
240
|
+
|
241
|
+
For your own certificate request you can set `dns_alt_names` in the
|
242
|
+
configuration and it will apply locally. There is no configuration option to
|
243
|
+
set DNS alt names, or any other `subjectAltName` value, for another nodes
|
244
|
+
certificate.
|
245
|
+
|
246
|
+
Alternately you can use the `--dns_alt_names` command line option to set the
|
247
|
+
labels added while generating your own CSR.
|
248
|
+
EOT
|
249
|
+
},
|
250
|
+
:dns_alt_names => {
|
251
|
+
:default => '',
|
252
|
+
:desc => <<EOT,
|
253
|
+
The comma-separated list of alternative DNS names to use for the local host.
|
254
|
+
|
255
|
+
When the node generates a CSR for itself, these are added to the request
|
256
|
+
as the desired `subjectAltName` in the certificate: additional DNS labels
|
257
|
+
that the certificate is also valid answering as.
|
258
|
+
|
259
|
+
This is generally required if you use a non-hostname `certname`, or if you
|
260
|
+
want to use `puppet kick` or `puppet resource -H` and the primary certname
|
261
|
+
does not match the DNS name you use to communicate with the host.
|
262
|
+
|
263
|
+
This is unnecessary for agents, unless you intend to use them as a server for
|
264
|
+
`puppet kick` or remote `puppet resource` management.
|
265
|
+
|
266
|
+
It is rarely necessary for servers; it is usually helpful only if you need to
|
267
|
+
have a pool of multiple load balanced masters, or for the same master to
|
268
|
+
respond on two physically separate networks under different names.
|
269
|
+
EOT
|
270
|
+
},
|
216
271
|
:certdir => {
|
217
272
|
:default => "$ssldir/certs",
|
218
273
|
:owner => "service",
|
data/lib/puppet/face/ca.rb
CHANGED
@@ -124,6 +124,11 @@ Puppet::Face.define(:ca, '0.1.0') do
|
|
124
124
|
end
|
125
125
|
|
126
126
|
action :generate do
|
127
|
+
option "--dns-alt-names NAMES" do
|
128
|
+
summary "Additional DNS names to add to the certificate request"
|
129
|
+
description Puppet.settings.setting(:dns_alt_names).desc
|
130
|
+
end
|
131
|
+
|
127
132
|
when_invoked do |host, options|
|
128
133
|
raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca?
|
129
134
|
unless ca = Puppet::SSL::CertificateAuthority.instance
|
@@ -131,7 +136,7 @@ Puppet::Face.define(:ca, '0.1.0') do
|
|
131
136
|
end
|
132
137
|
|
133
138
|
begin
|
134
|
-
ca.generate
|
139
|
+
ca.generate(host, :dns_alt_names => options[:dns_alt_names])
|
135
140
|
rescue RuntimeError => e
|
136
141
|
if e.to_s =~ /already has a requested certificate/
|
137
142
|
"#{host} already has a certificate request; use sign instead"
|
@@ -149,6 +154,10 @@ Puppet::Face.define(:ca, '0.1.0') do
|
|
149
154
|
end
|
150
155
|
|
151
156
|
action :sign do
|
157
|
+
option("--[no-]allow-dns-alt-names") do
|
158
|
+
summary "Whether or not to accept DNS alt names in the certificate request"
|
159
|
+
end
|
160
|
+
|
152
161
|
when_invoked do |host, options|
|
153
162
|
raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca?
|
154
163
|
unless ca = Puppet::SSL::CertificateAuthority.instance
|
@@ -156,7 +165,7 @@ Puppet::Face.define(:ca, '0.1.0') do
|
|
156
165
|
end
|
157
166
|
|
158
167
|
begin
|
159
|
-
ca.sign
|
168
|
+
ca.sign(host, options[:allow_dns_alt_names])
|
160
169
|
rescue ArgumentError => e
|
161
170
|
if e.to_s =~ /Could not find certificate request/
|
162
171
|
e.to_s
|
@@ -51,10 +51,21 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
|
|
51
51
|
$ puppet certificate generate somenode.puppetlabs.lan --ca-location remote
|
52
52
|
EOT
|
53
53
|
|
54
|
+
# Duplicate the option here explicitly to distinguish if it was passed arg
|
55
|
+
# us vs. set in the config file.
|
56
|
+
option "--dns-alt-names NAMES" do
|
57
|
+
summary "Additional DNS names to add to the certificate request"
|
58
|
+
description Puppet.settings.setting(:dns_alt_names).desc
|
59
|
+
end
|
60
|
+
|
54
61
|
when_invoked do |name, options|
|
55
62
|
host = Puppet::SSL::Host.new(name)
|
56
|
-
|
57
|
-
|
63
|
+
|
64
|
+
# If dns_alt_names are specified via the command line, we will always add
|
65
|
+
# them. Otherwise, they will default to the config file setting iff this
|
66
|
+
# cert is for the host we're running on.
|
67
|
+
|
68
|
+
host.generate_certificate_request(:dns_alt_names => options[:dns_alt_names])
|
58
69
|
end
|
59
70
|
end
|
60
71
|
|
@@ -86,10 +97,28 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
|
|
86
97
|
$ puppet certificate sign somenode.puppetlabs.lan --ca-location remote
|
87
98
|
EOT
|
88
99
|
|
100
|
+
option("--[no-]allow-dns-alt-names") do
|
101
|
+
summary "Whether or not to accept DNS alt names in the certificate request"
|
102
|
+
end
|
103
|
+
|
89
104
|
when_invoked do |name, options|
|
90
105
|
host = Puppet::SSL::Host.new(name)
|
91
|
-
|
92
|
-
|
106
|
+
if options[:ca_location] == :remote
|
107
|
+
if options[:allow_dns_alt_names]
|
108
|
+
raise ArgumentError, "--allow-dns-alt-names may not be specified with a remote CA"
|
109
|
+
end
|
110
|
+
|
111
|
+
host.desired_state = 'signed'
|
112
|
+
Puppet::SSL::Host.indirection.save(host)
|
113
|
+
else
|
114
|
+
# We have to do this case manually because we need to specify
|
115
|
+
# allow_dns_alt_names.
|
116
|
+
unless ca = Puppet::SSL::CertificateAuthority.instance
|
117
|
+
raise ArgumentError, "This process is not configured as a certificate authority"
|
118
|
+
end
|
119
|
+
|
120
|
+
ca.sign(name, options[:allow_dns_alt_names])
|
121
|
+
end
|
93
122
|
end
|
94
123
|
end
|
95
124
|
|
@@ -61,7 +61,7 @@ class Puppet::FileServing::Fileset
|
|
61
61
|
else
|
62
62
|
path = path.chomp(File::SEPARATOR) unless path == File::SEPARATOR
|
63
63
|
end
|
64
|
-
raise ArgumentError.new("Fileset paths must be fully qualified: #{path}") unless
|
64
|
+
raise ArgumentError.new("Fileset paths must be fully qualified: #{path}") unless Puppet::Util.absolute_path?(path)
|
65
65
|
|
66
66
|
@path = path
|
67
67
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'puppet/file_serving'
|
3
|
+
require 'puppet/util'
|
3
4
|
|
4
5
|
# This module is used to pick the appropriate terminus
|
5
6
|
# in file-serving indirections. This is necessary because
|
@@ -12,8 +13,7 @@ module Puppet::FileServing::IndirectionHooks
|
|
12
13
|
# We rely on the request's parsing of the URI.
|
13
14
|
|
14
15
|
# Short-circuit to :file if it's a fully-qualified path or specifies a 'file' protocol.
|
15
|
-
return PROTOCOL_MAP["file"] if request.key
|
16
|
-
return PROTOCOL_MAP["file"] if request.key =~ /^[a-z]:[\/\\]/i
|
16
|
+
return PROTOCOL_MAP["file"] if Puppet::Util.absolute_path?(request.key)
|
17
17
|
return PROTOCOL_MAP["file"] if request.protocol == "file"
|
18
18
|
|
19
19
|
# We're heading over the wire the protocol is 'puppet' and we've got a server name or we're not named 'apply' or 'puppet'
|
@@ -37,16 +37,55 @@ class Puppet::FileServing::Metadata < Puppet::FileServing::Base
|
|
37
37
|
@checksum_type = type
|
38
38
|
end
|
39
39
|
|
40
|
+
class MetaStat
|
41
|
+
extend Forwardable
|
42
|
+
|
43
|
+
def initialize(stat)
|
44
|
+
@stat = stat
|
45
|
+
end
|
46
|
+
|
47
|
+
def_delegator :@stat, :uid, :owner
|
48
|
+
def_delegator :@stat, :gid, :group
|
49
|
+
def_delegators :@stat, :mode, :ftype
|
50
|
+
end
|
51
|
+
|
52
|
+
class WindowsStat < MetaStat
|
53
|
+
if Puppet.features.microsoft_windows?
|
54
|
+
require 'puppet/util/windows/security'
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize(stat, path)
|
58
|
+
super(stat)
|
59
|
+
@path = path
|
60
|
+
end
|
61
|
+
|
62
|
+
[:owner, :group, :mode].each do |method|
|
63
|
+
define_method method do
|
64
|
+
Puppet::Util::Windows::Security.send("get_#{method}", @path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def collect_stat(path)
|
70
|
+
stat = stat()
|
71
|
+
|
72
|
+
if Puppet.features.microsoft_windows?
|
73
|
+
WindowsStat.new(stat, path)
|
74
|
+
else
|
75
|
+
MetaStat.new(stat)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
40
79
|
# Retrieve the attributes for this file, relative to a base directory.
|
41
80
|
# Note that File.stat raises Errno::ENOENT if the file is absent and this
|
42
81
|
# method does not catch that exception.
|
43
82
|
def collect
|
44
83
|
real_path = full_path
|
45
|
-
stat = stat()
|
46
|
-
@owner = stat.uid
|
47
|
-
@group = stat.gid
|
48
|
-
@ftype = stat.ftype
|
49
84
|
|
85
|
+
stat = collect_stat(real_path)
|
86
|
+
@owner = stat.owner
|
87
|
+
@group = stat.group
|
88
|
+
@ftype = stat.ftype
|
50
89
|
|
51
90
|
# We have to mask the mode, yay.
|
52
91
|
@mode = stat.mode & 007777
|
data/lib/puppet/indirector.rb
CHANGED
@@ -76,9 +76,8 @@ class Puppet::Indirector::Request
|
|
76
76
|
# because it rewrites the key. We could otherwise strip server/port/etc
|
77
77
|
# info out in the REST class, but it seemed bad design for the REST
|
78
78
|
# class to rewrite the key.
|
79
|
-
|
80
|
-
|
81
|
-
elsif key.to_s =~ /^\w+:\/\// # it's a URI
|
79
|
+
|
80
|
+
if key.to_s =~ /^\w+:\// and not Puppet::Util.absolute_path?(key.to_s) # it's a URI
|
82
81
|
set_uri_key(key)
|
83
82
|
else
|
84
83
|
@key = key
|
@@ -173,7 +172,7 @@ class Puppet::Indirector::Request
|
|
173
172
|
|
174
173
|
# Just short-circuit these to full paths
|
175
174
|
if uri.scheme == "file"
|
176
|
-
@key =
|
175
|
+
@key = Puppet::Util.uri_to_path(uri)
|
177
176
|
return
|
178
177
|
end
|
179
178
|
|
@@ -16,9 +16,8 @@ class Puppet::Resource::ActiveRecord < Puppet::Indirector::ActiveRecord
|
|
16
16
|
|
17
17
|
private
|
18
18
|
def request_to_type_name(request)
|
19
|
-
|
20
|
-
|
21
|
-
type.name
|
19
|
+
request.key.split('/', 2)[0] or
|
20
|
+
raise "No key found in the request, failing: #{request.inspect}"
|
22
21
|
end
|
23
22
|
|
24
23
|
def filter_to_active_record(filter)
|
@@ -59,13 +58,7 @@ class Puppet::Resource::ActiveRecord < Puppet::Indirector::ActiveRecord
|
|
59
58
|
raise Puppet::DevError, "Cannot collect resources for a nil host" unless host
|
60
59
|
|
61
60
|
search = "(exported=? AND restype=?)"
|
62
|
-
|
63
|
-
# others preserve the symbol-nature, which causes our storage (string) and
|
64
|
-
# query (symbol) to mismatch. So, manually stringify. --daniel 2011-09-08
|
65
|
-
#
|
66
|
-
# Also, PostgreSQL is case sensitive; we need to make sure our type name
|
67
|
-
# here matches what we inject. --daniel 2011-09-30
|
68
|
-
arguments = [true, type.to_s.capitalize]
|
61
|
+
arguments = [true, type]
|
69
62
|
|
70
63
|
if filter then
|
71
64
|
sql, values = filter_to_active_record(filter)
|
@@ -27,9 +27,9 @@ class Puppet::Resource::Ral < Puppet::Indirector::Code
|
|
27
27
|
|
28
28
|
catalog = Puppet::Resource::Catalog.new
|
29
29
|
catalog.add_resource ral_res
|
30
|
-
catalog.apply
|
30
|
+
transaction = catalog.apply
|
31
31
|
|
32
|
-
ral_res.to_resource
|
32
|
+
[ral_res.to_resource, transaction.report]
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
@@ -98,7 +98,7 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
|
|
98
98
|
elsif error.message.include? "hostname was not match"
|
99
99
|
raise unless cert = peer_certs.find { |c| c.name !~ /^puppet ca/i }
|
100
100
|
|
101
|
-
valid_certnames = [cert.name, *cert.
|
101
|
+
valid_certnames = [cert.name, *cert.subject_alt_names].uniq
|
102
102
|
msg = valid_certnames.length > 1 ? "one of #{valid_certnames.join(', ')}" : valid_certnames.first
|
103
103
|
|
104
104
|
raise Puppet::Error, "Server hostname '#{http_connection.address}' did not match server certificate; expected #{msg}"
|
@@ -1,10 +1,7 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
require 'puppet'
|
3
|
-
require 'puppet/sslcertificates'
|
4
3
|
require 'xmlrpc/server'
|
5
|
-
|
6
|
-
# Much of this was taken from QuickCert:
|
7
|
-
# http://segment7.net/projects/ruby/QuickCert/
|
4
|
+
require 'puppet/network/handler'
|
8
5
|
|
9
6
|
class Puppet::Network::Handler
|
10
7
|
class CA < Handler
|
@@ -18,73 +15,17 @@ class Puppet::Network::Handler
|
|
18
15
|
iface.add_method("array getcert(csr)")
|
19
16
|
}
|
20
17
|
|
21
|
-
def autosign
|
22
|
-
if defined?(@autosign)
|
23
|
-
@autosign
|
24
|
-
else
|
25
|
-
Puppet[:autosign]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# FIXME autosign? should probably accept both hostnames and IP addresses
|
30
|
-
def autosign?(hostname)
|
31
|
-
# simple values are easy
|
32
|
-
if autosign == true or autosign == false
|
33
|
-
return autosign
|
34
|
-
end
|
35
|
-
|
36
|
-
# we only otherwise know how to handle files
|
37
|
-
unless autosign =~ /^\//
|
38
|
-
raise Puppet::Error, "Invalid autosign value #{autosign.inspect}"
|
39
|
-
end
|
40
|
-
|
41
|
-
unless FileTest.exists?(autosign)
|
42
|
-
unless defined?(@@warnedonautosign)
|
43
|
-
@@warnedonautosign = true
|
44
|
-
Puppet.info "Autosign is enabled but #{autosign} is missing"
|
45
|
-
end
|
46
|
-
return false
|
47
|
-
end
|
48
|
-
auth = Puppet::Network::AuthStore.new
|
49
|
-
File.open(autosign) { |f|
|
50
|
-
f.each { |line|
|
51
|
-
next if line =~ /^\s*#/
|
52
|
-
next if line =~ /^\s*$/
|
53
|
-
auth.allow(line.chomp)
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
# for now, just cheat and pass a fake IP address to allowed?
|
58
|
-
auth.allowed?(hostname, "127.1.1.1")
|
59
|
-
end
|
60
|
-
|
61
18
|
def initialize(hash = {})
|
62
19
|
Puppet.settings.use(:main, :ssl, :ca)
|
63
|
-
@autosign = hash[:autosign] if hash.include? :autosign
|
64
20
|
|
65
|
-
@ca = Puppet::
|
21
|
+
@ca = Puppet::SSL::CertificateAuthority.instance
|
66
22
|
end
|
67
23
|
|
68
24
|
# our client sends us a csr, and we either store it for later signing,
|
69
25
|
# or we sign it right away
|
70
26
|
def getcert(csrtext, client = nil, clientip = nil)
|
71
|
-
csr =
|
72
|
-
|
73
|
-
# Use the hostname from the CSR, not from the network.
|
74
|
-
subject = csr.subject
|
75
|
-
|
76
|
-
nameary = subject.to_a.find { |ary|
|
77
|
-
ary[0] == "CN"
|
78
|
-
}
|
79
|
-
|
80
|
-
if nameary.nil?
|
81
|
-
Puppet.err(
|
82
|
-
"Invalid certificate request: could not retrieve server name"
|
83
|
-
)
|
84
|
-
return "invalid"
|
85
|
-
end
|
86
|
-
|
87
|
-
hostname = nameary[1]
|
27
|
+
csr = Puppet::SSL::CertificateRequest.from_s(csrtext)
|
28
|
+
hostname = csr.name
|
88
29
|
|
89
30
|
unless @ca
|
90
31
|
Puppet.notice "Host #{hostname} asked for signing from non-CA master"
|
@@ -93,57 +34,26 @@ class Puppet::Network::Handler
|
|
93
34
|
|
94
35
|
# We used to save the public key, but it's basically unnecessary
|
95
36
|
# and it mucks with the permissions requirements.
|
96
|
-
# save_pk(hostname, csr.public_key)
|
97
|
-
|
98
|
-
certfile = File.join(Puppet[:certdir], [hostname, "pem"].join("."))
|
99
37
|
|
100
38
|
# first check to see if we already have a signed cert for the host
|
101
|
-
cert
|
102
|
-
|
39
|
+
cert = Puppet::SSL::Certificate.indirection.find(hostname)
|
40
|
+
cacert = Puppet::SSL::Certificate.indirection.find(@ca.host.name)
|
41
|
+
|
42
|
+
if cert
|
103
43
|
Puppet.info "Retrieving existing certificate for #{hostname}"
|
104
|
-
unless csr.public_key.to_s == cert.public_key.to_s
|
44
|
+
unless csr.content.public_key.to_s == cert.content.public_key.to_s
|
105
45
|
raise Puppet::Error, "Certificate request does not match existing certificate; run 'puppetca --clean #{hostname}'."
|
106
46
|
end
|
107
|
-
|
108
|
-
elsif @ca
|
109
|
-
if self.autosign?(hostname) or client.nil?
|
110
|
-
Puppet.info "Signing certificate for CA server" if client.nil?
|
111
|
-
# okay, we don't have a signed cert
|
112
|
-
# if we're a CA and autosign is turned on, then go ahead and sign
|
113
|
-
# the csr and return the results
|
114
|
-
Puppet.info "Signing certificate for #{hostname}"
|
115
|
-
cert, cacert = @ca.sign(csr)
|
116
|
-
#Puppet.info "Cert: #{cert.class}; Cacert: #{cacert.class}"
|
117
|
-
return [cert.to_pem, cacert.to_pem]
|
118
|
-
else # just write out the csr for later signing
|
119
|
-
if @ca.getclientcsr(hostname)
|
120
|
-
Puppet.info "Not replacing existing request from #{hostname}"
|
121
|
-
else
|
122
|
-
Puppet.notice "Host #{hostname} has a waiting certificate request"
|
123
|
-
@ca.storeclientcsr(csr)
|
124
|
-
end
|
125
|
-
return ["", ""]
|
126
|
-
end
|
47
|
+
[cert.to_s, cacert.to_s]
|
127
48
|
else
|
128
|
-
|
129
|
-
end
|
130
|
-
end
|
49
|
+
Puppet::SSL::CertificateRequest.indirection.save(csr)
|
131
50
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
if FileTest.exists?(pkeyfile)
|
139
|
-
currentkey = File.open(pkeyfile) { |k| k.read }
|
140
|
-
unless currentkey == public_key.to_s
|
141
|
-
raise Puppet::Error, "public keys for #{hostname} differ"
|
51
|
+
# We determine whether we signed the csr by checking if there's a certificate for it
|
52
|
+
if cert = Puppet::SSL::Certificate.indirection.find(hostname)
|
53
|
+
[cert.to_s, cacert.to_s]
|
54
|
+
else
|
55
|
+
nil
|
142
56
|
end
|
143
|
-
else
|
144
|
-
File.open(pkeyfile, "w", 0644) { |f|
|
145
|
-
f.print public_key.to_s
|
146
|
-
}
|
147
57
|
end
|
148
58
|
end
|
149
59
|
end
|