beaker-pe 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -3
- data/lib/beaker-pe.rb +2 -0
- data/lib/beaker-pe/install/ca_utils.rb +192 -0
- data/lib/beaker-pe/version.rb +1 -1
- data/spec/beaker-pe/install/ca_utils_spec.rb +42 -0
- data/spec/beaker-pe/pe-client-tools/executable_helper_spec.rb +54 -13
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 472cb8527da6bbb6256c8342fff325b91dfe0d62
|
4
|
+
data.tar.gz: 75b005236142feec1df7954cac688d4d4f9f613c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24d74792e19f75a3d33f30de4644878dcc742a00b872775c8e30965a891e86641a89fff1a106cdf0a6b8fd9260dfb886890c013ac908f55e609d709419d5e554
|
7
|
+
data.tar.gz: 05daf324e0665af413f85c35dbefc81e2cc1e310bfb734328f93adb02ba4298993f4c41843a299e41200f36040efa8b9dd6e6c1d82319c99110337b79ca73a8b
|
data/Gemfile
CHANGED
@@ -17,9 +17,7 @@ group :acceptance_testing do
|
|
17
17
|
gem "beaker-vmpooler", *location_for(ENV['BEAKER_VMPOOLER_VERSION'] || '~> 1.3')
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
gem "scooter", *location_for(ENV['SCOOTER_VERSION'] || '~> 3.0')
|
22
|
-
end
|
20
|
+
gem "scooter", *location_for(ENV['SCOOTER_VERSION'] || '~> 4.3')
|
23
21
|
|
24
22
|
gem 'deep_merge'
|
25
23
|
|
data/lib/beaker-pe.rb
CHANGED
@@ -5,6 +5,7 @@ require 'stringify-hash'
|
|
5
5
|
require 'beaker-pe/version'
|
6
6
|
require 'beaker-pe/install/pe_defaults'
|
7
7
|
require 'beaker-pe/install/pe_utils'
|
8
|
+
require 'beaker-pe/install/ca_utils'
|
8
9
|
require 'beaker-pe/options/pe_version_scraper'
|
9
10
|
require 'beaker-pe/pe-client-tools/config_file_helper'
|
10
11
|
require 'beaker-pe/pe-client-tools/install_helper'
|
@@ -16,6 +17,7 @@ module Beaker
|
|
16
17
|
include Beaker::DSL::InstallUtils::PEDefaults
|
17
18
|
include Beaker::DSL::InstallUtils::PEUtils
|
18
19
|
include Beaker::DSL::InstallUtils::PEClientTools
|
20
|
+
include Beaker::DSL::InstallUtils::CAUtils
|
19
21
|
include Beaker::Options::PEVersionScraper
|
20
22
|
include Beaker::DSL::PEClientTools::ConfigFileHelper
|
21
23
|
include Beaker::DSL::PEClientTools::ExecutableHelper
|
@@ -0,0 +1,192 @@
|
|
1
|
+
#Much of this is taken from PuppetSpec:SSL
|
2
|
+
require "openssl"
|
3
|
+
|
4
|
+
module Beaker
|
5
|
+
module DSL
|
6
|
+
module InstallUtils
|
7
|
+
module CAUtils
|
8
|
+
PRIVATE_KEY_LENGTH = 2048
|
9
|
+
FIVE_YEARS = 5 * 365 * 24 * 60 * 60
|
10
|
+
CA_EXTENSIONS = [
|
11
|
+
["basicConstraints", "CA:TRUE", true],
|
12
|
+
["keyUsage", "keyCertSign, cRLSign", true],
|
13
|
+
["subjectKeyIdentifier", "hash", false],
|
14
|
+
["authorityKeyIdentifier", "keyid:always", false]
|
15
|
+
]
|
16
|
+
NODE_EXTENSIONS = [
|
17
|
+
["keyUsage", "digitalSignature", true],
|
18
|
+
["subjectKeyIdentifier", "hash", false]
|
19
|
+
]
|
20
|
+
DEFAULT_SIGNING_DIGEST = OpenSSL::Digest::SHA256.new
|
21
|
+
DEFAULT_REVOCATION_REASON = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE
|
22
|
+
ROOT_CA_NAME = "/CN=root-ca"
|
23
|
+
INT_CA_NAME = "/CN=intermediate-ca"
|
24
|
+
EXPLANATORY_TEXT = <<-EOT
|
25
|
+
# Root Issuer: #{ROOT_CA_NAME}
|
26
|
+
# Intermediate Issuer: #{INT_CA_NAME}
|
27
|
+
EOT
|
28
|
+
|
29
|
+
# Generate CA bundle with root and intermediate certs, as well as CRL chain and private key for
|
30
|
+
# the intermediate CA, pushed to the host for use during PE install with pe_install::signing_ca
|
31
|
+
#
|
32
|
+
# @param [Host] host The host to create CA bundle files on. Defaults to global 'master' object.
|
33
|
+
# @param [String] targetdir Location to save files on host, to be referenced in pe.conf for install.
|
34
|
+
# @return [Hash] File names => where they were put on the host
|
35
|
+
def generate_ca_bundle_on(host = master, targetdir = '/tmp/ca_bundle')
|
36
|
+
files = {}
|
37
|
+
pki = create_chained_pki
|
38
|
+
on(host, "mkdir -p #{targetdir}", :acceptable_exit_codes => [0])
|
39
|
+
pki.each do |name,cert|
|
40
|
+
create_remote_file(host, "#{targetdir}/#{name}", cert.to_s, :acceptable_exit_codes => [0])
|
41
|
+
files["#{name}".to_sym] = "#{targetdir}/#{name}"
|
42
|
+
end
|
43
|
+
files
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_private_key(length = PRIVATE_KEY_LENGTH)
|
47
|
+
OpenSSL::PKey::RSA.new(length)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self_signed_ca(key, name)
|
51
|
+
cert = OpenSSL::X509::Certificate.new
|
52
|
+
|
53
|
+
cert.public_key = key.public_key
|
54
|
+
cert.subject = OpenSSL::X509::Name.parse(name)
|
55
|
+
cert.issuer = cert.subject
|
56
|
+
cert.version = 2
|
57
|
+
cert.serial = rand(2**128)
|
58
|
+
|
59
|
+
not_before = just_now
|
60
|
+
cert.not_before = not_before
|
61
|
+
cert.not_after = not_before + FIVE_YEARS
|
62
|
+
|
63
|
+
ext_factory = extension_factory_for(cert, cert)
|
64
|
+
CA_EXTENSIONS.each do |ext|
|
65
|
+
extension = ext_factory.create_extension(*ext)
|
66
|
+
cert.add_extension(extension)
|
67
|
+
end
|
68
|
+
|
69
|
+
cert.sign(key, DEFAULT_SIGNING_DIGEST)
|
70
|
+
|
71
|
+
cert
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_csr(key, name)
|
75
|
+
csr = OpenSSL::X509::Request.new
|
76
|
+
|
77
|
+
csr.public_key = key.public_key
|
78
|
+
csr.subject = OpenSSL::X509::Name.parse(name)
|
79
|
+
csr.version = 2
|
80
|
+
csr.sign(key, DEFAULT_SIGNING_DIGEST)
|
81
|
+
|
82
|
+
csr
|
83
|
+
end
|
84
|
+
|
85
|
+
def sign(ca_key, ca_cert, csr, extensions = NODE_EXTENSIONS)
|
86
|
+
cert = OpenSSL::X509::Certificate.new
|
87
|
+
|
88
|
+
cert.public_key = csr.public_key
|
89
|
+
cert.subject = csr.subject
|
90
|
+
cert.issuer = ca_cert.subject
|
91
|
+
cert.version = 2
|
92
|
+
cert.serial = rand(2**128)
|
93
|
+
|
94
|
+
not_before = just_now
|
95
|
+
cert.not_before = not_before
|
96
|
+
cert.not_after = not_before + FIVE_YEARS
|
97
|
+
|
98
|
+
ext_factory = extension_factory_for(ca_cert, cert)
|
99
|
+
extensions.each do |ext|
|
100
|
+
extension = ext_factory.create_extension(*ext)
|
101
|
+
cert.add_extension(extension)
|
102
|
+
end
|
103
|
+
|
104
|
+
cert.sign(ca_key, DEFAULT_SIGNING_DIGEST)
|
105
|
+
|
106
|
+
cert
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_crl_for(ca_cert, ca_key)
|
110
|
+
crl = OpenSSL::X509::CRL.new
|
111
|
+
crl.version = 1
|
112
|
+
crl.issuer = ca_cert.subject
|
113
|
+
|
114
|
+
ef = extension_factory_for(ca_cert)
|
115
|
+
crl.add_extension(
|
116
|
+
ef.create_extension(["authorityKeyIdentifier", "keyid:always", false]))
|
117
|
+
crl.add_extension(
|
118
|
+
OpenSSL::X509::Extension.new("crlNumber", OpenSSL::ASN1::Integer(0)))
|
119
|
+
|
120
|
+
not_before = just_now
|
121
|
+
crl.last_update = not_before
|
122
|
+
crl.next_update = not_before + FIVE_YEARS
|
123
|
+
crl.sign(ca_key, DEFAULT_SIGNING_DIGEST)
|
124
|
+
|
125
|
+
crl
|
126
|
+
end
|
127
|
+
|
128
|
+
def revoke(serial, crl, ca_key)
|
129
|
+
revoked = OpenSSL::X509::Revoked.new
|
130
|
+
revoked.serial = serial
|
131
|
+
revoked.time = Time.now
|
132
|
+
revoked.add_extension(
|
133
|
+
OpenSSL::X509::Extension.new("CRLReason",
|
134
|
+
OpenSSL::ASN1::Enumerated(DEFAULT_REVOCATION_REASON)))
|
135
|
+
|
136
|
+
crl.add_revoked(revoked)
|
137
|
+
extensions = crl.extensions.group_by{|e| e.oid == 'crlNumber' }
|
138
|
+
crl_number = extensions[true].first
|
139
|
+
unchanged_exts = extensions[false]
|
140
|
+
|
141
|
+
next_crl_number = crl_number.value.to_i + 1
|
142
|
+
new_crl_number_ext = OpenSSL::X509::Extension.new("crlNumber",
|
143
|
+
OpenSSL::ASN1::Integer(next_crl_number))
|
144
|
+
|
145
|
+
crl.extensions = unchanged_exts + [new_crl_number_ext]
|
146
|
+
crl.sign(ca_key, DEFAULT_SIGNING_DIGEST)
|
147
|
+
|
148
|
+
crl
|
149
|
+
end
|
150
|
+
|
151
|
+
def create_chained_pki
|
152
|
+
root_key = create_private_key
|
153
|
+
root_cert = self_signed_ca(root_key, ROOT_CA_NAME)
|
154
|
+
root_crl = create_crl_for(root_cert, root_key)
|
155
|
+
|
156
|
+
int_key = create_private_key
|
157
|
+
int_csr = create_csr(int_key, INT_CA_NAME)
|
158
|
+
int_cert = sign(root_key, root_cert, int_csr, CA_EXTENSIONS)
|
159
|
+
int_crl = create_crl_for(int_cert, int_key)
|
160
|
+
|
161
|
+
int_ca_bundle = bundle(int_cert, root_cert)
|
162
|
+
int_crl_chain = bundle(int_crl, root_crl)
|
163
|
+
|
164
|
+
{
|
165
|
+
:root_cert => root_cert,
|
166
|
+
:int_cert => int_cert,
|
167
|
+
:int_ca_bundle => int_ca_bundle,
|
168
|
+
:int_key => int_key,
|
169
|
+
:int_crl_chain => int_crl_chain,
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
173
|
+
def just_now
|
174
|
+
Time.now - 1
|
175
|
+
end
|
176
|
+
|
177
|
+
def extension_factory_for(ca, cert = nil)
|
178
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
179
|
+
ef.issuer_certificate = ca
|
180
|
+
ef.subject_certificate = cert if cert
|
181
|
+
|
182
|
+
ef
|
183
|
+
end
|
184
|
+
|
185
|
+
def bundle(*items)
|
186
|
+
items.map {|i| EXPLANATORY_TEXT + i.to_pem }.join("\n")
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
data/lib/beaker-pe/version.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include Beaker::DSL::InstallUtils::CAUtils
|
3
|
+
|
4
|
+
describe Beaker::DSL::InstallUtils::CAUtils do
|
5
|
+
let(:dummy_pki) {
|
6
|
+
{
|
7
|
+
:root_cert => 'dummy_root_cert',
|
8
|
+
:int_cert => 'dummy_int_cert',
|
9
|
+
:int_ca_bundle => 'dummy_int_bundle',
|
10
|
+
:int_key => 'dummy_int_key',
|
11
|
+
:int_crl_chain => 'dummy_int_crl_chain',
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
allow(subject).to receive(:create_chained_pki).and_return(dummy_pki)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'generate_ca_bundle_on' do
|
20
|
+
let(:host) { make_host( 'unixhost', { :platform => 'linux'})}
|
21
|
+
let(:bundledir) { '/tmp/ca_bundle' }
|
22
|
+
let(:expected) {
|
23
|
+
{
|
24
|
+
:root_cert => "#{bundledir}/root_cert",
|
25
|
+
:int_cert => "#{bundledir}/int_cert",
|
26
|
+
:int_ca_bundle => "#{bundledir}/int_ca_bundle",
|
27
|
+
:int_key => "#{bundledir}/int_key",
|
28
|
+
:int_crl_chain => "#{bundledir}/int_crl_chain",
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
it "generates certs on host" do
|
33
|
+
expect(subject).to receive(:on).with(host, "mkdir -p #{bundledir}", :acceptable_exit_codes => [0])
|
34
|
+
expect(subject).to receive(:create_remote_file).with(host,"#{bundledir}/root_cert", "dummy_root_cert", :acceptable_exit_codes => [0])
|
35
|
+
expect(subject).to receive(:create_remote_file).with(host,"#{bundledir}/int_cert", "dummy_int_cert", :acceptable_exit_codes => [0])
|
36
|
+
expect(subject).to receive(:create_remote_file).with(host,"#{bundledir}/int_ca_bundle", "dummy_int_bundle", :acceptable_exit_codes => [0])
|
37
|
+
expect(subject).to receive(:create_remote_file).with(host,"#{bundledir}/int_key", "dummy_int_key", :acceptable_exit_codes => [0])
|
38
|
+
expect(subject).to receive(:create_remote_file).with(host,"#{bundledir}/int_crl_chain", "dummy_int_crl_chain", :acceptable_exit_codes => [0])
|
39
|
+
expect( subject.generate_ca_bundle_on(host,"#{bundledir}") ).to eq(expected)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -64,25 +64,66 @@ describe MixedWithExecutableHelper do
|
|
64
64
|
|
65
65
|
context 'puppet access login with lifetime parameter' do
|
66
66
|
let(:logger) {Beaker::Logger.new}
|
67
|
-
let(:test_host) {
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
let(:
|
67
|
+
let(:test_host) {
|
68
|
+
make_host('my_super_host', {
|
69
|
+
:roles => ['master', 'agent'],
|
70
|
+
:platform => 'linux',
|
71
|
+
:type => 'pe'
|
72
|
+
}
|
73
|
+
)
|
74
|
+
}
|
75
|
+
let(:credentials) {
|
76
|
+
mock = Object.new
|
77
|
+
allow(mock).to receive(:login).and_return('T')
|
78
|
+
allow(mock).to receive(:password).and_return('Swift')
|
79
|
+
mock
|
80
|
+
}
|
81
|
+
let(:test_dispatcher) {
|
82
|
+
mock = Object.new
|
83
|
+
allow(mock).to receive(:credentials).and_return(credentials)
|
84
|
+
mock
|
85
|
+
}
|
76
86
|
|
77
87
|
before do
|
78
88
|
allow(logger).to receive(:debug) { true }
|
79
|
-
expect(test_dispatcher).to be_kind_of(Scooter::HttpDispatchers::ConsoleDispatcher)
|
80
89
|
expect(test_host).to be_kind_of(Beaker::Host)
|
81
|
-
expect(test_host).to receive(:exec)
|
82
90
|
end
|
83
91
|
|
84
|
-
it '
|
85
|
-
|
92
|
+
it 'passes the lifetime value to :puppet_access_on on linux' do
|
93
|
+
lifetime_value = '5d'
|
94
|
+
|
95
|
+
expect(subject).to receive(:puppet_access_on).with(
|
96
|
+
test_host,
|
97
|
+
"login",
|
98
|
+
"--lifetime #{lifetime_value}",
|
99
|
+
anything
|
100
|
+
)
|
101
|
+
|
102
|
+
expect{
|
103
|
+
subject.login_with_puppet_access_on(
|
104
|
+
test_host,
|
105
|
+
test_dispatcher,
|
106
|
+
{:lifetime => lifetime_value}
|
107
|
+
)
|
108
|
+
}.not_to raise_error
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'passes the lifetime value to the passed dispatcher on windows' do
|
112
|
+
test_host[:platform] = "win-stuff"
|
113
|
+
allow(subject).to receive(:create_remote_file)
|
114
|
+
lifetime_value = '6d'
|
115
|
+
|
116
|
+
expect(test_dispatcher).to receive(
|
117
|
+
:acquire_token_with_credentials
|
118
|
+
).with(lifetime_value)
|
119
|
+
|
120
|
+
expect{
|
121
|
+
subject.login_with_puppet_access_on(
|
122
|
+
test_host,
|
123
|
+
test_dispatcher,
|
124
|
+
{:lifetime => lifetime_value}
|
125
|
+
)
|
126
|
+
}.not_to raise_error
|
86
127
|
end
|
87
128
|
end
|
88
129
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beaker-pe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppetlabs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -253,6 +253,7 @@ files:
|
|
253
253
|
- bin/beaker-template
|
254
254
|
- docs/how_to/install_puppet_enterprise.md
|
255
255
|
- lib/beaker-pe.rb
|
256
|
+
- lib/beaker-pe/install/ca_utils.rb
|
256
257
|
- lib/beaker-pe/install/feature_flags.rb
|
257
258
|
- lib/beaker-pe/install/pe_defaults.rb
|
258
259
|
- lib/beaker-pe/install/pe_utils.rb
|
@@ -262,6 +263,7 @@ files:
|
|
262
263
|
- lib/beaker-pe/pe-client-tools/install_helper.rb
|
263
264
|
- lib/beaker-pe/version.rb
|
264
265
|
- spec/beaker-pe/helpers_spec.rb
|
266
|
+
- spec/beaker-pe/install/ca_utils_spec.rb
|
265
267
|
- spec/beaker-pe/install/feature_flags_spec.rb
|
266
268
|
- spec/beaker-pe/install/pe_defaults_spec.rb
|
267
269
|
- spec/beaker-pe/install/pe_utils_spec.rb
|