~lynxman/ubuntu/precise/puppet/puppetlabsfixbug12844

« back to all changes in this revision

Viewing changes to test/network/handler/ca.rb

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2011-10-24 15:05:12 UTC
  • Revision ID: james.westby@ubuntu.com-20111024150512-yxqwfdp6hcs6of5l
Tags: 2.7.1-1ubuntu3.2
* SECURITY UPDATE: puppet master impersonation via incorrect certificates
  - debian/patches/CVE-2011-3872.patch: refactor certificate handling.
  - Thanks to upstream for providing the patch.
  - CVE-2011-3872

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env ruby
2
 
 
3
 
require File.expand_path(File.dirname(__FILE__) + '/../../lib/puppettest')
4
 
 
5
 
require 'puppettest'
6
 
require 'puppet/network/handler/ca'
7
 
require 'mocha'
8
 
 
9
 
$short = (ARGV.length > 0 and ARGV[0] == "short")
10
 
 
11
 
class TestCA < Test::Unit::TestCase
12
 
  include PuppetTest::ServerTest
13
 
 
14
 
  def setup
15
 
    Puppet::Util::SUIDManager.stubs(:asuser).yields
16
 
    super
17
 
  end
18
 
 
19
 
  # Verify that we're autosigning.  We have to autosign a "different" machine,
20
 
  # since we always autosign the CA server's certificate.
21
 
  def test_autocertgeneration
22
 
    ca = nil
23
 
 
24
 
    # create our ca
25
 
    assert_nothing_raised {
26
 
      ca = Puppet::Network::Handler.ca.new(:autosign => true)
27
 
    }
28
 
 
29
 
    # create a cert with a fake name
30
 
    key = nil
31
 
    csr = nil
32
 
    cert = nil
33
 
    hostname = "test.domain.com"
34
 
    assert_nothing_raised {
35
 
      cert = Puppet::SSLCertificates::Certificate.new(
36
 
        :name => "test.domain.com"
37
 
      )
38
 
    }
39
 
 
40
 
    # make the request
41
 
    assert_nothing_raised {
42
 
      cert.mkcsr
43
 
    }
44
 
 
45
 
    # and get it signed
46
 
    certtext = nil
47
 
    cacerttext = nil
48
 
    assert_nothing_raised {
49
 
      certtext, cacerttext = ca.getcert(cert.csr.to_s)
50
 
    }
51
 
 
52
 
    # they should both be strings
53
 
    assert_instance_of(String, certtext)
54
 
    assert_instance_of(String, cacerttext)
55
 
 
56
 
    # and they should both be valid certs
57
 
    assert_nothing_raised {
58
 
      OpenSSL::X509::Certificate.new(certtext)
59
 
    }
60
 
    assert_nothing_raised {
61
 
      OpenSSL::X509::Certificate.new(cacerttext)
62
 
    }
63
 
 
64
 
    # and pull it again, just to make sure we're getting the same thing
65
 
    newtext = nil
66
 
    assert_nothing_raised {
67
 
      newtext, cacerttext = ca.getcert(
68
 
        cert.csr.to_s, "test.reductivelabs.com", "127.0.0.1"
69
 
      )
70
 
    }
71
 
 
72
 
    assert_equal(certtext,newtext)
73
 
  end
74
 
 
75
 
  # this time don't use autosign
76
 
  def test_storeAndSign
77
 
    ca = nil
78
 
    caserv = nil
79
 
 
80
 
    # make our CA server
81
 
    assert_nothing_raised {
82
 
      caserv = Puppet::Network::Handler.ca.new(:autosign => false)
83
 
    }
84
 
 
85
 
    # retrieve the actual ca object
86
 
    assert_nothing_raised {
87
 
      ca = caserv.ca
88
 
    }
89
 
 
90
 
    # make our test cert again
91
 
    key = nil
92
 
    csr = nil
93
 
    cert = nil
94
 
    hostname = "test.domain.com"
95
 
    assert_nothing_raised {
96
 
      cert = Puppet::SSLCertificates::Certificate.new(
97
 
        :name => "anothertest.domain.com"
98
 
      )
99
 
    }
100
 
    # and the CSR
101
 
    assert_nothing_raised {
102
 
      cert.mkcsr
103
 
    }
104
 
 
105
 
    # retrieve them
106
 
    certtext = nil
107
 
    assert_nothing_raised {
108
 
      certtext, cacerttext = caserv.getcert(
109
 
        cert.csr.to_s, "test.reductivelabs.com", "127.0.0.1"
110
 
      )
111
 
    }
112
 
 
113
 
    # verify we got nothing back, since autosign is off
114
 
    assert_equal("", certtext)
115
 
 
116
 
    # now sign it manually, with the CA object
117
 
    x509 = nil
118
 
    assert_nothing_raised {
119
 
      x509, cacert = ca.sign(cert.csr)
120
 
    }
121
 
 
122
 
    # and write it out
123
 
    cert.cert = x509
124
 
    assert_nothing_raised {
125
 
      cert.write
126
 
    }
127
 
 
128
 
    assert(File.exists?(cert.certfile))
129
 
 
130
 
    # now get them again, and verify that we actually get them
131
 
    newtext = nil
132
 
    assert_nothing_raised {
133
 
      newtext, cacerttext  = caserv.getcert(cert.csr.to_s)
134
 
    }
135
 
 
136
 
    assert(newtext)
137
 
    assert_nothing_raised {
138
 
      OpenSSL::X509::Certificate.new(newtext)
139
 
    }
140
 
 
141
 
    # Now verify that we can clean a given host's certs
142
 
    assert_nothing_raised {
143
 
      ca.clean("anothertest.domain.com")
144
 
    }
145
 
 
146
 
    assert(!File.exists?(cert.certfile), "Cert still exists after clean")
147
 
  end
148
 
 
149
 
  # and now test the autosign file
150
 
  def test_autosign
151
 
    autosign = File.join(tmpdir, "autosigntesting")
152
 
    @@tmpfiles << autosign
153
 
    File.open(autosign, "w") { |f|
154
 
      f.puts "hostmatch.domain.com"
155
 
      f.puts "*.other.com"
156
 
    }
157
 
 
158
 
    caserv = nil
159
 
    assert_nothing_raised {
160
 
      caserv = Puppet::Network::Handler.ca.new(:autosign => autosign)
161
 
    }
162
 
 
163
 
    # make sure we know what's going on
164
 
    assert(caserv.autosign?("hostmatch.domain.com"))
165
 
    assert(caserv.autosign?("fakehost.other.com"))
166
 
    assert(!caserv.autosign?("kirby.reductivelabs.com"))
167
 
    assert(!caserv.autosign?("culain.domain.com"))
168
 
  end
169
 
 
170
 
  # verify that things aren't autosigned by default
171
 
  def test_nodefaultautosign
172
 
    caserv = nil
173
 
    assert_nothing_raised {
174
 
      caserv = Puppet::Network::Handler.ca.new
175
 
    }
176
 
 
177
 
    # make sure we know what's going on
178
 
    assert(!caserv.autosign?("hostmatch.domain.com"))
179
 
    assert(!caserv.autosign?("fakehost.other.com"))
180
 
    assert(!caserv.autosign?("kirby.reductivelabs.com"))
181
 
    assert(!caserv.autosign?("culain.domain.com"))
182
 
  end
183
 
 
184
 
  # We want the CA to autosign its own certificate, because otherwise
185
 
  # the puppetmasterd CA does not autostart.
186
 
  def test_caautosign
187
 
    server = nil
188
 
    Puppet.stubs(:master?).returns true
189
 
    assert_nothing_raised {
190
 
 
191
 
            server = Puppet::Network::HTTPServer::WEBrick.new(
192
 
                
193
 
        :Port => @@port,
194
 
        
195
 
        :Handlers => {
196
 
          :CA => {}, # so that certs autogenerate
197
 
          :Status => nil
198
 
        }
199
 
      )
200
 
    }
201
 
  end
202
 
 
203
 
  # Make sure true/false causes the file to be ignored.
204
 
  def test_autosign_true_beats_file
205
 
    caserv = nil
206
 
    assert_nothing_raised {
207
 
      caserv = Puppet::Network::Handler.ca.new
208
 
    }
209
 
 
210
 
    host = "hostname.domain.com"
211
 
 
212
 
    # Create an autosign file
213
 
    file = tempfile
214
 
    Puppet[:autosign] = file
215
 
 
216
 
    File.open(file, "w") { |f|
217
 
      f.puts host
218
 
    }
219
 
 
220
 
    # Start with "false"
221
 
    Puppet[:autosign] = false
222
 
 
223
 
    assert(! caserv.autosign?(host), "Host was incorrectly autosigned")
224
 
 
225
 
    # Then set it to true
226
 
    Puppet[:autosign] = true
227
 
    assert(caserv.autosign?(host), "Host was not autosigned")
228
 
    # And try a different host
229
 
    assert(caserv.autosign?("other.yay.com"), "Host was not autosigned")
230
 
 
231
 
    # And lastly the file
232
 
    Puppet[:autosign] = file
233
 
    assert(caserv.autosign?(host), "Host was not autosigned")
234
 
 
235
 
    # And try a different host
236
 
    assert(! caserv.autosign?("other.yay.com"), "Host was autosigned")
237
 
  end
238
 
 
239
 
  # Make sure that a CSR created with keys that don't match the existing
240
 
  # cert throws an exception on the server.
241
 
  def test_mismatched_public_keys_throws_exception
242
 
    ca = Puppet::Network::Handler.ca.new
243
 
 
244
 
    # First initialize the server
245
 
    client = Puppet::Network::Client.ca.new :CA => ca
246
 
    client.request_cert
247
 
    File.unlink(Puppet[:hostcsr])
248
 
 
249
 
    # Now use a different cert name
250
 
    Puppet[:certname] = "my.host.com"
251
 
    client = Puppet::Network::Client.ca.new :CA => ca
252
 
    firstcsr = client.csr
253
 
    File.unlink(Puppet[:hostcsr]) if FileTest.exists?(Puppet[:hostcsr])
254
 
 
255
 
    assert_nothing_raised("Could not get cert") do
256
 
      ca.getcert(firstcsr.to_s)
257
 
    end
258
 
 
259
 
    # Now get rid of the public key, forcing a new csr
260
 
    File.unlink(Puppet[:hostprivkey])
261
 
 
262
 
    client = Puppet::Network::Client.ca.new :CA => ca
263
 
 
264
 
    second_csr = client.csr
265
 
 
266
 
    assert(firstcsr.to_s != second_csr.to_s, "CSR did not change")
267
 
 
268
 
    assert_raise(Puppet::Error, "CA allowed mismatched keys") do
269
 
      ca.getcert(second_csr.to_s)
270
 
    end
271
 
  end
272
 
end
273