amarillo 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/amarillo +29 -8
- data/lib/amarillo/environment.rb +4 -1
- data/lib/amarillo.rb +63 -21
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5229f8188b6086ad5c09326cc438d8375703602036e50534cbb69d684a2ec9e7
|
4
|
+
data.tar.gz: b1a7005a37527eb00fd44dbc45cfa0ea3e232f90bbd8ad004f712bb74d8be0a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b167194f5fbb58f945fb5674d9466473cf9777a04536cbb709bdf7e75e018666c7421beb28dfc300ad49c5e522f2250339f8b92c882273608525084708caa088
|
7
|
+
data.tar.gz: 1e40be3bb8babc91470dca9588c51467cd572e99dada1d9e716f4cbe57e669c0731956a3e36598c35a37a9a015369b88b01cb7ffe604442463d6b884dd1d907d
|
data/bin/amarillo
CHANGED
@@ -35,12 +35,16 @@ OptionParser.new do |opts|
|
|
35
35
|
options[:list] = l
|
36
36
|
end
|
37
37
|
|
38
|
-
opts.on("-d", "--delete", "Delete certificate") do |d|
|
38
|
+
opts.on("-d", "--delete COMMONNAME", "Delete certificate specified by COMMONNAME") do |d|
|
39
39
|
options[:delete] = d
|
40
40
|
end
|
41
41
|
|
42
|
-
opts.on("-r", "--renew", "Renew certificates") do |r|
|
43
|
-
|
42
|
+
opts.on("-r", "--renew [COMMONNAME]", "Renew specific or all certificates") do |r|
|
43
|
+
if r
|
44
|
+
options[:renew] = r
|
45
|
+
else
|
46
|
+
options[:renew] = 'all'
|
47
|
+
end
|
44
48
|
end
|
45
49
|
|
46
50
|
opts.on("-z", "--zone ZONE", "Hosted zone") do |z|
|
@@ -59,6 +63,10 @@ OptionParser.new do |opts|
|
|
59
63
|
options[:keytype] = k
|
60
64
|
end
|
61
65
|
|
66
|
+
opts.on("-s", "--script SCRIPT", "A script or command to execute after a successful certificate creation or renewal") do |s|
|
67
|
+
options[:script] = s
|
68
|
+
end
|
69
|
+
|
62
70
|
opts.on("-a", "--amarillo-home AMARILLO_HOME", "Home directory for configuration, keys, and certificates") do |o|
|
63
71
|
options[:amarillo_home] = a
|
64
72
|
end
|
@@ -107,8 +115,8 @@ else
|
|
107
115
|
email = options[:email]
|
108
116
|
end
|
109
117
|
|
110
|
-
if options[:name].nil? and options[:renew].nil? and options[:list].nil? then
|
111
|
-
puts "Usage: amarillo --name COMMONNAME [--zone ZONE] [--email EMAIL] [--amarillo-home AMARILLO_HOME]"
|
118
|
+
if options[:name].nil? and options[:renew].nil? and options[:list].nil? and options[:delete].nil? then
|
119
|
+
puts "Usage: amarillo [--name COMMONNAME|--renew|--renew COMMONNAME] [--zone ZONE] [--email EMAIL] [--amarillo-home AMARILLO_HOME]"
|
112
120
|
exit -1
|
113
121
|
else
|
114
122
|
name = options[:name]
|
@@ -123,13 +131,26 @@ end
|
|
123
131
|
y = Amarillo.new amarillo_home
|
124
132
|
|
125
133
|
if options[:renew] then
|
126
|
-
|
134
|
+
|
135
|
+
if options[:renew] != 'all' then
|
136
|
+
y.renewCertificate options[:renew]
|
137
|
+
else
|
138
|
+
y.renewCertificates
|
139
|
+
end
|
140
|
+
|
127
141
|
elsif options[:list] then
|
128
142
|
y.listCertificates
|
129
143
|
elsif options[:delete] then
|
130
|
-
y.deleteCertificate
|
144
|
+
y.deleteCertificate options[:delete]
|
131
145
|
else
|
132
|
-
|
146
|
+
config = {
|
147
|
+
"zone" => zone,
|
148
|
+
"commonName" => name,
|
149
|
+
"email" => email,
|
150
|
+
"key_type" => options[:keytype],
|
151
|
+
"script" => options[:script]
|
152
|
+
}
|
153
|
+
y.requestCertificate certConfig: config
|
133
154
|
end
|
134
155
|
|
135
156
|
|
data/lib/amarillo/environment.rb
CHANGED
@@ -105,7 +105,10 @@ HEREDOC
|
|
105
105
|
"email" => email,
|
106
106
|
"zone" => zone,
|
107
107
|
"nameservers" => ['208.67.222.222', '9.9.9.9'],
|
108
|
-
"key_type" => 'ec,secp384r1'
|
108
|
+
"key_type" => 'ec,secp384r1',
|
109
|
+
"owner" => 'root',
|
110
|
+
"group" => 'root',
|
111
|
+
"key_mode" => 0660
|
109
112
|
}}
|
110
113
|
File.write(@configFile, config.to_yaml)
|
111
114
|
else
|
data/lib/amarillo.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Inspired by Pete Keen's (pete@petekeen.net) post
|
4
4
|
# https://www.petekeen.net/lets-encrypt-without-certbot
|
5
5
|
#
|
6
|
-
# Copyright
|
6
|
+
# Copyright 2022 iAchieved.it LLC
|
7
7
|
#
|
8
8
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
9
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -86,7 +86,17 @@ class Amarillo
|
|
86
86
|
|
87
87
|
end
|
88
88
|
|
89
|
-
def requestCertificate(
|
89
|
+
def requestCertificate(configPath: nil, certConfig: nil)
|
90
|
+
|
91
|
+
if configPath
|
92
|
+
certConfig = YAML.load(File.read(configPath))
|
93
|
+
end
|
94
|
+
|
95
|
+
commonName = certConfig["commonName"]
|
96
|
+
email = certConfig["email"]
|
97
|
+
zone = certConfig["zone"]
|
98
|
+
key_type = certConfig["key_type"]
|
99
|
+
script = certConfig["script"]
|
90
100
|
|
91
101
|
@zone = zone
|
92
102
|
|
@@ -148,7 +158,7 @@ class Amarillo
|
|
148
158
|
|
149
159
|
@logger.info "Waiting for DNS record to propagate"
|
150
160
|
while !check_dns(commonName, nameservers, challengeValue)
|
151
|
-
sleep
|
161
|
+
sleep 5
|
152
162
|
@logger.info "Still waiting..."
|
153
163
|
end
|
154
164
|
|
@@ -157,20 +167,13 @@ class Amarillo
|
|
157
167
|
@logger.info "Requesting validation..."
|
158
168
|
authorization.dns.reload
|
159
169
|
while authorization.dns.status == 'pending'
|
160
|
-
sleep
|
170
|
+
sleep 5
|
161
171
|
@logger.info "DNS status: #{authorization.dns.status}"
|
162
172
|
authorization.dns.reload
|
163
173
|
end
|
164
174
|
|
165
175
|
@logger.info "Generating key"
|
166
176
|
|
167
|
-
# Create certificate yml
|
168
|
-
certConfig = {
|
169
|
-
"commonName" => commonName,
|
170
|
-
"email" => email,
|
171
|
-
"zone" => zone
|
172
|
-
}
|
173
|
-
|
174
177
|
if key_type
|
175
178
|
certConfig["key_type"] = key_type
|
176
179
|
else
|
@@ -218,7 +221,13 @@ class Amarillo
|
|
218
221
|
File.open(keyOutputPath, "w") do |f|
|
219
222
|
f.puts certPrivateKey.to_pem.to_s
|
220
223
|
end
|
221
|
-
|
224
|
+
|
225
|
+
keyMode = @config["defaults"]["key_mode"] || 0600
|
226
|
+
if keyMode
|
227
|
+
File.chmod(keyMode, keyOutputPath)
|
228
|
+
else
|
229
|
+
File.chmod(0600, keyOutputPath)
|
230
|
+
end
|
222
231
|
|
223
232
|
@logger.info "Saving certificate to #{certOutputPath}"
|
224
233
|
|
@@ -226,9 +235,21 @@ class Amarillo
|
|
226
235
|
f.puts order.certificate
|
227
236
|
end
|
228
237
|
|
238
|
+
owner = certConfig["owner"] || @config["defaults"]["owner"] || "root"
|
239
|
+
group = certConfig["group"] || @config["defaults"]["group"] || "root"
|
240
|
+
begin
|
241
|
+
FileUtils.chown(owner, group, keyOutputPath)
|
242
|
+
rescue
|
243
|
+
@logger.info "Unable to change ownership of key file #{keyOutputPath}"
|
244
|
+
end
|
245
|
+
|
229
246
|
certConfigFile = "#{@configsPath}/#{commonName}.yml"
|
247
|
+
|
248
|
+
@logger.info "Saving certificate configuration to #{certConfigFile}"
|
230
249
|
File.write(certConfigFile, certConfig.to_yaml)
|
231
250
|
|
251
|
+
self.doRenewalAction script
|
252
|
+
|
232
253
|
end
|
233
254
|
|
234
255
|
def cleanup(label, record_type, challengeValue)
|
@@ -256,10 +277,6 @@ class Amarillo
|
|
256
277
|
@route53.change_resource_record_sets(options)
|
257
278
|
end
|
258
279
|
|
259
|
-
def renewCertificate(zone, commonName, email)
|
260
|
-
|
261
|
-
end
|
262
|
-
|
263
280
|
def listCertificates
|
264
281
|
|
265
282
|
rows = []
|
@@ -293,6 +310,7 @@ class Amarillo
|
|
293
310
|
|
294
311
|
end
|
295
312
|
|
313
|
+
# Renew all certificates
|
296
314
|
def renewCertificates
|
297
315
|
t = Time.now
|
298
316
|
@logger.info "Renewing certificates"
|
@@ -300,10 +318,7 @@ class Amarillo
|
|
300
318
|
Dir["#{@configsPath}/*.yml"].each do |c|
|
301
319
|
config = YAML.load(File.read(c))
|
302
320
|
|
303
|
-
cn
|
304
|
-
email = config["email"]
|
305
|
-
zone = config["zone"]
|
306
|
-
key_type = config["key_type"]
|
321
|
+
cn = config["commonName"]
|
307
322
|
|
308
323
|
certificatePath = "#{@certificatePath}/#{cn}.crt"
|
309
324
|
raw = File.read certificatePath
|
@@ -312,12 +327,39 @@ class Amarillo
|
|
312
327
|
|
313
328
|
if daysToExpiration < 30 then
|
314
329
|
@logger.info "#{cn} certificate needs to be renewed"
|
315
|
-
self.requestCertificate
|
330
|
+
self.requestCertificate configPath: c
|
316
331
|
else
|
317
332
|
@logger.info "#{cn} certificate does not need to be renewed"
|
318
333
|
end
|
319
334
|
end
|
320
335
|
end
|
336
|
+
|
337
|
+
# Renew specific certificate, implied force
|
338
|
+
def renewCertificate(commonName)
|
339
|
+
|
340
|
+
configPath = "#{@configsPath}/#{commonName}.yml"
|
341
|
+
self.requestCertificate configPath: configPath
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
def doRenewalAction(renewal_action)
|
346
|
+
|
347
|
+
if renewal_action
|
348
|
+
|
349
|
+
@logger.info "Executing certificate renewal action: #{renewal_action}"
|
350
|
+
|
351
|
+
begin
|
352
|
+
%x( #{renewal_action} )
|
353
|
+
@logger.info "Renewal action returned: #{$?}"
|
354
|
+
rescue
|
355
|
+
@logger.error("Error executing certificate renewal action")
|
356
|
+
raise
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
end
|
362
|
+
|
321
363
|
end
|
322
364
|
|
323
365
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amarillo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iAchieved.it LLC
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acme-client
|
@@ -109,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
requirements: []
|
112
|
-
rubygems_version: 3.
|
112
|
+
rubygems_version: 3.2.33
|
113
113
|
signing_key:
|
114
114
|
specification_version: 4
|
115
115
|
summary: Amarillo
|