puppet 0.9.2 → 0.13.0

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 (213) hide show
  1. data/CHANGELOG +58 -0
  2. data/README +21 -18
  3. data/Rakefile +176 -36
  4. data/bin/puppet +34 -48
  5. data/bin/puppetca +41 -28
  6. data/bin/puppetd +87 -65
  7. data/bin/puppetdoc +99 -23
  8. data/bin/puppetmasterd +72 -91
  9. data/conf/redhat/client.init +80 -0
  10. data/conf/redhat/client.sysconfig +11 -0
  11. data/conf/redhat/fileserver.conf +12 -0
  12. data/conf/redhat/puppet.spec +130 -0
  13. data/conf/redhat/server.init +89 -0
  14. data/conf/redhat/server.sysconfig +9 -0
  15. data/examples/code/allatonce +2 -2
  16. data/examples/code/assignments +1 -1
  17. data/examples/code/classing +2 -2
  18. data/examples/code/components +2 -2
  19. data/examples/code/file.bl +5 -5
  20. data/examples/code/filedefaults +2 -2
  21. data/examples/code/fileparsing +1 -1
  22. data/examples/code/filerecursion +1 -1
  23. data/examples/code/functions +1 -1
  24. data/examples/code/groups +1 -1
  25. data/examples/code/importing +1 -1
  26. data/examples/code/nodes +1 -1
  27. data/examples/code/one +1 -1
  28. data/examples/code/relationships +2 -2
  29. data/examples/code/simpletests +5 -5
  30. data/examples/code/snippets/argumentdefaults +2 -2
  31. data/examples/code/snippets/casestatement +16 -8
  32. data/examples/code/snippets/classheirarchy.pp +4 -4
  33. data/examples/code/snippets/classincludes.pp +4 -4
  34. data/examples/code/snippets/classpathtest +2 -2
  35. data/examples/code/snippets/componentmetaparams.pp +11 -0
  36. data/examples/code/snippets/dirchmod +5 -5
  37. data/examples/code/snippets/emptyclass.pp +9 -0
  38. data/examples/code/snippets/failmissingexecpath.pp +1 -1
  39. data/examples/code/snippets/falsevalues.pp +1 -1
  40. data/examples/code/snippets/filecreate +5 -5
  41. data/examples/code/snippets/implicititeration +5 -5
  42. data/examples/code/snippets/multipleinstances +4 -4
  43. data/examples/code/snippets/namevartest +3 -3
  44. data/examples/code/snippets/scopetest +1 -1
  45. data/examples/code/snippets/selectorvalues.pp +3 -3
  46. data/examples/code/snippets/simpledefaults +2 -2
  47. data/examples/code/snippets/simpleselector +5 -5
  48. data/examples/code/snippets/singleary.pp +19 -0
  49. data/examples/root/etc/init.d/sleeper +3 -2
  50. data/ext/emacs/puppet-mode-init.el +6 -0
  51. data/ext/emacs/puppet-mode.el +189 -0
  52. data/ext/ldap/puppet.schema +17 -0
  53. data/ext/{module:puppet → module_puppet} +30 -31
  54. data/ext/vim/filetype.vim +9 -0
  55. data/ext/vim/puppet.vim +87 -0
  56. data/install.rb +63 -30
  57. data/lib/puppet.rb +216 -122
  58. data/lib/puppet/client.rb +51 -416
  59. data/lib/puppet/client/ca.rb +17 -0
  60. data/lib/puppet/client/dipper.rb +78 -0
  61. data/lib/puppet/client/file.rb +20 -0
  62. data/lib/puppet/client/log.rb +17 -0
  63. data/lib/puppet/client/master.rb +246 -0
  64. data/lib/puppet/client/proxy.rb +27 -0
  65. data/lib/puppet/client/status.rb +7 -0
  66. data/lib/puppet/config.rb +563 -13
  67. data/lib/puppet/daemon.rb +50 -22
  68. data/lib/puppet/element.rb +4 -4
  69. data/lib/puppet/event-loop.rb +1 -0
  70. data/lib/puppet/event-loop/better-definers.rb +367 -0
  71. data/lib/puppet/event-loop/event-loop.rb +355 -0
  72. data/lib/puppet/event-loop/signal-system.rb +220 -0
  73. data/lib/puppet/event.rb +9 -11
  74. data/lib/puppet/filetype.rb +195 -0
  75. data/lib/puppet/log.rb +35 -12
  76. data/lib/puppet/metric.rb +2 -2
  77. data/lib/puppet/networkclient.rb +145 -0
  78. data/lib/puppet/parameter.rb +335 -0
  79. data/lib/puppet/parser/ast.rb +42 -1453
  80. data/lib/puppet/parser/ast/astarray.rb +88 -0
  81. data/lib/puppet/parser/ast/branch.rb +47 -0
  82. data/lib/puppet/parser/ast/caseopt.rb +66 -0
  83. data/lib/puppet/parser/ast/casestatement.rb +78 -0
  84. data/lib/puppet/parser/ast/classdef.rb +78 -0
  85. data/lib/puppet/parser/ast/compdef.rb +111 -0
  86. data/lib/puppet/parser/ast/component.rb +105 -0
  87. data/lib/puppet/parser/ast/hostclass.rb +82 -0
  88. data/lib/puppet/parser/ast/leaf.rb +86 -0
  89. data/lib/puppet/parser/ast/node.rb +103 -0
  90. data/lib/puppet/parser/ast/nodedef.rb +68 -0
  91. data/lib/puppet/parser/ast/objectdef.rb +336 -0
  92. data/lib/puppet/parser/ast/objectparam.rb +30 -0
  93. data/lib/puppet/parser/ast/objectref.rb +76 -0
  94. data/lib/puppet/parser/ast/selector.rb +60 -0
  95. data/lib/puppet/parser/ast/typedefaults.rb +45 -0
  96. data/lib/puppet/parser/ast/vardef.rb +44 -0
  97. data/lib/puppet/parser/interpreter.rb +31 -14
  98. data/lib/puppet/parser/lexer.rb +2 -4
  99. data/lib/puppet/parser/parser.rb +332 -242
  100. data/lib/puppet/parser/scope.rb +55 -38
  101. data/lib/puppet/server.rb +43 -44
  102. data/lib/puppet/server/authstore.rb +3 -6
  103. data/lib/puppet/server/ca.rb +5 -2
  104. data/lib/puppet/server/filebucket.rb +2 -4
  105. data/lib/puppet/server/fileserver.rb +28 -12
  106. data/lib/puppet/server/logger.rb +15 -4
  107. data/lib/puppet/server/master.rb +62 -7
  108. data/lib/puppet/sslcertificates.rb +41 -607
  109. data/lib/puppet/sslcertificates/ca.rb +291 -0
  110. data/lib/puppet/sslcertificates/certificate.rb +283 -0
  111. data/lib/puppet/statechange.rb +6 -1
  112. data/lib/puppet/storage.rb +67 -56
  113. data/lib/puppet/transaction.rb +25 -9
  114. data/lib/puppet/transportable.rb +102 -22
  115. data/lib/puppet/type.rb +1096 -315
  116. data/lib/puppet/type/component.rb +30 -21
  117. data/lib/puppet/type/cron.rb +409 -448
  118. data/lib/puppet/type/exec.rb +234 -174
  119. data/lib/puppet/type/group.rb +65 -82
  120. data/lib/puppet/type/nameservice.rb +247 -3
  121. data/lib/puppet/type/nameservice/netinfo.rb +29 -40
  122. data/lib/puppet/type/nameservice/objectadd.rb +52 -66
  123. data/lib/puppet/type/nameservice/posix.rb +6 -194
  124. data/lib/puppet/type/package.rb +447 -295
  125. data/lib/puppet/type/package/apt.rb +51 -50
  126. data/lib/puppet/type/package/bsd.rb +82 -0
  127. data/lib/puppet/type/package/dpkg.rb +85 -88
  128. data/lib/puppet/type/package/rpm.rb +67 -63
  129. data/lib/puppet/type/package/sun.rb +119 -98
  130. data/lib/puppet/type/package/yum.rb +41 -37
  131. data/lib/puppet/type/parsedtype.rb +295 -0
  132. data/lib/puppet/type/parsedtype/host.rb +143 -0
  133. data/lib/puppet/type/parsedtype/port.rb +232 -0
  134. data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
  135. data/lib/puppet/type/pfile.rb +484 -460
  136. data/lib/puppet/type/pfile/checksum.rb +237 -181
  137. data/lib/puppet/type/pfile/content.rb +67 -0
  138. data/lib/puppet/type/pfile/ensure.rb +212 -0
  139. data/lib/puppet/type/pfile/group.rb +106 -105
  140. data/lib/puppet/type/pfile/mode.rb +98 -101
  141. data/lib/puppet/type/pfile/source.rb +228 -209
  142. data/lib/puppet/type/pfile/type.rb +18 -21
  143. data/lib/puppet/type/pfile/uid.rb +127 -130
  144. data/lib/puppet/type/pfilebucket.rb +68 -63
  145. data/lib/puppet/type/schedule.rb +341 -0
  146. data/lib/puppet/type/service.rb +351 -255
  147. data/lib/puppet/type/service/base.rb +9 -14
  148. data/lib/puppet/type/service/debian.rb +32 -38
  149. data/lib/puppet/type/service/init.rb +130 -130
  150. data/lib/puppet/type/service/smf.rb +48 -20
  151. data/lib/puppet/type/state.rb +229 -16
  152. data/lib/puppet/type/symlink.rb +51 -63
  153. data/lib/puppet/type/tidy.rb +105 -102
  154. data/lib/puppet/type/user.rb +118 -180
  155. data/lib/puppet/util.rb +100 -6
  156. data/test/certmgr/certmgr.rb +0 -1
  157. data/test/client/client.rb +4 -4
  158. data/test/executables/puppetbin.rb +7 -14
  159. data/test/executables/puppetca.rb +18 -24
  160. data/test/executables/puppetd.rb +7 -16
  161. data/test/executables/puppetmasterd.rb +7 -9
  162. data/test/executables/puppetmodule.rb +11 -16
  163. data/test/language/ast.rb +11 -7
  164. data/test/language/interpreter.rb +1 -1
  165. data/test/language/scope.rb +2 -0
  166. data/test/language/snippets.rb +30 -5
  167. data/test/language/transportable.rb +77 -0
  168. data/test/other/config.rb +316 -0
  169. data/test/other/events.rb +22 -21
  170. data/test/other/log.rb +14 -14
  171. data/test/other/metrics.rb +4 -8
  172. data/test/other/overrides.rb +5 -5
  173. data/test/other/relationships.rb +4 -2
  174. data/test/other/storage.rb +64 -3
  175. data/test/other/transactions.rb +20 -20
  176. data/test/parser/parser.rb +7 -4
  177. data/test/puppet/conffiles.rb +12 -12
  178. data/test/puppet/defaults.rb +13 -11
  179. data/test/puppet/utiltest.rb +14 -11
  180. data/test/puppettest.rb +156 -48
  181. data/test/server/bucket.rb +2 -2
  182. data/test/server/fileserver.rb +6 -6
  183. data/test/server/logger.rb +19 -11
  184. data/test/server/master.rb +33 -4
  185. data/test/server/server.rb +2 -7
  186. data/test/types/basic.rb +5 -7
  187. data/test/types/component.rb +22 -18
  188. data/test/types/cron.rb +111 -44
  189. data/test/types/exec.rb +116 -59
  190. data/test/types/file.rb +262 -137
  191. data/test/types/filebucket.rb +13 -15
  192. data/test/types/fileignoresource.rb +12 -16
  193. data/test/types/filesources.rb +73 -48
  194. data/test/types/filetype.rb +13 -15
  195. data/test/types/group.rb +15 -13
  196. data/test/types/host.rb +146 -0
  197. data/test/types/package.rb +74 -63
  198. data/test/types/port.rb +139 -0
  199. data/test/types/query.rb +8 -8
  200. data/test/types/schedule.rb +335 -0
  201. data/test/types/service.rb +137 -21
  202. data/test/types/sshkey.rb +140 -0
  203. data/test/types/symlink.rb +3 -5
  204. data/test/types/tidy.rb +5 -14
  205. data/test/types/type.rb +67 -11
  206. data/test/types/user.rb +25 -23
  207. metadata +186 -122
  208. data/lib/puppet/type/pfile/create.rb +0 -108
  209. data/lib/puppet/type/pprocess.rb +0 -97
  210. data/lib/puppet/type/typegen.rb +0 -149
  211. data/lib/puppet/type/typegen/filerecord.rb +0 -243
  212. data/lib/puppet/type/typegen/filetype.rb +0 -316
  213. data/test/other/state.rb +0 -106
@@ -0,0 +1,291 @@
1
+ class Puppet::SSLCertificates::CA
2
+ Certificate = Puppet::SSLCertificates::Certificate
3
+ attr_accessor :keyfile, :file, :config, :dir, :cert
4
+
5
+ Puppet.setdefaults("ca",
6
+ [:certdir, "$ssldir/certs", "The certificate directory."],
7
+ [:publickeydir, "$ssldir/public_keys", "The public key directory."],
8
+ [:privatekeydir, "$ssldir/private_keys", "The private key directory."],
9
+ [:cadir, "$ssldir/ca",
10
+ "The root directory for the certificate authority."],
11
+ [:cacert, "$cadir/ca_crt.pem", "The CA certificate."],
12
+ [:cakey, "$cadir/ca_key.pem", "The CA private key."],
13
+ [:capub, "$cadir/ca_pub.pem", "The CA public key."],
14
+ [:caprivatedir, "$cadir/private",
15
+ "Where the CA stores private certificate information."],
16
+ [:csrdir, "$cadir/requests",
17
+ "Where the CA stores certificate requests"],
18
+ [:signeddir, "$cadir/signed",
19
+ "Where the CA stores signed certificates."],
20
+ [:capass, "$caprivatedir/ca.pass",
21
+ "Where the CA stores the password for the private key"],
22
+ [:serial, "$cadir/serial",
23
+ "Where the serial number for certificates is stored."],
24
+ [:privatedir, "$ssldir/private",
25
+ "Where the client stores private certificate information."],
26
+ [:passfile, "$privatedir/password",
27
+ "Where puppetd stores the password for its private key. Generally
28
+ unused."],
29
+ [:autosign, "$confdir/autosign.conf",
30
+ "Whether to enable autosign. Valid values are true (which autosigns
31
+ any key request, and is a very bad idea), false (which never autosigns
32
+ any key request), and the path to a file, which uses that configuration
33
+ file to determine which keys to sign."],
34
+ [:ca_days, 1825, "How long a certificate should be valid."],
35
+ [:ca_md, "md5", "The type of hash used in certificates."],
36
+ [:req_bits, 2048, "The bit length of the certificates."],
37
+ [:keylength, 1024, "The bit length of keys."]
38
+ )
39
+
40
+ #@@params.each { |param|
41
+ # Puppet.setdefault(param,@@defaults[param])
42
+ #}
43
+
44
+ def certfile
45
+ @config[:cacert]
46
+ end
47
+
48
+ def host2csrfile(hostname)
49
+ File.join(Puppet[:csrdir], [hostname, "pem"].join("."))
50
+ end
51
+
52
+ # this stores signed certs in a directory unrelated to
53
+ # normal client certs
54
+ def host2certfile(hostname)
55
+ File.join(Puppet[:signeddir], [hostname, "pem"].join("."))
56
+ end
57
+
58
+ def thing2name(thing)
59
+ thing.subject.to_a.find { |ary|
60
+ ary[0] == "CN"
61
+ }[1]
62
+ end
63
+
64
+ def initialize(hash = {})
65
+ self.setconfig(hash)
66
+
67
+ if Puppet[:capass]
68
+ if FileTest.exists?(Puppet[:capass])
69
+ #puts "Reading %s" % Puppet[:capass]
70
+ #system "ls -al %s" % Puppet[:capass]
71
+ #File.read Puppet[:capass]
72
+ Puppet.info "Getting pass"
73
+ @config[:password] = self.getpass
74
+ else
75
+ # Don't create a password if the cert already exists
76
+ unless FileTest.exists?(@config[:cacert])
77
+ Puppet.info "Genning pass"
78
+ @config[:password] = self.genpass
79
+ end
80
+ end
81
+ end
82
+
83
+ self.getcert
84
+ unless FileTest.exists?(@config[:serial])
85
+ File.open(@config[:serial], "w") { |f|
86
+ f << "%04X" % 1
87
+ }
88
+ end
89
+ end
90
+
91
+ def genpass
92
+ pass = ""
93
+ 20.times { pass += (rand(74) + 48).chr }
94
+
95
+ Puppet.recmkdir(File.dirname(@config[:capass]))
96
+ begin
97
+ File.open(@config[:capass], "w", 0600) { |f| f.print pass }
98
+ rescue Errno::EACCES => detail
99
+ raise Puppet::Error, detail.to_s
100
+ end
101
+ return pass
102
+ end
103
+
104
+ def getpass
105
+ if @config[:capass] and File.readable?(@config[:capass])
106
+ return File.read(@config[:capass])
107
+ else
108
+ raise Puppet::Error, "Could not read CA passfile %s" % @config[:capass]
109
+ end
110
+ end
111
+
112
+ def getcert
113
+ if FileTest.exists?(@config[:cacert])
114
+ @cert = OpenSSL::X509::Certificate.new(
115
+ File.read(@config[:cacert])
116
+ )
117
+ else
118
+ self.mkrootcert
119
+ end
120
+ end
121
+
122
+ def getclientcsr(host)
123
+ csrfile = host2csrfile(host)
124
+ unless File.exists?(csrfile)
125
+ return nil
126
+ end
127
+
128
+ return OpenSSL::X509::Request.new(File.read(csrfile))
129
+ end
130
+
131
+ def getclientcert(host)
132
+ certfile = host2certfile(host)
133
+ unless File.exists?(certfile)
134
+ return [nil, nil]
135
+ end
136
+
137
+ return [OpenSSL::X509::Certificate.new(File.read(certfile)), @cert]
138
+ end
139
+
140
+ def list
141
+ return Dir.entries(Puppet[:csrdir]).reject { |file|
142
+ file =~ /^\.+$/
143
+ }.collect { |file|
144
+ file.sub(/\.pem$/, '')
145
+ }
146
+ end
147
+
148
+ def mkrootcert
149
+ cert = Certificate.new(
150
+ :name => "CAcert",
151
+ :cert => @config[:cacert],
152
+ :encrypt => @config[:capass],
153
+ :key => @config[:cakey],
154
+ :selfsign => true,
155
+ :length => 1825,
156
+ :type => :ca
157
+ )
158
+ @cert = cert.mkselfsigned
159
+ File.open(@config[:cacert], "w", 0660) { |f|
160
+ f.puts @cert.to_pem
161
+ }
162
+ @key = cert.key
163
+ return cert
164
+ end
165
+
166
+ def removeclientcsr(host)
167
+ csrfile = host2csrfile(host)
168
+ unless File.exists?(csrfile)
169
+ raise Puppet::Error, "No certificate request for %s" % host
170
+ end
171
+
172
+ File.unlink(csrfile)
173
+ end
174
+
175
+ def setconfig(hash)
176
+ @config = {}
177
+ Puppet.config.params("ca").each { |param|
178
+ param = param.intern if param.is_a? String
179
+ if hash.include?(param)
180
+ @config[param] = hash[param]
181
+ Puppet[param] = hash[param]
182
+ hash.delete(param)
183
+ else
184
+ @config[param] = Puppet[param]
185
+ end
186
+ }
187
+
188
+ if hash.include?(:password)
189
+ @config[:password] = hash[:password]
190
+ hash.delete(:password)
191
+ end
192
+
193
+ if hash.length > 0
194
+ raise ArgumentError, "Unknown parameters %s" % hash.keys.join(",")
195
+ end
196
+
197
+ [:cadir, :csrdir, :signeddir].each { |dir|
198
+ unless @config[dir]
199
+ raise Puppet::DevError, "%s is undefined" % dir
200
+ end
201
+ unless FileTest.exists?(@config[dir])
202
+ Puppet.recmkdir(@config[dir])
203
+ end
204
+ }
205
+ end
206
+
207
+ def sign(csr)
208
+ unless csr.is_a?(OpenSSL::X509::Request)
209
+ raise Puppet::Error,
210
+ "CA#sign only accepts OpenSSL::X509::Request objects, not %s" %
211
+ csr.class
212
+ end
213
+
214
+ unless csr.verify(csr.public_key)
215
+ raise Puppet::Error, "CSR sign verification failed"
216
+ end
217
+
218
+ # i should probably check key length...
219
+
220
+ # read the ca cert in
221
+ cacert = OpenSSL::X509::Certificate.new(
222
+ File.read(@config[:cacert])
223
+ )
224
+
225
+ cakey = nil
226
+ if @config[:password]
227
+ cakey = OpenSSL::PKey::RSA.new(
228
+ File.read(@config[:cakey]), @config[:password]
229
+ )
230
+ else
231
+ system("ls -al %s" % Puppet[:capass])
232
+ cakey = OpenSSL::PKey::RSA.new(
233
+ File.read(@config[:cakey])
234
+ )
235
+ end
236
+
237
+ unless cacert.check_private_key(cakey)
238
+ raise Puppet::Error, "CA Certificate is invalid"
239
+ end
240
+
241
+ serial = File.read(@config[:serial]).chomp.hex
242
+ newcert = Puppet::SSLCertificates.mkcert(
243
+ :type => :server,
244
+ :name => csr.subject,
245
+ :days => @config[:ca_days],
246
+ :issuer => cacert,
247
+ :serial => serial,
248
+ :publickey => csr.public_key
249
+ )
250
+
251
+ # increment the serial
252
+ File.open(@config[:serial], "w") { |f|
253
+ f << "%04X" % (serial + 1)
254
+ }
255
+
256
+ newcert.sign(cakey, OpenSSL::Digest::SHA1.new)
257
+
258
+ self.storeclientcert(newcert)
259
+
260
+ return [newcert, cacert]
261
+ end
262
+
263
+ def storeclientcsr(csr)
264
+ host = thing2name(csr)
265
+
266
+ csrfile = host2csrfile(host)
267
+ if File.exists?(csrfile)
268
+ raise Puppet::Error, "Certificate request for %s already exists" % host
269
+ end
270
+
271
+ File.open(csrfile, "w", 0660) { |f|
272
+ f.print csr.to_pem
273
+ }
274
+ end
275
+
276
+ def storeclientcert(cert)
277
+ host = thing2name(cert)
278
+
279
+ certfile = host2certfile(host)
280
+ if File.exists?(certfile)
281
+ Puppet.notice "Overwriting signed certificate %s for %s" %
282
+ [certfile, host]
283
+ end
284
+
285
+ File.open(certfile, "w", 0660) { |f|
286
+ f.print cert.to_pem
287
+ }
288
+ end
289
+ end
290
+
291
+ # $Id: ca.rb 873 2006-02-07 23:12:33Z luke $
@@ -0,0 +1,283 @@
1
+ class Puppet::SSLCertificates::Certificate
2
+ SSLCertificates = Puppet::SSLCertificates
3
+
4
+ attr_accessor :certfile, :keyfile, :name, :dir, :hash, :type
5
+ attr_accessor :key, :cert, :csr, :cacert
6
+
7
+ @@params2names = {
8
+ :name => "CN",
9
+ :state => "ST",
10
+ :country => "C",
11
+ :email => "emailAddress",
12
+ :org => "O",
13
+ :city => "L",
14
+ :ou => "OU"
15
+ }
16
+
17
+ def certname
18
+ OpenSSL::X509::Name.new self.subject
19
+ end
20
+
21
+ def delete
22
+ [@certfile,@keyfile].each { |file|
23
+ if FileTest.exists?(file)
24
+ File.unlink(file)
25
+ end
26
+ }
27
+
28
+ if defined? @hash and @hash
29
+ if FileTest.symlink?(@hash)
30
+ File.unlink(@hash)
31
+ end
32
+ end
33
+ end
34
+
35
+ def exists?
36
+ return FileTest.exists?(@certfile)
37
+ end
38
+
39
+ def getkey
40
+ unless FileTest.exists?(@keyfile)
41
+ self.mkkey()
42
+ end
43
+ if @password
44
+ @key = OpenSSL::PKey::RSA.new(
45
+ File.read(@keyfile),
46
+ @password
47
+ )
48
+ else
49
+ @key = OpenSSL::PKey::RSA.new(
50
+ File.read(@keyfile)
51
+ )
52
+ end
53
+ end
54
+
55
+ def initialize(hash)
56
+ unless hash.include?(:name)
57
+ raise Puppet::Error, "You must specify the common name for the certificate"
58
+ end
59
+ @name = hash[:name]
60
+
61
+ # init a few variables
62
+ @cert = @key = @csr = nil
63
+
64
+ if hash.include?(:cert)
65
+ @certfile = hash[:cert]
66
+ @dir = File.dirname(@certfile)
67
+ else
68
+ @dir = hash[:dir] || Puppet[:certdir]
69
+ @certfile = File.join(@dir, @name)
70
+ end
71
+
72
+ @cacertfile ||= File.join(Puppet[:certdir], "ca.pem")
73
+
74
+ unless FileTest.directory?(@dir)
75
+ Puppet.recmkdir(@dir)
76
+ end
77
+
78
+ unless @certfile =~ /\.pem$/
79
+ @certfile += ".pem"
80
+ end
81
+ @keyfile = hash[:key] || File.join(
82
+ Puppet[:privatekeydir], [@name,"pem"].join(".")
83
+ )
84
+ unless FileTest.directory?(@dir)
85
+ Puppet.recmkdir(@dir)
86
+ end
87
+
88
+ [@keyfile].each { |file|
89
+ dir = File.dirname(file)
90
+
91
+ unless FileTest.directory?(dir)
92
+ Puppet.recmkdir(dir)
93
+ end
94
+ }
95
+
96
+ @days = hash[:length] || 365
97
+ @selfsign = hash[:selfsign] || false
98
+ @encrypt = hash[:encrypt] || false
99
+ @replace = hash[:replace] || false
100
+ @issuer = hash[:issuer] || nil
101
+
102
+ if hash.include?(:type)
103
+ case hash[:type]
104
+ when :ca, :client, :server: @type = hash[:type]
105
+ else
106
+ raise "Invalid Cert type %s" % hash[:type]
107
+ end
108
+ else
109
+ @type = :client
110
+ end
111
+
112
+ @params = {:name => @name}
113
+ [:state, :country, :email, :org, :ou].each { |param|
114
+ if hash.include?(param)
115
+ @params[param] = hash[param]
116
+ end
117
+ }
118
+
119
+ if @encrypt
120
+ if @encrypt =~ /^\//
121
+ File.open(@encrypt) { |f|
122
+ @password = f.read.chomp
123
+ }
124
+ else
125
+ raise Puppet::Error, ":encrypt must be a path to a pass phrase file"
126
+ end
127
+ else
128
+ @password = nil
129
+ end
130
+
131
+ if hash.include?(:selfsign)
132
+ @selfsign = hash[:selfsign]
133
+ else
134
+ @selfsign = false
135
+ end
136
+ end
137
+
138
+ # this only works for servers, not for users
139
+ def mkcsr
140
+ unless defined? @key and @key
141
+ self.getkey
142
+ end
143
+
144
+ name = OpenSSL::X509::Name.new self.subject
145
+
146
+ @csr = OpenSSL::X509::Request.new
147
+ @csr.version = 0
148
+ @csr.subject = name
149
+ @csr.public_key = @key.public_key
150
+ @csr.sign(@key, OpenSSL::Digest::SHA1.new)
151
+
152
+ #File.open(@csrfile, "w") { |f|
153
+ # f << @csr.to_pem
154
+ #}
155
+
156
+ unless @csr.verify(@key.public_key)
157
+ raise Puppet::Error, "CSR sign verification failed"
158
+ end
159
+
160
+ return @csr
161
+ end
162
+
163
+ def mkkey
164
+ # @key is the file
165
+
166
+ @key = OpenSSL::PKey::RSA.new(1024)
167
+ # { |p,n|
168
+ # case p
169
+ # when 0; Puppet.info "key info: ." # BN_generate_prime
170
+ # when 1; Puppet.info "key info: +" # BN_generate_prime
171
+ # when 2; Puppet.info "key info: *" # searching good prime,
172
+ # # n = #of try,
173
+ # # but also data from BN_generate_prime
174
+ # when 3; Puppet.info "key info: \n" # found good prime, n==0 - p, n==1 - q,
175
+ # # but also data from BN_generate_prime
176
+ # else; Puppet.info "key info: *" # BN_generate_prime
177
+ # end
178
+ # }
179
+
180
+ if @password
181
+ #passwdproc = proc { @password }
182
+ keytext = @key.export(
183
+ OpenSSL::Cipher::DES.new(:EDE3, :CBC),
184
+ @password
185
+ )
186
+ File.open(@keyfile, "w", 0400) { |f|
187
+ f << keytext
188
+ }
189
+ else
190
+ File.open(@keyfile, "w", 0400) { |f|
191
+ f << @key.to_pem
192
+ }
193
+ end
194
+
195
+ #cmd = "#{ossl} genrsa -out #{@key} 1024"
196
+ end
197
+
198
+ def mkselfsigned
199
+ unless defined? @key and @key
200
+ self.getkey
201
+ end
202
+
203
+ if defined? @cert and @cert
204
+ raise Puppet::Error, "Cannot replace existing certificate"
205
+ end
206
+
207
+ args = {
208
+ :name => self.certname,
209
+ :days => @days,
210
+ :issuer => nil,
211
+ :serial => 0x0,
212
+ :publickey => @key.public_key
213
+ }
214
+ if @type
215
+ args[:type] = @type
216
+ else
217
+ args[:type] = :server
218
+ end
219
+ @cert = SSLCertificates.mkcert(args)
220
+
221
+ @cert.sign(@key, OpenSSL::Digest::SHA1.new) if @selfsign
222
+
223
+ return @cert
224
+ end
225
+
226
+ def subject(string = false)
227
+ subj = @@params2names.collect { |param, name|
228
+ if @params.include?(param)
229
+ [name, @params[param]]
230
+ end
231
+ }.reject { |ary| ary.nil? }
232
+
233
+ if string
234
+ return "/" + subj.collect { |ary|
235
+ "%s=%s" % ary
236
+ }.join("/") + "/"
237
+ else
238
+ return subj
239
+ end
240
+ end
241
+
242
+ # verify that we can track down the cert chain or whatever
243
+ def verify
244
+ "openssl verify -verbose -CAfile /home/luke/.puppet/ssl/certs/ca.pem -purpose sslserver culain.madstop.com.pem"
245
+ end
246
+
247
+ def write
248
+ files = {
249
+ @certfile => @cert,
250
+ @keyfile => @key,
251
+ }
252
+ if defined? @cacert
253
+ files[@cacertfile] = @cacert
254
+ end
255
+
256
+ files.each { |file,thing|
257
+ if defined? thing and thing
258
+ if FileTest.exists?(file)
259
+ next
260
+ end
261
+
262
+ text = nil
263
+
264
+ if thing.is_a?(OpenSSL::PKey::RSA) and @password
265
+ text = thing.export(
266
+ OpenSSL::Cipher::DES.new(:EDE3, :CBC),
267
+ @password
268
+ )
269
+ else
270
+ text = thing.to_pem
271
+ end
272
+
273
+ File.open(file, "w", 0660) { |f| f.print text }
274
+ end
275
+ }
276
+
277
+ if defined? @cacert
278
+ SSLCertificates.mkhash(Puppet[:certdir], @cacert, @cacertfile)
279
+ end
280
+ end
281
+ end
282
+
283
+ # $Id: certificate.rb 873 2006-02-07 23:12:33Z luke $