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.
- data/CHANGELOG +58 -0
- data/README +21 -18
- data/Rakefile +176 -36
- data/bin/puppet +34 -48
- data/bin/puppetca +41 -28
- data/bin/puppetd +87 -65
- data/bin/puppetdoc +99 -23
- data/bin/puppetmasterd +72 -91
- data/conf/redhat/client.init +80 -0
- data/conf/redhat/client.sysconfig +11 -0
- data/conf/redhat/fileserver.conf +12 -0
- data/conf/redhat/puppet.spec +130 -0
- data/conf/redhat/server.init +89 -0
- data/conf/redhat/server.sysconfig +9 -0
- data/examples/code/allatonce +2 -2
- data/examples/code/assignments +1 -1
- data/examples/code/classing +2 -2
- data/examples/code/components +2 -2
- data/examples/code/file.bl +5 -5
- data/examples/code/filedefaults +2 -2
- data/examples/code/fileparsing +1 -1
- data/examples/code/filerecursion +1 -1
- data/examples/code/functions +1 -1
- data/examples/code/groups +1 -1
- data/examples/code/importing +1 -1
- data/examples/code/nodes +1 -1
- data/examples/code/one +1 -1
- data/examples/code/relationships +2 -2
- data/examples/code/simpletests +5 -5
- data/examples/code/snippets/argumentdefaults +2 -2
- data/examples/code/snippets/casestatement +16 -8
- data/examples/code/snippets/classheirarchy.pp +4 -4
- data/examples/code/snippets/classincludes.pp +4 -4
- data/examples/code/snippets/classpathtest +2 -2
- data/examples/code/snippets/componentmetaparams.pp +11 -0
- data/examples/code/snippets/dirchmod +5 -5
- data/examples/code/snippets/emptyclass.pp +9 -0
- data/examples/code/snippets/failmissingexecpath.pp +1 -1
- data/examples/code/snippets/falsevalues.pp +1 -1
- data/examples/code/snippets/filecreate +5 -5
- data/examples/code/snippets/implicititeration +5 -5
- data/examples/code/snippets/multipleinstances +4 -4
- data/examples/code/snippets/namevartest +3 -3
- data/examples/code/snippets/scopetest +1 -1
- data/examples/code/snippets/selectorvalues.pp +3 -3
- data/examples/code/snippets/simpledefaults +2 -2
- data/examples/code/snippets/simpleselector +5 -5
- data/examples/code/snippets/singleary.pp +19 -0
- data/examples/root/etc/init.d/sleeper +3 -2
- data/ext/emacs/puppet-mode-init.el +6 -0
- data/ext/emacs/puppet-mode.el +189 -0
- data/ext/ldap/puppet.schema +17 -0
- data/ext/{module:puppet → module_puppet} +30 -31
- data/ext/vim/filetype.vim +9 -0
- data/ext/vim/puppet.vim +87 -0
- data/install.rb +63 -30
- data/lib/puppet.rb +216 -122
- data/lib/puppet/client.rb +51 -416
- data/lib/puppet/client/ca.rb +17 -0
- data/lib/puppet/client/dipper.rb +78 -0
- data/lib/puppet/client/file.rb +20 -0
- data/lib/puppet/client/log.rb +17 -0
- data/lib/puppet/client/master.rb +246 -0
- data/lib/puppet/client/proxy.rb +27 -0
- data/lib/puppet/client/status.rb +7 -0
- data/lib/puppet/config.rb +563 -13
- data/lib/puppet/daemon.rb +50 -22
- data/lib/puppet/element.rb +4 -4
- data/lib/puppet/event-loop.rb +1 -0
- data/lib/puppet/event-loop/better-definers.rb +367 -0
- data/lib/puppet/event-loop/event-loop.rb +355 -0
- data/lib/puppet/event-loop/signal-system.rb +220 -0
- data/lib/puppet/event.rb +9 -11
- data/lib/puppet/filetype.rb +195 -0
- data/lib/puppet/log.rb +35 -12
- data/lib/puppet/metric.rb +2 -2
- data/lib/puppet/networkclient.rb +145 -0
- data/lib/puppet/parameter.rb +335 -0
- data/lib/puppet/parser/ast.rb +42 -1453
- data/lib/puppet/parser/ast/astarray.rb +88 -0
- data/lib/puppet/parser/ast/branch.rb +47 -0
- data/lib/puppet/parser/ast/caseopt.rb +66 -0
- data/lib/puppet/parser/ast/casestatement.rb +78 -0
- data/lib/puppet/parser/ast/classdef.rb +78 -0
- data/lib/puppet/parser/ast/compdef.rb +111 -0
- data/lib/puppet/parser/ast/component.rb +105 -0
- data/lib/puppet/parser/ast/hostclass.rb +82 -0
- data/lib/puppet/parser/ast/leaf.rb +86 -0
- data/lib/puppet/parser/ast/node.rb +103 -0
- data/lib/puppet/parser/ast/nodedef.rb +68 -0
- data/lib/puppet/parser/ast/objectdef.rb +336 -0
- data/lib/puppet/parser/ast/objectparam.rb +30 -0
- data/lib/puppet/parser/ast/objectref.rb +76 -0
- data/lib/puppet/parser/ast/selector.rb +60 -0
- data/lib/puppet/parser/ast/typedefaults.rb +45 -0
- data/lib/puppet/parser/ast/vardef.rb +44 -0
- data/lib/puppet/parser/interpreter.rb +31 -14
- data/lib/puppet/parser/lexer.rb +2 -4
- data/lib/puppet/parser/parser.rb +332 -242
- data/lib/puppet/parser/scope.rb +55 -38
- data/lib/puppet/server.rb +43 -44
- data/lib/puppet/server/authstore.rb +3 -6
- data/lib/puppet/server/ca.rb +5 -2
- data/lib/puppet/server/filebucket.rb +2 -4
- data/lib/puppet/server/fileserver.rb +28 -12
- data/lib/puppet/server/logger.rb +15 -4
- data/lib/puppet/server/master.rb +62 -7
- data/lib/puppet/sslcertificates.rb +41 -607
- data/lib/puppet/sslcertificates/ca.rb +291 -0
- data/lib/puppet/sslcertificates/certificate.rb +283 -0
- data/lib/puppet/statechange.rb +6 -1
- data/lib/puppet/storage.rb +67 -56
- data/lib/puppet/transaction.rb +25 -9
- data/lib/puppet/transportable.rb +102 -22
- data/lib/puppet/type.rb +1096 -315
- data/lib/puppet/type/component.rb +30 -21
- data/lib/puppet/type/cron.rb +409 -448
- data/lib/puppet/type/exec.rb +234 -174
- data/lib/puppet/type/group.rb +65 -82
- data/lib/puppet/type/nameservice.rb +247 -3
- data/lib/puppet/type/nameservice/netinfo.rb +29 -40
- data/lib/puppet/type/nameservice/objectadd.rb +52 -66
- data/lib/puppet/type/nameservice/posix.rb +6 -194
- data/lib/puppet/type/package.rb +447 -295
- data/lib/puppet/type/package/apt.rb +51 -50
- data/lib/puppet/type/package/bsd.rb +82 -0
- data/lib/puppet/type/package/dpkg.rb +85 -88
- data/lib/puppet/type/package/rpm.rb +67 -63
- data/lib/puppet/type/package/sun.rb +119 -98
- data/lib/puppet/type/package/yum.rb +41 -37
- data/lib/puppet/type/parsedtype.rb +295 -0
- data/lib/puppet/type/parsedtype/host.rb +143 -0
- data/lib/puppet/type/parsedtype/port.rb +232 -0
- data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
- data/lib/puppet/type/pfile.rb +484 -460
- data/lib/puppet/type/pfile/checksum.rb +237 -181
- data/lib/puppet/type/pfile/content.rb +67 -0
- data/lib/puppet/type/pfile/ensure.rb +212 -0
- data/lib/puppet/type/pfile/group.rb +106 -105
- data/lib/puppet/type/pfile/mode.rb +98 -101
- data/lib/puppet/type/pfile/source.rb +228 -209
- data/lib/puppet/type/pfile/type.rb +18 -21
- data/lib/puppet/type/pfile/uid.rb +127 -130
- data/lib/puppet/type/pfilebucket.rb +68 -63
- data/lib/puppet/type/schedule.rb +341 -0
- data/lib/puppet/type/service.rb +351 -255
- data/lib/puppet/type/service/base.rb +9 -14
- data/lib/puppet/type/service/debian.rb +32 -38
- data/lib/puppet/type/service/init.rb +130 -130
- data/lib/puppet/type/service/smf.rb +48 -20
- data/lib/puppet/type/state.rb +229 -16
- data/lib/puppet/type/symlink.rb +51 -63
- data/lib/puppet/type/tidy.rb +105 -102
- data/lib/puppet/type/user.rb +118 -180
- data/lib/puppet/util.rb +100 -6
- data/test/certmgr/certmgr.rb +0 -1
- data/test/client/client.rb +4 -4
- data/test/executables/puppetbin.rb +7 -14
- data/test/executables/puppetca.rb +18 -24
- data/test/executables/puppetd.rb +7 -16
- data/test/executables/puppetmasterd.rb +7 -9
- data/test/executables/puppetmodule.rb +11 -16
- data/test/language/ast.rb +11 -7
- data/test/language/interpreter.rb +1 -1
- data/test/language/scope.rb +2 -0
- data/test/language/snippets.rb +30 -5
- data/test/language/transportable.rb +77 -0
- data/test/other/config.rb +316 -0
- data/test/other/events.rb +22 -21
- data/test/other/log.rb +14 -14
- data/test/other/metrics.rb +4 -8
- data/test/other/overrides.rb +5 -5
- data/test/other/relationships.rb +4 -2
- data/test/other/storage.rb +64 -3
- data/test/other/transactions.rb +20 -20
- data/test/parser/parser.rb +7 -4
- data/test/puppet/conffiles.rb +12 -12
- data/test/puppet/defaults.rb +13 -11
- data/test/puppet/utiltest.rb +14 -11
- data/test/puppettest.rb +156 -48
- data/test/server/bucket.rb +2 -2
- data/test/server/fileserver.rb +6 -6
- data/test/server/logger.rb +19 -11
- data/test/server/master.rb +33 -4
- data/test/server/server.rb +2 -7
- data/test/types/basic.rb +5 -7
- data/test/types/component.rb +22 -18
- data/test/types/cron.rb +111 -44
- data/test/types/exec.rb +116 -59
- data/test/types/file.rb +262 -137
- data/test/types/filebucket.rb +13 -15
- data/test/types/fileignoresource.rb +12 -16
- data/test/types/filesources.rb +73 -48
- data/test/types/filetype.rb +13 -15
- data/test/types/group.rb +15 -13
- data/test/types/host.rb +146 -0
- data/test/types/package.rb +74 -63
- data/test/types/port.rb +139 -0
- data/test/types/query.rb +8 -8
- data/test/types/schedule.rb +335 -0
- data/test/types/service.rb +137 -21
- data/test/types/sshkey.rb +140 -0
- data/test/types/symlink.rb +3 -5
- data/test/types/tidy.rb +5 -14
- data/test/types/type.rb +67 -11
- data/test/types/user.rb +25 -23
- metadata +186 -122
- data/lib/puppet/type/pfile/create.rb +0 -108
- data/lib/puppet/type/pprocess.rb +0 -97
- data/lib/puppet/type/typegen.rb +0 -149
- data/lib/puppet/type/typegen/filerecord.rb +0 -243
- data/lib/puppet/type/typegen/filetype.rb +0 -316
- data/test/other/state.rb +0 -106
data/lib/puppet/server/logger.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
1
3
|
module Puppet
|
2
|
-
class Server
|
4
|
+
class Server
|
3
5
|
class LoggerError < RuntimeError; end
|
4
6
|
|
5
7
|
# Receive logs from remote hosts.
|
@@ -10,18 +12,27 @@ class Server # :nodoc:
|
|
10
12
|
|
11
13
|
# accept a log message from a client, and route it accordingly
|
12
14
|
def addlog(message, client = nil, clientip = nil)
|
15
|
+
unless message
|
16
|
+
raise Puppet::DevError, "Did not receive message"
|
17
|
+
end
|
18
|
+
|
19
|
+
Puppet.info message.inspect
|
13
20
|
# if the client is set, then we're not local
|
14
21
|
if client
|
15
22
|
begin
|
16
|
-
message =
|
23
|
+
message = YAML.load(CGI.unescape(message))
|
17
24
|
#message = message
|
18
25
|
rescue => detail
|
19
26
|
raise XMLRPC::FaultException.new(
|
20
|
-
1, "Could not
|
27
|
+
1, "Could not unYAML log message from %s" % client
|
21
28
|
)
|
22
29
|
end
|
23
30
|
end
|
24
31
|
|
32
|
+
unless message
|
33
|
+
raise Puppet::DevError, "Could not resurrect message"
|
34
|
+
end
|
35
|
+
|
25
36
|
# Mark it as remote, so it's not sent to syslog
|
26
37
|
message.remote = true
|
27
38
|
|
@@ -40,4 +51,4 @@ class Server # :nodoc:
|
|
40
51
|
end
|
41
52
|
end
|
42
53
|
|
43
|
-
# $Id: logger.rb
|
54
|
+
# $Id: logger.rb 846 2006-01-20 20:38:01Z luke $
|
data/lib/puppet/server/master.rb
CHANGED
@@ -3,6 +3,7 @@ require 'puppet'
|
|
3
3
|
require 'puppet/parser/interpreter'
|
4
4
|
require 'puppet/sslcertificates'
|
5
5
|
require 'xmlrpc/server'
|
6
|
+
require 'yaml'
|
6
7
|
|
7
8
|
module Puppet
|
8
9
|
class Server
|
@@ -13,8 +14,26 @@ class Server
|
|
13
14
|
|
14
15
|
@interface = XMLRPC::Service::Interface.new("puppetmaster") { |iface|
|
15
16
|
iface.add_method("string getconfig(string)")
|
17
|
+
iface.add_method("int freshness()")
|
16
18
|
}
|
17
19
|
|
20
|
+
def filetimeout
|
21
|
+
@interpreter.filetimeout
|
22
|
+
end
|
23
|
+
|
24
|
+
def filetimeout=(int)
|
25
|
+
@interpreter.filetimeout = int
|
26
|
+
end
|
27
|
+
|
28
|
+
# Tell a client whether there's a fresh config for it
|
29
|
+
def freshness(client = nil, clientip = nil)
|
30
|
+
if defined? @interpreter
|
31
|
+
return @interpreter.parsedate
|
32
|
+
else
|
33
|
+
return 0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
18
37
|
def initialize(hash = {})
|
19
38
|
|
20
39
|
# FIXME this should all be s/:File/:Manifest/g or something
|
@@ -34,9 +53,11 @@ class Server
|
|
34
53
|
@ca = nil
|
35
54
|
end
|
36
55
|
|
56
|
+
@parsecheck = hash[:FileTimeout] || 15
|
57
|
+
|
37
58
|
Puppet.debug("Creating interpreter")
|
38
59
|
|
39
|
-
args = {:Manifest => @file}
|
60
|
+
args = {:Manifest => @file, :ParseCheck => @parsecheck}
|
40
61
|
|
41
62
|
if hash.include?(:UseNodes)
|
42
63
|
args[:UseNodes] = hash[:UseNodes]
|
@@ -57,7 +78,7 @@ class Server
|
|
57
78
|
end
|
58
79
|
end
|
59
80
|
|
60
|
-
def getconfig(facts, client = nil, clientip = nil)
|
81
|
+
def getconfig(facts, format = "marshal", client = nil, clientip = nil)
|
61
82
|
if @local
|
62
83
|
# we don't need to do anything, since we should already
|
63
84
|
# have raw objects
|
@@ -66,11 +87,26 @@ class Server
|
|
66
87
|
Puppet.debug "Our client is remote"
|
67
88
|
|
68
89
|
# XXX this should definitely be done in the protocol, somehow
|
69
|
-
|
70
|
-
|
71
|
-
|
90
|
+
case format
|
91
|
+
when "marshal":
|
92
|
+
begin
|
93
|
+
facts = Marshal::load(CGI.unescape(facts))
|
94
|
+
rescue => detail
|
95
|
+
raise XMLRPC::FaultException.new(
|
96
|
+
1, "Could not rebuild facts"
|
97
|
+
)
|
98
|
+
end
|
99
|
+
when "yaml":
|
100
|
+
begin
|
101
|
+
facts = YAML.load(CGI.unescape(facts))
|
102
|
+
rescue => detail
|
103
|
+
raise XMLRPC::FaultException.new(
|
104
|
+
1, "Could not rebuild facts"
|
105
|
+
)
|
106
|
+
end
|
107
|
+
else
|
72
108
|
raise XMLRPC::FaultException.new(
|
73
|
-
1, "
|
109
|
+
1, "Unavailable config format %s" % format
|
74
110
|
)
|
75
111
|
end
|
76
112
|
end
|
@@ -95,7 +131,26 @@ class Server
|
|
95
131
|
if @local
|
96
132
|
return retobjects
|
97
133
|
else
|
98
|
-
|
134
|
+
str = nil
|
135
|
+
case format
|
136
|
+
when "marshal":
|
137
|
+
str = Marshal::dump(retobjects)
|
138
|
+
when "yaml":
|
139
|
+
str = YAML.dump(retobjects)
|
140
|
+
else
|
141
|
+
raise XMLRPC::FaultException.new(
|
142
|
+
1, "Unavailable config format %s" % format
|
143
|
+
)
|
144
|
+
end
|
145
|
+
return CGI.escape(str)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def local?
|
150
|
+
if defined? @local and @local
|
151
|
+
return true
|
152
|
+
else
|
153
|
+
return false
|
99
154
|
end
|
100
155
|
end
|
101
156
|
end
|
@@ -1,46 +1,44 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#--------------------
|
4
|
-
# the puppet client
|
5
|
-
#
|
6
|
-
# $Id: sslcertificates.rb 720 2005-10-21 06:16:43Z luke $
|
7
|
-
|
1
|
+
# The library for manipulating SSL certs.
|
8
2
|
|
9
3
|
require 'puppet'
|
10
|
-
require 'openssl'
|
11
|
-
|
12
|
-
module Puppet
|
13
|
-
module SSLCertificates
|
14
|
-
def self.mkdir(dir)
|
15
|
-
# this is all a bunch of stupid hackery
|
16
|
-
unless FileTest.exists?(dir)
|
17
|
-
comp = Puppet::Type::Component.create(
|
18
|
-
:name => "certdir creation"
|
19
|
-
)
|
20
|
-
path = ['']
|
21
|
-
|
22
|
-
dir.split(File::SEPARATOR).each { |d|
|
23
|
-
path << d
|
24
|
-
if FileTest.exists?(File.join(path))
|
25
|
-
unless FileTest.directory?(File.join(path))
|
26
|
-
raise "%s exists but is not a directory" % File.join(path)
|
27
|
-
end
|
28
|
-
else
|
29
|
-
obj = Puppet::Type.type(:file).create(
|
30
|
-
:name => File.join(path),
|
31
|
-
:mode => "750",
|
32
|
-
:create => "directory"
|
33
|
-
)
|
34
4
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
5
|
+
begin
|
6
|
+
require 'openssl'
|
7
|
+
rescue LoadError
|
8
|
+
raise Puppet::Error, "You must have the Ruby openssl library installed"
|
9
|
+
end
|
41
10
|
|
42
|
-
|
43
|
-
|
11
|
+
module Puppet::SSLCertificates
|
12
|
+
# def self.mkdir(dir)
|
13
|
+
# # this is all a bunch of stupid hackery
|
14
|
+
# unless FileTest.exists?(dir)
|
15
|
+
# comp = Puppet.type(:component).create(
|
16
|
+
# :name => "certdir creation"
|
17
|
+
# )
|
18
|
+
# path = ['']
|
19
|
+
#
|
20
|
+
# dir.split(File::SEPARATOR).each { |d|
|
21
|
+
# path << d
|
22
|
+
# if FileTest.exists?(File.join(path))
|
23
|
+
# unless FileTest.directory?(File.join(path))
|
24
|
+
# raise "%s exists but is not a directory" % File.join(path)
|
25
|
+
# end
|
26
|
+
# else
|
27
|
+
# obj = Puppet::Type.type(:file).create(
|
28
|
+
# :name => File.join(path),
|
29
|
+
# :mode => "750",
|
30
|
+
# :ensure => "directory"
|
31
|
+
# )
|
32
|
+
#
|
33
|
+
# comp.push obj
|
34
|
+
# end
|
35
|
+
# }
|
36
|
+
# trans = comp.evaluate
|
37
|
+
# trans.evaluate
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# Puppet::Type.allclear
|
41
|
+
# end
|
44
42
|
|
45
43
|
#def self.mkcert(type, name, days, issuercert, issuername, serial, publickey)
|
46
44
|
def self.mkcert(hash)
|
@@ -166,572 +164,8 @@ module SSLCertificates
|
|
166
164
|
|
167
165
|
return hashpath
|
168
166
|
end
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
class CA
|
173
|
-
attr_accessor :keyfile, :file, :config, :dir, :cert
|
174
|
-
|
175
|
-
@@params = [
|
176
|
-
:certdir,
|
177
|
-
:publickeydir,
|
178
|
-
:privatekeydir,
|
179
|
-
:cadir,
|
180
|
-
:cakey,
|
181
|
-
:cacert,
|
182
|
-
:capass,
|
183
|
-
:capub,
|
184
|
-
:csrdir,
|
185
|
-
:signeddir,
|
186
|
-
:serial,
|
187
|
-
:privatedir,
|
188
|
-
:ca_crl_days,
|
189
|
-
:ca_days,
|
190
|
-
:ca_md,
|
191
|
-
:req_bits,
|
192
|
-
:keylength,
|
193
|
-
:autosign
|
194
|
-
]
|
195
|
-
|
196
|
-
@@defaults = {
|
197
|
-
:certdir => [:ssldir, "certs"],
|
198
|
-
:publickeydir => [:ssldir, "public_keys"],
|
199
|
-
:privatekeydir => [:ssldir, "private_keys"],
|
200
|
-
:cadir => [:ssldir, "ca"],
|
201
|
-
:cacert => [:cadir, "ca_crt.pem"],
|
202
|
-
:cakey => [:cadir, "ca_key.pem"],
|
203
|
-
:capub => [:cadir, "ca_pub.pem"],
|
204
|
-
:csrdir => [:cadir, "requests"],
|
205
|
-
:signeddir => [:cadir, "signed"],
|
206
|
-
:capass => [:cadir, "ca.pass"],
|
207
|
-
:serial => [:cadir, "serial"],
|
208
|
-
:privatedir => [:ssldir, "private"],
|
209
|
-
:passfile => [:privatedir, "password"],
|
210
|
-
:autosign => [:puppetconf, "autosign.conf"],
|
211
|
-
:ca_crl_days => 365,
|
212
|
-
:ca_days => 1825,
|
213
|
-
:ca_md => "md5",
|
214
|
-
:req_bits => 2048,
|
215
|
-
:keylength => 1024,
|
216
|
-
}
|
217
|
-
|
218
|
-
@@params.each { |param|
|
219
|
-
Puppet.setdefault(param,@@defaults[param])
|
220
|
-
}
|
221
|
-
|
222
|
-
def certfile
|
223
|
-
@config[:cacert]
|
224
|
-
end
|
225
|
-
|
226
|
-
def host2csrfile(hostname)
|
227
|
-
File.join(Puppet[:csrdir], [hostname, "pem"].join("."))
|
228
|
-
end
|
229
|
-
|
230
|
-
# this stores signed certs in a directory unrelated to
|
231
|
-
# normal client certs
|
232
|
-
def host2certfile(hostname)
|
233
|
-
File.join(Puppet[:signeddir], [hostname, "pem"].join("."))
|
234
|
-
end
|
235
|
-
|
236
|
-
def thing2name(thing)
|
237
|
-
thing.subject.to_a.find { |ary|
|
238
|
-
ary[0] == "CN"
|
239
|
-
}[1]
|
240
|
-
end
|
241
|
-
|
242
|
-
def initialize(hash = {})
|
243
|
-
self.setconfig(hash)
|
244
|
-
|
245
|
-
self.getcert
|
246
|
-
unless FileTest.exists?(@config[:serial])
|
247
|
-
File.open(@config[:serial], "w") { |f|
|
248
|
-
f << "%04X" % 1
|
249
|
-
}
|
250
|
-
end
|
251
|
-
|
252
|
-
if Puppet[:capass] and ! FileTest.exists?(Puppet[:capass])
|
253
|
-
self.genpass
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def genpass
|
258
|
-
pass = ""
|
259
|
-
20.times { pass += (rand(74) + 48).chr }
|
260
|
-
|
261
|
-
unless @config[:capass]
|
262
|
-
raise "No passfile"
|
263
|
-
end
|
264
|
-
Puppet::SSLCertificates.mkdir(File.dirname(@config[:capass]))
|
265
|
-
File.open(@config[:capass], "w", 0600) { |f| f.print pass }
|
266
|
-
return pass
|
267
|
-
end
|
268
|
-
|
269
|
-
def getcert
|
270
|
-
if FileTest.exists?(@config[:cacert])
|
271
|
-
@cert = OpenSSL::X509::Certificate.new(
|
272
|
-
File.read(@config[:cacert])
|
273
|
-
)
|
274
|
-
else
|
275
|
-
self.mkrootcert
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
def getclientcsr(host)
|
280
|
-
csrfile = host2csrfile(host)
|
281
|
-
unless File.exists?(csrfile)
|
282
|
-
return nil
|
283
|
-
end
|
284
|
-
|
285
|
-
return OpenSSL::X509::Request.new(File.read(csrfile))
|
286
|
-
end
|
287
|
-
|
288
|
-
def getclientcert(host)
|
289
|
-
certfile = host2certfile(host)
|
290
|
-
unless File.exists?(certfile)
|
291
|
-
return [nil, nil]
|
292
|
-
end
|
293
|
-
|
294
|
-
return [OpenSSL::X509::Certificate.new(File.read(certfile)), @cert]
|
295
|
-
end
|
296
|
-
|
297
|
-
def list
|
298
|
-
return Dir.entries(Puppet[:csrdir]).reject { |file|
|
299
|
-
file =~ /^\.+$/
|
300
|
-
}.collect { |file|
|
301
|
-
file.sub(/\.pem$/, '')
|
302
|
-
}
|
303
|
-
end
|
304
|
-
|
305
|
-
def mkrootcert
|
306
|
-
cert = Certificate.new(
|
307
|
-
:name => "CAcert",
|
308
|
-
:cert => @config[:cacert],
|
309
|
-
:encrypt => @config[:passfile],
|
310
|
-
:key => @config[:cakey],
|
311
|
-
:selfsign => true,
|
312
|
-
:length => 1825,
|
313
|
-
:type => :ca
|
314
|
-
)
|
315
|
-
@cert = cert.mkselfsigned
|
316
|
-
File.open(@config[:cacert], "w", 0660) { |f|
|
317
|
-
f.puts @cert.to_pem
|
318
|
-
}
|
319
|
-
@key = cert.key
|
320
|
-
return cert
|
321
|
-
end
|
322
|
-
|
323
|
-
def removeclientcsr(host)
|
324
|
-
csrfile = host2csrfile(host)
|
325
|
-
unless File.exists?(csrfile)
|
326
|
-
raise Puppet::Error, "No certificate request for %s" % host
|
327
|
-
end
|
328
|
-
|
329
|
-
File.unlink(csrfile)
|
330
|
-
end
|
331
|
-
|
332
|
-
def setconfig(hash)
|
333
|
-
@config = {}
|
334
|
-
@@params.each { |param|
|
335
|
-
if hash.include?(param)
|
336
|
-
begin
|
337
|
-
@config[param] = hash[param]
|
338
|
-
Puppet[param] = hash[param]
|
339
|
-
hash.delete(param)
|
340
|
-
rescue => detail
|
341
|
-
puts detail
|
342
|
-
exit
|
343
|
-
end
|
344
|
-
else
|
345
|
-
begin
|
346
|
-
@config[param] = Puppet[param]
|
347
|
-
rescue => detail
|
348
|
-
puts detail
|
349
|
-
exit
|
350
|
-
end
|
351
|
-
end
|
352
|
-
}
|
353
|
-
|
354
|
-
if hash.include?(:password)
|
355
|
-
@config[:password] = hash[:password]
|
356
|
-
hash.delete(:password)
|
357
|
-
end
|
358
|
-
|
359
|
-
if hash.length > 0
|
360
|
-
raise ArgumentError, "Unknown parameters %s" % hash.keys.join(",")
|
361
|
-
end
|
362
|
-
|
363
|
-
[:cadir, :csrdir, :signeddir].each { |dir|
|
364
|
-
unless @config[dir]
|
365
|
-
raise "%s is undefined" % dir
|
366
|
-
end
|
367
|
-
unless FileTest.exists?(@config[dir])
|
368
|
-
Puppet::SSLCertificates.mkdir(@config[dir])
|
369
|
-
end
|
370
|
-
}
|
371
|
-
end
|
372
|
-
|
373
|
-
def sign(csr)
|
374
|
-
unless csr.is_a?(OpenSSL::X509::Request)
|
375
|
-
raise Puppet::Error,
|
376
|
-
"CA#sign only accepts OpenSSL::X509::Request objects, not %s" %
|
377
|
-
csr.class
|
378
|
-
end
|
379
|
-
|
380
|
-
unless csr.verify(csr.public_key)
|
381
|
-
raise Puppet::Error, "CSR sign verification failed"
|
382
|
-
end
|
383
|
-
|
384
|
-
# i should probably check key length...
|
385
|
-
|
386
|
-
# read the ca cert in
|
387
|
-
cacert = OpenSSL::X509::Certificate.new(
|
388
|
-
File.read(@config[:cacert])
|
389
|
-
)
|
390
|
-
|
391
|
-
cakey = nil
|
392
|
-
if @config[:password]
|
393
|
-
cakey = OpenSSL::PKey::RSA.new(
|
394
|
-
File.read(@config[:cakey]), @config[:password]
|
395
|
-
)
|
396
|
-
else
|
397
|
-
cakey = OpenSSL::PKey::RSA.new(
|
398
|
-
File.read(@config[:cakey])
|
399
|
-
)
|
400
|
-
end
|
401
|
-
|
402
|
-
unless cacert.check_private_key(cakey)
|
403
|
-
raise Puppet::Error, "CA Certificate is invalid"
|
404
|
-
end
|
405
|
-
|
406
|
-
serial = File.read(@config[:serial]).chomp.hex
|
407
|
-
newcert = SSLCertificates.mkcert(
|
408
|
-
:type => :server,
|
409
|
-
:name => csr.subject,
|
410
|
-
:days => @config[:ca_days],
|
411
|
-
:issuer => cacert,
|
412
|
-
:serial => serial,
|
413
|
-
:publickey => csr.public_key
|
414
|
-
)
|
415
|
-
|
416
|
-
# increment the serial
|
417
|
-
File.open(@config[:serial], "w") { |f|
|
418
|
-
f << "%04X" % (serial + 1)
|
419
|
-
}
|
420
|
-
|
421
|
-
newcert.sign(cakey, OpenSSL::Digest::SHA1.new)
|
422
|
-
|
423
|
-
self.storeclientcert(newcert)
|
424
|
-
|
425
|
-
return [newcert, cacert]
|
426
|
-
end
|
427
|
-
|
428
|
-
def storeclientcsr(csr)
|
429
|
-
host = thing2name(csr)
|
430
|
-
|
431
|
-
csrfile = host2csrfile(host)
|
432
|
-
if File.exists?(csrfile)
|
433
|
-
raise Puppet::Error, "Certificate request for %s already exists" % host
|
434
|
-
end
|
435
|
-
|
436
|
-
File.open(csrfile, "w", 0660) { |f|
|
437
|
-
f.print csr.to_pem
|
438
|
-
}
|
439
|
-
end
|
440
|
-
|
441
|
-
def storeclientcert(cert)
|
442
|
-
host = thing2name(cert)
|
443
|
-
|
444
|
-
certfile = host2certfile(host)
|
445
|
-
if File.exists?(certfile)
|
446
|
-
Puppet.notice "Overwriting signed certificate %s for %s" %
|
447
|
-
[certfile, host]
|
448
|
-
end
|
449
|
-
|
450
|
-
File.open(certfile, "w", 0660) { |f|
|
451
|
-
f.print cert.to_pem
|
452
|
-
}
|
453
|
-
end
|
454
|
-
|
455
|
-
end
|
456
|
-
|
457
|
-
class Certificate
|
458
|
-
attr_accessor :certfile, :keyfile, :name, :dir, :hash, :type
|
459
|
-
attr_accessor :key, :cert, :csr, :cacert
|
460
|
-
|
461
|
-
@@params2names = {
|
462
|
-
:name => "CN",
|
463
|
-
:state => "ST",
|
464
|
-
:country => "C",
|
465
|
-
:email => "emailAddress",
|
466
|
-
:org => "O",
|
467
|
-
:city => "L",
|
468
|
-
:ou => "OU"
|
469
|
-
}
|
470
|
-
|
471
|
-
def certname
|
472
|
-
OpenSSL::X509::Name.new self.subject
|
473
|
-
end
|
474
|
-
|
475
|
-
def delete
|
476
|
-
[@certfile,@keyfile].each { |file|
|
477
|
-
if FileTest.exists?(file)
|
478
|
-
File.unlink(file)
|
479
|
-
end
|
480
|
-
}
|
481
|
-
|
482
|
-
if defined? @hash and @hash
|
483
|
-
if FileTest.symlink?(@hash)
|
484
|
-
File.unlink(@hash)
|
485
|
-
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
def exists?
|
490
|
-
return FileTest.exists?(@certfile)
|
491
|
-
end
|
492
|
-
|
493
|
-
def getkey
|
494
|
-
unless FileTest.exists?(@keyfile)
|
495
|
-
self.mkkey()
|
496
|
-
end
|
497
|
-
if @password
|
498
|
-
@key = OpenSSL::PKey::RSA.new(
|
499
|
-
File.read(@keyfile),
|
500
|
-
@password
|
501
|
-
)
|
502
|
-
else
|
503
|
-
@key = OpenSSL::PKey::RSA.new(
|
504
|
-
File.read(@keyfile)
|
505
|
-
)
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
def initialize(hash)
|
510
|
-
unless hash.include?(:name)
|
511
|
-
raise "You must specify the common name for the certificate"
|
512
|
-
end
|
513
|
-
@name = hash[:name]
|
514
|
-
|
515
|
-
# init a few variables
|
516
|
-
@cert = @key = @csr = nil
|
517
|
-
|
518
|
-
if hash.include?(:cert)
|
519
|
-
@certfile = hash[:cert]
|
520
|
-
@dir = File.dirname(@certfile)
|
521
|
-
else
|
522
|
-
@dir = hash[:dir] || Puppet[:certdir]
|
523
|
-
@certfile = File.join(@dir, @name)
|
524
|
-
end
|
525
|
-
|
526
|
-
@cacertfile ||= File.join(Puppet[:certdir], "ca.pem")
|
527
|
-
|
528
|
-
unless FileTest.directory?(@dir)
|
529
|
-
Puppet::SSLCertificates.mkdir(@dir)
|
530
|
-
end
|
531
|
-
|
532
|
-
unless @certfile =~ /\.pem$/
|
533
|
-
@certfile += ".pem"
|
534
|
-
end
|
535
|
-
@keyfile = hash[:key] || File.join(
|
536
|
-
Puppet[:privatekeydir], [@name,"pem"].join(".")
|
537
|
-
)
|
538
|
-
unless FileTest.directory?(@dir)
|
539
|
-
Puppet::SSLCertificates.mkdir(@dir)
|
540
|
-
end
|
541
|
-
|
542
|
-
[@keyfile].each { |file|
|
543
|
-
dir = File.dirname(file)
|
544
|
-
|
545
|
-
unless FileTest.directory?(dir)
|
546
|
-
Puppet::SSLCertificates.mkdir(dir)
|
547
|
-
end
|
548
|
-
}
|
549
|
-
|
550
|
-
@days = hash[:length] || 365
|
551
|
-
@selfsign = hash[:selfsign] || false
|
552
|
-
@encrypt = hash[:encrypt] || false
|
553
|
-
@replace = hash[:replace] || false
|
554
|
-
@issuer = hash[:issuer] || nil
|
555
|
-
|
556
|
-
if hash.include?(:type)
|
557
|
-
case hash[:type]
|
558
|
-
when :ca, :client, :server: @type = hash[:type]
|
559
|
-
else
|
560
|
-
raise "Invalid Cert type %s" % hash[:type]
|
561
|
-
end
|
562
|
-
else
|
563
|
-
@type = :client
|
564
|
-
end
|
565
|
-
|
566
|
-
@params = {:name => @name}
|
567
|
-
[:state, :country, :email, :org, :ou].each { |param|
|
568
|
-
if hash.include?(param)
|
569
|
-
@params[param] = hash[param]
|
570
|
-
end
|
571
|
-
}
|
572
|
-
|
573
|
-
if @encrypt
|
574
|
-
if @encrypt =~ /^\//
|
575
|
-
File.open(@encrypt) { |f|
|
576
|
-
@password = f.read.chomp
|
577
|
-
}
|
578
|
-
else
|
579
|
-
raise ":encrypt must be a path to a pass phrase file"
|
580
|
-
end
|
581
|
-
else
|
582
|
-
@password = nil
|
583
|
-
end
|
584
|
-
|
585
|
-
if hash.include?(:selfsign)
|
586
|
-
@selfsign = hash[:selfsign]
|
587
|
-
else
|
588
|
-
@selfsign = false
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
# this only works for servers, not for users
|
593
|
-
def mkcsr
|
594
|
-
unless defined? @key and @key
|
595
|
-
self.getkey
|
596
|
-
end
|
597
|
-
|
598
|
-
name = OpenSSL::X509::Name.new self.subject
|
599
|
-
|
600
|
-
@csr = OpenSSL::X509::Request.new
|
601
|
-
@csr.version = 0
|
602
|
-
@csr.subject = name
|
603
|
-
@csr.public_key = @key.public_key
|
604
|
-
@csr.sign(@key, OpenSSL::Digest::SHA1.new)
|
605
|
-
|
606
|
-
#File.open(@csrfile, "w") { |f|
|
607
|
-
# f << @csr.to_pem
|
608
|
-
#}
|
609
|
-
|
610
|
-
unless @csr.verify(@key.public_key)
|
611
|
-
raise Puppet::Error, "CSR sign verification failed"
|
612
|
-
end
|
613
|
-
|
614
|
-
return @csr
|
615
|
-
end
|
616
|
-
|
617
|
-
def mkkey
|
618
|
-
# @key is the file
|
619
|
-
|
620
|
-
@key = OpenSSL::PKey::RSA.new(1024)
|
621
|
-
# { |p,n|
|
622
|
-
# case p
|
623
|
-
# when 0; Puppet.info "key info: ." # BN_generate_prime
|
624
|
-
# when 1; Puppet.info "key info: +" # BN_generate_prime
|
625
|
-
# when 2; Puppet.info "key info: *" # searching good prime,
|
626
|
-
# # n = #of try,
|
627
|
-
# # but also data from BN_generate_prime
|
628
|
-
# when 3; Puppet.info "key info: \n" # found good prime, n==0 - p, n==1 - q,
|
629
|
-
# # but also data from BN_generate_prime
|
630
|
-
# else; Puppet.info "key info: *" # BN_generate_prime
|
631
|
-
# end
|
632
|
-
# }
|
633
|
-
|
634
|
-
if @password
|
635
|
-
#passwdproc = proc { @password }
|
636
|
-
keytext = @key.export(
|
637
|
-
OpenSSL::Cipher::DES.new(:EDE3, :CBC),
|
638
|
-
@password
|
639
|
-
)
|
640
|
-
File.open(@keyfile, "w", 0400) { |f|
|
641
|
-
f << keytext
|
642
|
-
}
|
643
|
-
else
|
644
|
-
File.open(@keyfile, "w", 0400) { |f|
|
645
|
-
f << @key.to_pem
|
646
|
-
}
|
647
|
-
end
|
648
|
-
|
649
|
-
#cmd = "#{ossl} genrsa -out #{@key} 1024"
|
650
|
-
end
|
651
|
-
|
652
|
-
def mkselfsigned
|
653
|
-
unless defined? @key and @key
|
654
|
-
self.getkey
|
655
|
-
end
|
656
|
-
|
657
|
-
if defined? @cert and @cert
|
658
|
-
raise Puppet::Error, "Cannot replace existing certificate"
|
659
|
-
end
|
660
|
-
|
661
|
-
args = {
|
662
|
-
:name => self.certname,
|
663
|
-
:days => @days,
|
664
|
-
:issuer => nil,
|
665
|
-
:serial => 0x0,
|
666
|
-
:publickey => @key.public_key
|
667
|
-
}
|
668
|
-
if @type
|
669
|
-
args[:type] = @type
|
670
|
-
else
|
671
|
-
args[:type] = :server
|
672
|
-
end
|
673
|
-
@cert = SSLCertificates.mkcert(args)
|
674
|
-
|
675
|
-
@cert.sign(@key, OpenSSL::Digest::SHA1.new) if @selfsign
|
676
|
-
|
677
|
-
return @cert
|
678
|
-
end
|
679
|
-
|
680
|
-
def subject(string = false)
|
681
|
-
subj = @@params2names.collect { |param, name|
|
682
|
-
if @params.include?(param)
|
683
|
-
[name, @params[param]]
|
684
|
-
end
|
685
|
-
}.reject { |ary| ary.nil? }
|
686
|
-
|
687
|
-
if string
|
688
|
-
return "/" + subj.collect { |ary|
|
689
|
-
"%s=%s" % ary
|
690
|
-
}.join("/") + "/"
|
691
|
-
else
|
692
|
-
return subj
|
693
|
-
end
|
694
|
-
end
|
695
|
-
|
696
|
-
# verify that we can track down the cert chain or whatever
|
697
|
-
def verify
|
698
|
-
"openssl verify -verbose -CAfile /home/luke/.puppet/ssl/certs/ca.pem -purpose sslserver culain.madstop.com.pem"
|
699
|
-
end
|
700
|
-
|
701
|
-
def write
|
702
|
-
files = {
|
703
|
-
@certfile => @cert,
|
704
|
-
@keyfile => @key,
|
705
|
-
}
|
706
|
-
if defined? @cacert
|
707
|
-
files[@cacertfile] = @cacert
|
708
|
-
end
|
709
|
-
|
710
|
-
files.each { |file,thing|
|
711
|
-
if defined? thing and thing
|
712
|
-
if FileTest.exists?(file)
|
713
|
-
next
|
714
|
-
end
|
715
|
-
|
716
|
-
text = nil
|
717
|
-
|
718
|
-
if thing.is_a?(OpenSSL::PKey::RSA) and @password
|
719
|
-
text = thing.export(
|
720
|
-
OpenSSL::Cipher::DES.new(:EDE3, :CBC),
|
721
|
-
@password
|
722
|
-
)
|
723
|
-
else
|
724
|
-
text = thing.to_pem
|
725
|
-
end
|
726
|
-
|
727
|
-
File.open(file, "w", 0660) { |f| f.print text }
|
728
|
-
end
|
729
|
-
}
|
730
|
-
|
731
|
-
if defined? @cacert
|
732
|
-
SSLCertificates.mkhash(Puppet[:certdir], @cacert, @cacertfile)
|
733
|
-
end
|
734
|
-
end
|
735
|
-
end
|
736
|
-
end
|
167
|
+
require 'puppet/sslcertificates/certificate'
|
168
|
+
require 'puppet/sslcertificates/ca'
|
737
169
|
end
|
170
|
+
|
171
|
+
# $Id: sslcertificates.rb 873 2006-02-07 23:12:33Z luke $
|