1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
require 'spec_helper'
describe "autosigning" do
include PuppetSpec::Files
let(:puppet_dir) { tmpdir("ca_autosigning") }
let(:csr_attributes_content) do
{
'custom_attributes' => {
'1.3.6.1.4.1.34380.2.0' => 'hostname.domain.com',
'1.3.6.1.4.1.34380.2.1' => 'my passphrase',
'1.3.6.1.4.1.34380.2.2' => # system IPs in hex
[ 0xC0A80001, # 192.168.0.1
0xC0A80101 ], # 192.168.1.1
},
'extension_requests' => {
'pp_uuid' => 'abcdef',
'1.3.6.1.4.1.34380.1.1.2' => '1234', # pp_instance_id
'1.3.6.1.4.1.34380.1.2.1' => 'some-value', # private extension
},
}
end
let(:host) { Puppet::SSL::Host.new }
before do
Puppet.settings[:confdir] = puppet_dir
Puppet.settings[:vardir] = puppet_dir
# This is necessary so the terminus instances don't lie around.
Puppet::SSL::Key.indirection.termini.clear
end
def write_csr_attributes(yaml)
File.open(Puppet.settings[:csr_attributes], 'w') do |file|
file.puts YAML.dump(yaml)
end
end
context "when the csr_attributes file is valid, but empty" do
it "generates a CSR when the file is empty" do
Puppet::FileSystem.touch(Puppet.settings[:csr_attributes])
host.generate_certificate_request
end
it "generates a CSR when the file contains whitespace" do
File.open(Puppet.settings[:csr_attributes], 'w') do |file|
file.puts "\n\n"
end
host.generate_certificate_request
end
end
context "when the csr_attributes file doesn't contain a YAML encoded hash" do
it "raises when the file contains a string" do
write_csr_attributes('a string')
expect {
host.generate_certificate_request
}.to raise_error(Puppet::Error, /invalid CSR attributes, expected instance of Hash, received instance of String/)
end
it "raises when the file contains an empty array" do
write_csr_attributes([])
expect {
host.generate_certificate_request
}.to raise_error(Puppet::Error, /invalid CSR attributes, expected instance of Hash, received instance of Array/)
end
end
context "with extension requests from csr_attributes file" do
let(:ca) { Puppet::SSL::CertificateAuthority.new }
it "generates a CSR when the csr_attributes file is an empty hash" do
write_csr_attributes(csr_attributes_content)
host.generate_certificate_request
end
context "and subjectAltName" do
it "raises an error if you include subjectAltName in csr_attributes" do
csr_attributes_content['extension_requests']['subjectAltName'] = 'foo'
write_csr_attributes(csr_attributes_content)
expect { host.generate_certificate_request }.to raise_error(Puppet::Error, /subjectAltName.*conflicts with internally used extension request/)
end
it "properly merges subjectAltName when in settings" do
Puppet.settings[:dns_alt_names] = 'althostname.nowhere'
write_csr_attributes(csr_attributes_content)
host.generate_certificate_request
csr = Puppet::SSL::CertificateRequest.indirection.find(host.name)
expect(csr.subject_alt_names).to include('DNS:althostname.nowhere')
end
end
context "without subjectAltName" do
before do
write_csr_attributes(csr_attributes_content)
host.generate_certificate_request
end
it "pulls extension attributes from the csr_attributes file into the certificate" do
csr = Puppet::SSL::CertificateRequest.indirection.find(host.name)
expect(csr.request_extensions).to have(3).items
expect(csr.request_extensions).to include('oid' => 'pp_uuid', 'value' => 'abcdef')
expect(csr.request_extensions).to include('oid' => 'pp_instance_id', 'value' => '1234')
expect(csr.request_extensions).to include('oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'some-value')
end
it "copies extension requests to certificate" do
cert = ca.sign(host.name)
expect(cert.custom_extensions).to include('oid' => 'pp_uuid', 'value' => 'abcdef')
expect(cert.custom_extensions).to include('oid' => 'pp_instance_id', 'value' => '1234')
expect(cert.custom_extensions).to include('oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'some-value')
end
it "does not copy custom attributes to certificate" do
cert = ca.sign(host.name)
cert.custom_extensions.each do |ext|
expect(Puppet::SSL::Oids.subtree_of?('1.3.6.1.4.1.34380.2', ext['oid'])).to be_false
end
end
end
end
end
|