acmesmith 0.10.0 → 0.11.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
  SHA1:
3
- metadata.gz: 39060c7505c4a73bfccf496d1015c69573e247b7
4
- data.tar.gz: f021fc666dee39ce983143b8b42c6d89fe10e336
3
+ metadata.gz: bce001c8eca147fba2d1d2e0b43d30ebd175f096
4
+ data.tar.gz: 65fb44fdf5367fa3e6c66ecb837fd3119f07db76
5
5
  SHA512:
6
- metadata.gz: 07ee7ce1383349bd7fbc93d78fe97bca3d9407df833c3d7f299d5fd17ef1307118f5e50f8c28523a131cc9756cfb858d9aa465a43850d6f86a723b8f06515fdc
7
- data.tar.gz: be76cdfe37a4988c9dfdb1db3d3fb49bc16ba7fe719ae7ad588f22a1f636f74b19f9f5383464d52128055bcc83e9de7102528ba04b2df98b887b2deb157d6176
6
+ metadata.gz: a544bb8d9ee438806215471846bd71dd34fcd3dc0cdd38d15a130292d255c1f221492c1c129bcdb5906ac8afc5819b161296dd0b64607ad36149966f7cf23d7e
7
+ data.tar.gz: ecc46f9cc09ec3630d14a3052b43b51659fdaba8716e43095bc578326e7e5fc99174da54b26d80abc1579b8bb7c35e991e405a5238a38fd7c805ca985b9fa630
data/README.md CHANGED
@@ -62,6 +62,14 @@ $ acmesmith save-pkcs12 COMMON_NAME --output=PATH # Save certificate and p
62
62
  $ acmesmith autorenew [-d DAYS] # Renew certificates which being expired soon
63
63
  ```
64
64
 
65
+ ```
66
+ # Save (or update) certificate files and key in a one command
67
+ $ acmesmith save COMMON_NAME \
68
+ --version-file=/tmp/cert.txt # Path to save a certificate version for following run
69
+ --key-file=/tmp/cert.key # Path to save a key
70
+ --fullchain-file=/tmp/cert.pem # Path to save a certficiate and its chain (concatenated)
71
+ ```
72
+
65
73
  See `acmesmith help [subcommand]` for more help.
66
74
 
67
75
  ## Configuration
data/docs/vendor/aws.md CHANGED
@@ -103,4 +103,20 @@ Be sure to replace `{S3-REGION}` and `{YOUR-AWS-ACCOUNT-ID}` before applying it.
103
103
  }
104
104
  ```
105
105
 
106
+ #### Policy for ACM post issuing hook
107
+
108
+ ``` json
109
+ {
110
+ "Version": "2012-10-17",
111
+ "Statement": [
112
+ {
113
+ "Effect": "Allow",
114
+ "Action": ["acm:ImportCertificate", "acm:AddTagsToCertificate"],
115
+ "Resource": ["*"]
116
+ }
117
+ ]
118
+ }
119
+ ```
120
+
121
+ Optionally you can limit resource to certificate ARN(s).
106
122
 
@@ -1,6 +1,8 @@
1
1
  require 'acmesmith/account_key'
2
2
  require 'acmesmith/certificate'
3
3
 
4
+ require 'acmesmith/save_certificate_service'
5
+
4
6
  require 'acme-client'
5
7
 
6
8
  module Acmesmith
@@ -146,10 +148,17 @@ module Acmesmith
146
148
  certs
147
149
  end
148
150
 
149
- def save_certificate(common_name, version: 'current', mode: '0600', output:)
151
+ def save_certificate(common_name, version: 'current', mode: '0600', output:, type: 'fullchain')
150
152
  cert = storage.get_certificate(common_name, version: version)
151
153
  File.open(output, 'w', mode.to_i(8)) do |f|
152
- f.puts(cert.fullchain)
154
+ case type
155
+ when 'certificate'
156
+ f.puts cert.certificate.to_pem
157
+ when 'chain'
158
+ f.puts cert.chain
159
+ when 'fullchain'
160
+ f.puts cert.fullchain
161
+ end
153
162
  end
154
163
  end
155
164
 
@@ -178,6 +187,13 @@ module Acmesmith
178
187
  end
179
188
  end
180
189
 
190
+ def save(common_name, version: 'current', **kwargs)
191
+ cert = storage.get_certificate(common_name, version: version)
192
+ cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
193
+
194
+ SaveCertificateService.new(cert, **kwargs).perform!
195
+ end
196
+
181
197
  def autorenew(days: 7, common_names: nil)
182
198
  (common_names || storage.list_certificates).each do |cn|
183
199
  puts "=> #{cn}"
@@ -6,7 +6,7 @@ require 'acmesmith/client'
6
6
  module Acmesmith
7
7
  class Command < Thor
8
8
  class_option :config, default: './acmesmith.yml', aliases: %w(-c)
9
- class_option :passphrase_from_env, type: :boolean, aliases: %w(-E), default: false, desc: 'Read $ACMESMITH_ACCOUNT_KEY_PASSPHRASE and $ACMESMITH_CERTIFICATE_KEY_PASSPHRASE for passphrases'
9
+ class_option :passphrase_from_env, type: :boolean, aliases: %w(-E), default: nil, desc: 'Read $ACMESMITH_ACCOUNT_KEY_PASSPHRASE and $ACMESMITH_CERTIFICATE_KEY_PASSPHRASE for passphrases'
10
10
 
11
11
  desc "register CONTACT", "Create account key (contact e.g. mailto:xxx@example.org)"
12
12
  def register(contact)
@@ -57,10 +57,11 @@ module Acmesmith
57
57
 
58
58
  desc 'save-certificate COMMON_NAME', 'Save certificate to a file'
59
59
  method_option :version, type: :string, default: 'current'
60
+ method_option :type, type: :string, enum: %w(certificate chain fullchain), default: 'fullchain'
60
61
  method_option :output, type: :string, required: true, banner: 'PATH', desc: 'Path to output file'
61
62
  method_option :mode, type: :string, default: '0600', desc: 'Mode (permission) of the output file on create'
62
63
  def save_certificate(common_name)
63
- client.save_certificate(common_name, version: options[:version], mode: options[:mode], output: options[:output])
64
+ client.save_certificate(common_name, version: options[:version], mode: options[:mode], output: options[:output], type: options[:type])
64
65
  end
65
66
 
66
67
  desc "show-private-key COMMON_NAME", "show private key"
@@ -78,6 +79,32 @@ module Acmesmith
78
79
  client.save_private_key(common_name, version: options[:version], mode: options[:mode], output: options[:output])
79
80
  end
80
81
 
82
+ desc 'save COMMON_NAME', 'Save (or update) certificate and key files.'
83
+ method_option :version, type: :string, default: 'current'
84
+ method_option :key_mode, type: :string, default: '0600', desc: 'Mode (permission) of the key file on create'
85
+ method_option :certificate_mode, type: :string, default: '0644', desc: 'Mode (permission) of the certificate files on create'
86
+ method_option :version_file, type: :string, required: false, banner: 'PATH', desc: 'Path to save a certificate version for following run (optional)'
87
+ method_option :key_file, type: :string, required: false, banner: 'PATH', desc: 'Path to save a key'
88
+ method_option :fullchain_file, type: :string, required: false , banner: 'PATH', desc: 'Path to save a certficiate and its chain (concatenated)'
89
+ method_option :chain_file, type: :string, required: false , banner: 'PATH', desc: 'Path to save a certificate chain (root and intermediate CA)'
90
+ method_option :certificate_file, type: :string, required: false, banner: 'PATH', desc: 'Path to save a certficiate'
91
+ method_option :atomic, type: :boolean, default: true, desc: 'Enable atomic file update with rename(2)'
92
+ def save(common_name)
93
+ client.save(
94
+ common_name,
95
+ version: options[:version],
96
+ key_mode: options[:key_mode],
97
+ certificate_mode: options[:certificate_mode],
98
+ version_file: options[:version_file],
99
+ key_file: options[:key_file],
100
+ fullchain_file: options[:fullchain_file],
101
+ chain_file: options[:chain_file],
102
+ certificate_file: options[:certificate_file],
103
+ atomic: options[:atomic],
104
+ verbose: true,
105
+ )
106
+ end
107
+
81
108
  desc 'save-pkcs12 COMMON_NAME', 'Save ceriticate and private key to .p12 file'
82
109
  method_option :version, type: :string, default: 'current'
83
110
  method_option :output, type: :string, required: true, banner: 'PATH', desc: 'Path to output file'
@@ -0,0 +1,64 @@
1
+ module Acmesmith
2
+ class SaveCertificateService
3
+ def initialize(cert, key_mode: '0600', certificate_mode: '0644', version_file: nil, key_file: nil, fullchain_file: nil, chain_file: nil, certificate_file: nil, atomic: true, verbose: false)
4
+ @cert = cert
5
+ @key_mode = key_mode
6
+ @certificate_mode = certificate_mode
7
+ @version_file = version_file
8
+ @key_file = key_file
9
+ @fullchain_file = fullchain_file
10
+ @chain_file = chain_file
11
+ @certificate_file = certificate_file
12
+ @atomic = atomic
13
+ @verbose = verbose
14
+ end
15
+
16
+ attr_reader :cert
17
+ attr_reader :key_mode, :certificate_mode
18
+ attr_reader :version_file, :key_file, :fullchain_file, :chain_file, :certificate_file
19
+ def atomic?; !!@atomic; end
20
+
21
+ def perform!
22
+ if local_version == cert.version
23
+ return
24
+ end
25
+
26
+ log "Saving certificate CN=#{cert.common_name} (ver: #{cert.version})"
27
+
28
+ write_file(key_file, key_mode, cert.private_key)
29
+ write_file(certificate_file, certificate_mode, cert.certificate.to_pem)
30
+ write_file(chain_file, certificate_mode, cert.chain)
31
+ write_file(fullchain_file, certificate_mode, cert.fullchain)
32
+ write_file(version_file, certificate_mode, cert.version)
33
+ end
34
+
35
+ def local_version
36
+ @local_version ||= begin
37
+ if version_file && File.exist?(version_file)
38
+ File.read(version_file).chomp
39
+ else
40
+ nil
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def log(*args)
48
+ if @verbose
49
+ puts *args
50
+ end
51
+ end
52
+
53
+ def write_file(path, mode, body)
54
+ return unless path
55
+ realpath = atomic? ? "#{path}.new" : path
56
+ File.open(realpath, 'w', mode.to_i(8)) do |io|
57
+ io.puts body
58
+ end
59
+ if atomic?
60
+ File.rename realpath, path
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module Acmesmith
2
- VERSION = "0.10.0"
2
+ VERSION = "0.11.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acmesmith
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sorah (Shota Fukumori)
@@ -133,6 +133,7 @@ files:
133
133
  - lib/acmesmith/post_issuing_hooks/acm.rb
134
134
  - lib/acmesmith/post_issuing_hooks/base.rb
135
135
  - lib/acmesmith/post_issuing_hooks/shell.rb
136
+ - lib/acmesmith/save_certificate_service.rb
136
137
  - lib/acmesmith/storages.rb
137
138
  - lib/acmesmith/storages/base.rb
138
139
  - lib/acmesmith/storages/filesystem.rb