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.

Files changed (140) hide show
  1. data/CHANGELOG +121 -0
  2. data/conf/redhat/puppet.spec +16 -7
  3. data/lib/puppet.rb +1 -1
  4. data/lib/puppet/application/cert.rb +17 -3
  5. data/lib/puppet/application/device.rb +1 -0
  6. data/lib/puppet/application/kick.rb +0 -2
  7. data/lib/puppet/application/resource.rb +73 -66
  8. data/lib/puppet/configurer/plugin_handler.rb +6 -2
  9. data/lib/puppet/defaults.rb +60 -5
  10. data/lib/puppet/face/ca.rb +11 -2
  11. data/lib/puppet/face/certificate.rb +33 -4
  12. data/lib/puppet/file_serving/fileset.rb +1 -1
  13. data/lib/puppet/file_serving/indirection_hooks.rb +2 -2
  14. data/lib/puppet/file_serving/metadata.rb +43 -4
  15. data/lib/puppet/indirector.rb +0 -1
  16. data/lib/puppet/indirector/request.rb +3 -4
  17. data/lib/puppet/indirector/resource/active_record.rb +3 -10
  18. data/lib/puppet/indirector/resource/ral.rb +2 -2
  19. data/lib/puppet/indirector/rest.rb +1 -1
  20. data/lib/puppet/network/handler/ca.rb +16 -106
  21. data/lib/puppet/network/handler/master.rb +0 -3
  22. data/lib/puppet/network/handler/runner.rb +1 -0
  23. data/lib/puppet/parser/scope.rb +10 -0
  24. data/lib/puppet/provider/file/posix.rb +72 -34
  25. data/lib/puppet/provider/file/windows.rb +100 -0
  26. data/lib/puppet/provider/group/windows_adsi.rb +2 -2
  27. data/lib/puppet/provider/user/windows_adsi.rb +19 -4
  28. data/lib/puppet/resource.rb +16 -0
  29. data/lib/puppet/resource/catalog.rb +1 -1
  30. data/lib/puppet/ssl/certificate.rb +2 -2
  31. data/lib/puppet/ssl/certificate_authority.rb +86 -10
  32. data/lib/puppet/ssl/certificate_authority/interface.rb +64 -19
  33. data/lib/puppet/ssl/certificate_factory.rb +112 -91
  34. data/lib/puppet/ssl/certificate_request.rb +88 -1
  35. data/lib/puppet/ssl/host.rb +20 -3
  36. data/lib/puppet/type/file.rb +15 -34
  37. data/lib/puppet/type/file/group.rb +11 -91
  38. data/lib/puppet/type/file/mode.rb +11 -41
  39. data/lib/puppet/type/file/owner.rb +18 -34
  40. data/lib/puppet/type/file/source.rb +22 -7
  41. data/lib/puppet/type/group.rb +4 -3
  42. data/lib/puppet/type/user.rb +4 -1
  43. data/lib/puppet/util.rb +59 -6
  44. data/lib/puppet/util/adsi.rb +11 -0
  45. data/lib/puppet/util/log.rb +4 -0
  46. data/lib/puppet/util/log/destinations.rb +7 -1
  47. data/lib/puppet/util/monkey_patches.rb +19 -0
  48. data/lib/puppet/util/network_device/config.rb +4 -5
  49. data/lib/puppet/util/settings.rb +5 -0
  50. data/lib/puppet/util/suidmanager.rb +0 -1
  51. data/lib/puppet/util/windows.rb +4 -0
  52. data/lib/puppet/util/windows/error.rb +16 -0
  53. data/lib/puppet/util/windows/security.rb +593 -0
  54. data/spec/integration/defaults_spec.rb +27 -0
  55. data/spec/integration/network/handler_spec.rb +1 -1
  56. data/spec/integration/type/file_spec.rb +382 -145
  57. data/spec/integration/util/windows/security_spec.rb +468 -0
  58. data/spec/shared_behaviours/file_serving.rb +4 -3
  59. data/spec/unit/application/agent_spec.rb +1 -0
  60. data/spec/unit/application/device_spec.rb +5 -0
  61. data/spec/unit/application/resource_spec.rb +62 -101
  62. data/spec/unit/configurer/downloader_spec.rb +2 -2
  63. data/spec/unit/configurer/plugin_handler_spec.rb +15 -8
  64. data/spec/unit/configurer_spec.rb +2 -2
  65. data/spec/unit/face/ca_spec.rb +34 -0
  66. data/spec/unit/face/certificate_spec.rb +168 -1
  67. data/spec/unit/file_serving/fileset_spec.rb +1 -1
  68. data/spec/unit/file_serving/indirection_hooks_spec.rb +1 -1
  69. data/spec/unit/file_serving/metadata_spec.rb +151 -107
  70. data/spec/unit/indirector/certificate_request/ca_spec.rb +0 -3
  71. data/spec/unit/indirector/direct_file_server_spec.rb +10 -9
  72. data/spec/unit/indirector/file_metadata/file_spec.rb +6 -4
  73. data/spec/unit/indirector/request_spec.rb +13 -3
  74. data/spec/unit/indirector/resource/active_record_spec.rb +4 -10
  75. data/spec/unit/indirector/resource/ral_spec.rb +6 -4
  76. data/spec/unit/indirector/rest_spec.rb +5 -6
  77. data/spec/unit/network/handler/ca_spec.rb +86 -0
  78. data/spec/unit/parser/collector_spec.rb +7 -7
  79. data/spec/unit/parser/scope_spec.rb +20 -0
  80. data/spec/unit/provider/file/posix_spec.rb +226 -0
  81. data/spec/unit/provider/file/windows_spec.rb +136 -0
  82. data/spec/unit/provider/group/windows_adsi_spec.rb +7 -2
  83. data/spec/unit/provider/user/windows_adsi_spec.rb +36 -3
  84. data/spec/unit/resource/catalog_spec.rb +20 -10
  85. data/spec/unit/resource_spec.rb +55 -8
  86. data/spec/unit/ssl/certificate_authority/interface_spec.rb +97 -54
  87. data/spec/unit/ssl/certificate_authority_spec.rb +133 -23
  88. data/spec/unit/ssl/certificate_factory_spec.rb +90 -70
  89. data/spec/unit/ssl/certificate_request_spec.rb +62 -1
  90. data/spec/unit/ssl/certificate_spec.rb +20 -14
  91. data/spec/unit/ssl/host_spec.rb +52 -6
  92. data/spec/unit/type/file/content_spec.rb +4 -4
  93. data/spec/unit/type/file/group_spec.rb +34 -96
  94. data/spec/unit/type/file/mode_spec.rb +88 -0
  95. data/spec/unit/type/file/owner_spec.rb +32 -123
  96. data/spec/unit/type/file/source_spec.rb +120 -41
  97. data/spec/unit/type/file_spec.rb +1033 -753
  98. data/spec/unit/type_spec.rb +19 -1
  99. data/spec/unit/util/adsi_spec.rb +19 -0
  100. data/spec/unit/util/log/destinations_spec.rb +75 -0
  101. data/spec/unit/util/log_spec.rb +15 -0
  102. data/spec/unit/util/network_device/config_spec.rb +7 -0
  103. data/spec/unit/util/settings_spec.rb +10 -0
  104. data/spec/unit/util_spec.rb +126 -13
  105. data/test/language/functions.rb +0 -1
  106. data/test/language/snippets.rb +0 -9
  107. data/test/lib/puppettest/exetest.rb +1 -1
  108. data/test/lib/puppettest/servertest.rb +0 -1
  109. data/test/rails/rails.rb +0 -1
  110. data/test/ral/type/filesources.rb +0 -60
  111. metadata +13 -33
  112. data/lib/puppet/network/client.rb +0 -174
  113. data/lib/puppet/network/client/ca.rb +0 -56
  114. data/lib/puppet/network/client/file.rb +0 -6
  115. data/lib/puppet/network/client/proxy.rb +0 -27
  116. data/lib/puppet/network/client/report.rb +0 -26
  117. data/lib/puppet/network/client/runner.rb +0 -10
  118. data/lib/puppet/network/client/status.rb +0 -4
  119. data/lib/puppet/network/http_server.rb +0 -3
  120. data/lib/puppet/network/http_server/mongrel.rb +0 -130
  121. data/lib/puppet/network/http_server/webrick.rb +0 -155
  122. data/lib/puppet/network/xmlrpc/client.rb +0 -211
  123. data/lib/puppet/provider/file/win32.rb +0 -72
  124. data/lib/puppet/sslcertificates.rb +0 -146
  125. data/lib/puppet/sslcertificates/ca.rb +0 -375
  126. data/lib/puppet/sslcertificates/certificate.rb +0 -255
  127. data/lib/puppet/sslcertificates/inventory.rb +0 -38
  128. data/lib/puppet/sslcertificates/support.rb +0 -146
  129. data/spec/integration/network/client_spec.rb +0 -18
  130. data/spec/unit/network/xmlrpc/client_spec.rb +0 -172
  131. data/spec/unit/sslcertificates/ca_spec.rb +0 -106
  132. data/test/certmgr/certmgr.rb +0 -308
  133. data/test/certmgr/inventory.rb +0 -69
  134. data/test/certmgr/support.rb +0 -105
  135. data/test/network/client/ca.rb +0 -69
  136. data/test/network/client/dipper.rb +0 -34
  137. data/test/network/handler/ca.rb +0 -273
  138. data/test/network/server/mongrel_test.rb +0 -99
  139. data/test/network/server/webrick.rb +0 -111
  140. data/test/network/xmlrpc/client.rb +0 -45
@@ -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 => { :default => true,
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 => ['', "The DNS names on the Server certificate as a colon-separated list.
214
- If it's anything other than an empty string, it will be used as an alias in the created
215
- certificate. By default, only the server gets an alias set up, and only for 'puppet'."],
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",
@@ -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 host
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 host
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
- host.generate_certificate_request
57
- host.certificate_request.class.indirection.save(host.certificate_request)
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
- host.desired_state = 'signed'
92
- Puppet::SSL::Host.indirection.save(host)
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 File.expand_path(path) == path
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 =~ /^#{::File::SEPARATOR}/
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
@@ -49,7 +49,6 @@ module Puppet::Indirector
49
49
  attr_reader :indirection
50
50
  end
51
51
 
52
-
53
52
  # Helper definition for indirections that handle filenames.
54
53
  BadNameRegexp = Regexp.union(/^\.\./,
55
54
  %r{[\\/]},
@@ -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
- if key.to_s =~ /^[a-z]:[\/\\]/i # It's an absolute path for Windows.
80
- @key = key
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 = URI.unescape(uri.path)
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
- name = request.key.split('/', 2)[0]
20
- type = Puppet::Type.type(name) or raise Puppet::Error, "Could not find type #{name}"
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
- # Some versions of ActiveRecord just to_s a symbol, which our type is, but
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.alternate_names].uniq
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::SSLCertificates::CA.new(hash)
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 = OpenSSL::X509::Request.new(csrtext)
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, cacert = ca.getclientcert(hostname)
102
- if cert and cacert
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
- return [cert.to_pem, cacert.to_pem]
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
- raise "huh?"
129
- end
130
- end
49
+ Puppet::SSL::CertificateRequest.indirection.save(csr)
131
50
 
132
- private
133
-
134
- # Save the public key.
135
- def save_pk(hostname, public_key)
136
- pkeyfile = File.join(Puppet[:publickeydir], [hostname, "pem"].join('.'))
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