Skip to content

Commit 727343a

Browse files
committed
profile::certbot_incommon
1 parent 1109dc0 commit 727343a

File tree

4 files changed

+296
-0
lines changed

4 files changed

+296
-0
lines changed

manifests/profile/certbot_incommon.pp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# @param certs domains/certificates with haproxy services; wildcard implicitly added
2+
# example: "quod": { "somejournal.org": ["san-for-journal.org"] }
3+
# @param simple_certs domains/certificates for standalone hosts; no implicit wildcard
4+
# example: "somedomain.org": ["san-for-domain.org","*.somedomain.org"]
5+
class nebula::profile::certbot_incommon (
6+
Hash[String, Hash[String, Array[String]]] $certs = {},
7+
Hash[String, Array[String]] $simple_certs = {},
8+
String $cert_dir = '/var/local/cert_dir',
9+
String $haproxy_cert_dir = '/var/local/haproxy_cert_dir',
10+
String $letsencrypt_email = '[email protected]',
11+
String $server = 'https://acme.sectigo.com/v2/InCommonECCOV'
12+
) {
13+
ensure_packages([
14+
'certbot',
15+
])
16+
17+
file { '/tmp/all_cert_commands_incommon':
18+
content => template('nebula/profile/certbot_incommon/commands.erb')
19+
}
20+
21+
$certs.each |$service, $domains| {
22+
$domains.each |$main_domain, $alt_domains| {
23+
concat { "${cert_dir}/${main_domain}.crt":
24+
group => 'puppet',
25+
}
26+
27+
concat { "${cert_dir}/${main_domain}.key":
28+
group => 'puppet',
29+
}
30+
31+
concat { "${haproxy_cert_dir}/${service}/${main_domain}.pem":
32+
group => 'puppet',
33+
}
34+
35+
concat_fragment { "${main_domain}.crt cert":
36+
target => "${cert_dir}/${main_domain}.crt",
37+
source => "/etc/letsencrypt/live/${main_domain}/fullchain.pem"
38+
}
39+
40+
concat_fragment { "${main_domain}.key key":
41+
target => "${cert_dir}/${main_domain}.key",
42+
source => "/etc/letsencrypt/live/${main_domain}/privkey.pem"
43+
}
44+
45+
concat_fragment { "${main_domain}.pem cert":
46+
order => '01',
47+
target => "${haproxy_cert_dir}/${service}/${main_domain}.pem",
48+
source => "/etc/letsencrypt/live/${main_domain}/fullchain.pem"
49+
}
50+
51+
concat_fragment { "${main_domain}.pem key":
52+
order => '02',
53+
target => "${haproxy_cert_dir}/${service}/${main_domain}.pem",
54+
source => "/etc/letsencrypt/live/${main_domain}/privkey.pem"
55+
}
56+
}
57+
}
58+
59+
$simple_certs.each |$domain, $sans| {
60+
concat { "${cert_dir}/${domain}.crt":
61+
group => 'puppet',
62+
}
63+
64+
concat { "${cert_dir}/${domain}.key":
65+
group => 'puppet',
66+
}
67+
68+
concat_fragment { "${cert_dir}/${domain}.crt cert":
69+
target => "${cert_dir}/${domain}.crt",
70+
source => "/etc/letsencrypt/live/${domain}/fullchain.pem",
71+
}
72+
73+
concat_fragment { "${cert_dir}/${domain}.key key":
74+
target => "${cert_dir}/${domain}.key",
75+
source => "/etc/letsencrypt/live/${domain}/privkey.pem",
76+
}
77+
}
78+
}

manifests/role/puppet/master.pp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
include nebula::profile::puppet::master
1212
include nebula::profile::certbot_route53
1313
include nebula::profile::certbot_cloudflare
14+
include nebula::profile::certbot_incommon
1415

1516
# FIXME because there's also a git repo
1617
include nebula::profile::krb5
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright (c) 2022 The Regents of the University of Michigan.
4+
# All Rights Reserved. Licensed according to the terms of the Revised
5+
# BSD License. See LICENSE.txt for details.
6+
require "spec_helper"
7+
8+
describe "nebula::profile::certbot_incommon" do
9+
on_supported_os.each do |os, os_facts|
10+
context "on #{os}" do
11+
let(:facts) { os_facts }
12+
13+
it { is_expected.to compile }
14+
15+
it { is_expected.to contain_package("certbot") }
16+
17+
context "with a single cert" do
18+
let(:params) do
19+
{
20+
certs: {"onlyservice" => {"example.invalid" => []}},
21+
cert_dir: "/certs",
22+
haproxy_cert_dir: "/haproxy",
23+
letsencrypt_email: "[email protected]"
24+
}
25+
end
26+
27+
it { is_expected.to compile }
28+
29+
it do
30+
expect(subject).to contain_file("/tmp/all_cert_commands_incommon")
31+
.with_content(
32+
<<~CREDENTIALS
33+
certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "example.invalid,*.example.invalid"
34+
CREDENTIALS
35+
)
36+
end
37+
38+
it { is_expected.to contain_concat("/certs/example.invalid.crt").with_group("puppet") }
39+
it { is_expected.to contain_concat("/certs/example.invalid.key").with_group("puppet") }
40+
it { is_expected.to contain_concat("/haproxy/onlyservice/example.invalid.pem").with_group("puppet") }
41+
42+
it do
43+
expect(subject).to contain_concat_fragment("example.invalid.crt cert")
44+
.with_target("/certs/example.invalid.crt")
45+
.with_source("/etc/letsencrypt/live/example.invalid/fullchain.pem")
46+
end
47+
48+
it do
49+
expect(subject).to contain_concat_fragment("example.invalid.key key")
50+
.with_target("/certs/example.invalid.key")
51+
.with_source("/etc/letsencrypt/live/example.invalid/privkey.pem")
52+
end
53+
54+
it do
55+
expect(subject).to contain_concat_fragment("example.invalid.pem cert")
56+
.with_order("01")
57+
.with_target("/haproxy/onlyservice/example.invalid.pem")
58+
.with_source("/etc/letsencrypt/live/example.invalid/fullchain.pem")
59+
end
60+
61+
it do
62+
expect(subject).to contain_concat_fragment("example.invalid.pem key")
63+
.with_order("02")
64+
.with_target("/haproxy/onlyservice/example.invalid.pem")
65+
.with_source("/etc/letsencrypt/live/example.invalid/privkey.pem")
66+
end
67+
end
68+
69+
context "with a multiple certs and services" do
70+
let(:params) do
71+
{
72+
certs: {
73+
"a" => {"abc.invalid" => %w[abc.example], "abc.com" => []},
74+
"z" => {"zyx.invalid" => []}
75+
}
76+
}
77+
end
78+
79+
it do
80+
expect(subject).to contain_file("/tmp/all_cert_commands_incommon")
81+
.with_content(
82+
<<~CREDENTIALS
83+
certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "abc.invalid,*.abc.invalid,abc.example,*.abc.example"
84+
certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "abc.com,*.abc.com"
85+
certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "zyx.invalid,*.zyx.invalid"
86+
CREDENTIALS
87+
)
88+
end
89+
90+
it { is_expected.to compile }
91+
92+
it { is_expected.to contain_concat("/var/local/cert_dir/abc.invalid.crt") }
93+
it { is_expected.to contain_concat("/var/local/cert_dir/abc.invalid.key") }
94+
it { is_expected.to contain_concat("/var/local/haproxy_cert_dir/a/abc.invalid.pem") }
95+
it { is_expected.to contain_concat_fragment("abc.invalid.crt cert") }
96+
it { is_expected.to contain_concat_fragment("abc.invalid.key key") }
97+
it { is_expected.to contain_concat_fragment("abc.invalid.pem cert") }
98+
it { is_expected.to contain_concat_fragment("abc.invalid.pem key") }
99+
100+
it { is_expected.to contain_concat("/var/local/cert_dir/abc.com.crt") }
101+
it { is_expected.to contain_concat("/var/local/cert_dir/abc.com.key") }
102+
it { is_expected.to contain_concat("/var/local/haproxy_cert_dir/a/abc.com.pem") }
103+
it { is_expected.to contain_concat_fragment("abc.com.crt cert") }
104+
it { is_expected.to contain_concat_fragment("abc.com.key key") }
105+
it { is_expected.to contain_concat_fragment("abc.com.pem cert") }
106+
it { is_expected.to contain_concat_fragment("abc.com.pem key") }
107+
108+
it { is_expected.to contain_concat("/var/local/cert_dir/zyx.invalid.crt") }
109+
it { is_expected.to contain_concat("/var/local/cert_dir/zyx.invalid.key") }
110+
it { is_expected.to contain_concat("/var/local/haproxy_cert_dir/z/zyx.invalid.pem") }
111+
it { is_expected.to contain_concat_fragment("zyx.invalid.crt cert") }
112+
it { is_expected.to contain_concat_fragment("zyx.invalid.key key") }
113+
it { is_expected.to contain_concat_fragment("zyx.invalid.pem cert") }
114+
it { is_expected.to contain_concat_fragment("zyx.invalid.pem key") }
115+
116+
it { is_expected.not_to contain_concat("/var/local/cert_dir/abc.example.crt") }
117+
it { is_expected.not_to contain_concat("/var/local/cert_dir/abc.example.key") }
118+
it { is_expected.not_to contain_concat("/var/local/haproxy_cert_dir/a/abc.example.pem") }
119+
it { is_expected.not_to contain_concat_fragment("abc.example.crt cert") }
120+
it { is_expected.not_to contain_concat_fragment("abc.example.key key") }
121+
it { is_expected.not_to contain_concat_fragment("abc.example.pem cert") }
122+
it { is_expected.not_to contain_concat_fragment("abc.example.pem key") }
123+
end
124+
125+
context "with one simple cert, no SANs" do
126+
let(:params) do
127+
{
128+
simple_certs: {
129+
"abc.example": []
130+
}
131+
}
132+
end
133+
134+
it { is_expected.to compile }
135+
136+
it do
137+
expect(subject).to contain_file("/tmp/all_cert_commands_incommon")
138+
.with_content(%r{certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "abc.example"})
139+
end
140+
141+
it do
142+
expect(subject).to contain_concat_fragment("/var/local/cert_dir/abc.example.crt cert")
143+
.with_target("/var/local/cert_dir/abc.example.crt")
144+
.with_source("/etc/letsencrypt/live/abc.example/fullchain.pem")
145+
end
146+
147+
it do
148+
expect(subject).to contain_concat_fragment("/var/local/cert_dir/abc.example.key key")
149+
.with_target("/var/local/cert_dir/abc.example.key")
150+
.with_source("/etc/letsencrypt/live/abc.example/privkey.pem")
151+
end
152+
end
153+
154+
context "with one simple cert, two SANs" do
155+
let(:params) do
156+
{
157+
simple_certs: {
158+
"abc.example": ["san.local", "xyz.local"]
159+
}
160+
}
161+
end
162+
163+
it do
164+
expect(subject).to contain_file("/tmp/all_cert_commands_incommon")
165+
.with_content(
166+
<<~CREDENTIALS
167+
certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "abc.example,san.local,xyz.local"
168+
CREDENTIALS
169+
)
170+
end
171+
end
172+
173+
context "with two simple certs" do
174+
let(:params) do
175+
{
176+
simple_certs: {
177+
"abc.example": [],
178+
"xyz.example": ["alt.example", "*.alt.example"]
179+
}
180+
}
181+
end
182+
183+
it do
184+
expect(subject).to contain_file("/tmp/all_cert_commands_incommon")
185+
.with_content(%r{certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "abc.example"})
186+
end
187+
188+
it do
189+
expect(subject).to contain_file("/tmp/all_cert_commands_incommon")
190+
.with_content(%r{certbot certonly --standalone --server "https://acme.sectigo.com/v2/InCommonECCOV" -m "[email protected]" -d "xyz.example,alt.example,\*.alt.example"})
191+
end
192+
193+
it do
194+
expect(subject).to contain_concat_fragment("/var/local/cert_dir/abc.example.crt cert")
195+
.with_target("/var/local/cert_dir/abc.example.crt")
196+
.with_source("/etc/letsencrypt/live/abc.example/fullchain.pem")
197+
end
198+
199+
it do
200+
expect(subject).to contain_concat_fragment("/var/local/cert_dir/xyz.example.crt cert")
201+
.with_target("/var/local/cert_dir/xyz.example.crt")
202+
.with_source("/etc/letsencrypt/live/xyz.example/fullchain.pem")
203+
end
204+
end
205+
end
206+
end
207+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<% @certs.each do |service, domains| -%>
2+
<% domains.each do |main_domain, alt_domains| -%>
3+
<% full_san = [main_domain, "*.#{main_domain}"] -%>
4+
<% alt_domains.each { |x| full_san += [x, "*.#{x}"] } -%>
5+
certbot certonly --standalone --server "<%= @server %>" -m "<%= @letsencrypt_email %>" -d "<%= full_san.join(",") %>"
6+
<% end -%>
7+
<% end -%>
8+
<% @simple_certs.each do |domain, sans| -%>
9+
certbot certonly --standalone --server "<%= @server %>" -m "<%= @letsencrypt_email %>" -d "<%= [domain, sans].flatten.join(",") %>"
10+
<% end -%>

0 commit comments

Comments
 (0)