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 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