amarillo 0.3.3 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4e3236346294475f1a163d18a26c6802d203f7fb9d9feb47c24f90ef117e2fb
4
- data.tar.gz: c02964b63238765fd4eacc43d61fb7c6aae1aa256374c447efa429d99d4816dd
3
+ metadata.gz: 5229f8188b6086ad5c09326cc438d8375703602036e50534cbb69d684a2ec9e7
4
+ data.tar.gz: b1a7005a37527eb00fd44dbc45cfa0ea3e232f90bbd8ad004f712bb74d8be0a5
5
5
  SHA512:
6
- metadata.gz: e8f1b4dbb46b7c28c3ba1f800e6b625351887e46212bd5dc34ea345ab993b9b4ddb58d664fd4a6504104f101a94cdf3a5e782d5100429e0c124efeaa277c7da7
7
- data.tar.gz: 3905e62aae46c7238416fbd60ce58afca677b05b146a3391170dcd99610cc2d086eedfc1972c6355035db49a7193b16a87d8dbd87023ab659329c4b3fdd00012
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
- options[:renew] = r
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
- y.renewCertificates
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 name
144
+ y.deleteCertificate options[:delete]
131
145
  else
132
- y.requestCertificate zone, name, email, options[:keytype]
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
 
@@ -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 2021 iAchieved.it LLC
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(zone, commonName, email, key_type)
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 2
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 2
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
- File.chmod(0600, keyOutputPath)
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 = config["commonName"]
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 zone, cn, email, key_type
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.3.3
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-07-24 00:00:00.000000000 Z
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.3.3
112
+ rubygems_version: 3.2.33
113
113
  signing_key:
114
114
  specification_version: 4
115
115
  summary: Amarillo