acmesmith 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +6 -0
- data/.github/workflows/build.yml +123 -0
- data/.gitignore +0 -1
- data/CHANGELOG.md +35 -0
- data/Dockerfile +29 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +73 -0
- data/LICENSE.txt +1 -1
- data/README.md +71 -93
- data/acmesmith.gemspec +1 -1
- data/config.sample.yml +41 -2
- data/docs/challenge_responders/route53.md +28 -0
- data/docs/examples/UpdateWindowsCertificate.ps1 +58 -0
- data/docs/post_issuing_hooks/acm.md +16 -0
- data/docs/post_issuing_hooks/shell.md +17 -0
- data/docs/storages/filesystem.md +11 -0
- data/docs/storages/s3.md +32 -0
- data/lib/acmesmith/account_key.rb +12 -1
- data/lib/acmesmith/authorization_service.rb +175 -0
- data/lib/acmesmith/certificate.rb +42 -11
- data/lib/acmesmith/challenge_responder_filter.rb +23 -0
- data/lib/acmesmith/challenge_responders/base.rb +11 -2
- data/lib/acmesmith/challenge_responders/pebble_challtestsrv_dns.rb +53 -0
- data/lib/acmesmith/challenge_responders/route53.rb +13 -2
- data/lib/acmesmith/client.rb +13 -131
- data/lib/acmesmith/config.rb +23 -2
- data/lib/acmesmith/ordering_service.rb +104 -0
- data/lib/acmesmith/storages/base.rb +15 -0
- data/lib/acmesmith/storages/s3.rb +3 -3
- data/lib/acmesmith/version.rb +1 -1
- metadata +19 -6
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'acmesmith/authorization_service'
|
2
|
+
require 'acmesmith/certificate'
|
3
|
+
|
4
|
+
module Acmesmith
|
5
|
+
class OrderingService
|
6
|
+
class NotCompleted < StandardError; end
|
7
|
+
|
8
|
+
# @param acme [Acme::Client] ACME client
|
9
|
+
# @param identifiers [Array<String>] Array of domain names for a ordering certificate. The first item will be a common name.
|
10
|
+
# @param challenge_responder_rules [Array<Acmesmith::Config::ChallengeResponderRule>] responders
|
11
|
+
# @param not_before [Time]
|
12
|
+
# @param not_after [Time]
|
13
|
+
def initialize(acme:, identifiers:, challenge_responder_rules:, not_before: nil, not_after: nil)
|
14
|
+
@acme = acme
|
15
|
+
@identifiers = identifiers
|
16
|
+
@challenge_responder_rules = challenge_responder_rules
|
17
|
+
@not_before = not_before
|
18
|
+
@not_after = not_after
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :acme, :identifiers, :challenge_responder_rules, :not_before, :not_after
|
22
|
+
|
23
|
+
def perform!
|
24
|
+
puts "=> Ordering a certificate for the following identifiers:"
|
25
|
+
puts
|
26
|
+
puts " * CN: #{common_name}"
|
27
|
+
sans.each do |san|
|
28
|
+
puts " * SAN: #{san}"
|
29
|
+
end
|
30
|
+
|
31
|
+
puts
|
32
|
+
puts "=> Placing an order"
|
33
|
+
@order = acme.new_order(identifiers: identifiers, not_before: not_before, not_after: not_after)
|
34
|
+
puts " * URL: #{order.url}"
|
35
|
+
|
36
|
+
ensure_authorization()
|
37
|
+
|
38
|
+
finalize_order()
|
39
|
+
wait_order_for_complete()
|
40
|
+
|
41
|
+
@certificate = Certificate.by_issuance(order.certificate, csr)
|
42
|
+
|
43
|
+
puts
|
44
|
+
puts "=> Certificate issued"
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def ensure_authorization
|
49
|
+
return if order.authorizations.empty? || order.status == 'ready'
|
50
|
+
puts "=> Looking for required domain authorizations"
|
51
|
+
puts
|
52
|
+
order.authorizations.map(&:domain).each do |domain|
|
53
|
+
puts " * #{domain}"
|
54
|
+
end
|
55
|
+
puts
|
56
|
+
|
57
|
+
AuthorizationService.new(challenge_responder_rules, order.authorizations).perform!
|
58
|
+
end
|
59
|
+
|
60
|
+
def finalize_order
|
61
|
+
puts
|
62
|
+
puts "=> Finalizing the order"
|
63
|
+
puts
|
64
|
+
puts csr.csr.to_pem
|
65
|
+
puts
|
66
|
+
|
67
|
+
print " * Requesting..."
|
68
|
+
order.finalize(csr: csr)
|
69
|
+
puts" [ ok ]"
|
70
|
+
end
|
71
|
+
|
72
|
+
def wait_order_for_complete
|
73
|
+
while %w(ready processing).include?(order.status)
|
74
|
+
order.reload()
|
75
|
+
puts " * Waiting for complete: status=#{order.status}"
|
76
|
+
sleep 2
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def certificate
|
81
|
+
@certificate or raise NotCompleted, "not completed yet"
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return Acme::Client::Resources::Order[]
|
85
|
+
def order
|
86
|
+
@order or raise "BUG: order not yet generated"
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String]
|
90
|
+
def common_name
|
91
|
+
identifiers.first
|
92
|
+
end
|
93
|
+
|
94
|
+
# @return [Array<String>]
|
95
|
+
def sans
|
96
|
+
identifiers[1..-1]
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [Acme::Client::CertificateRequest]
|
100
|
+
def csr
|
101
|
+
@csr ||= Acme::Client::CertificateRequest.new(subject: { common_name: common_name }, names: sans)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -7,30 +7,45 @@ module Acmesmith
|
|
7
7
|
def initialize()
|
8
8
|
end
|
9
9
|
|
10
|
+
# @return [Acmesmith::AccountKey]
|
10
11
|
def get_account_key
|
11
12
|
raise NotImplementedError
|
12
13
|
end
|
13
14
|
|
15
|
+
# @param key [Acmesmith::AccountKey]
|
16
|
+
# @param passphrase [String, nil]
|
14
17
|
def put_account_key(key, passphrase = nil)
|
15
18
|
raise NotImplementedError
|
16
19
|
end
|
17
20
|
|
21
|
+
# @param cert [Acmesmith::Certificate]
|
22
|
+
# @param passphrase [String, nil]
|
23
|
+
# @param update_current [true, false]
|
18
24
|
def put_certificate(cert, passphrase = nil, update_current: true)
|
19
25
|
raise NotImplementedError
|
20
26
|
end
|
21
27
|
|
28
|
+
# @param common_name [String]
|
29
|
+
# @param version [String, nil]
|
30
|
+
# @return [Acmesmith::Certificate]
|
22
31
|
def get_certificate(common_name, version: 'current')
|
23
32
|
raise NotImplementedError
|
24
33
|
end
|
25
34
|
|
35
|
+
# @param common_name [String]
|
36
|
+
# @return [String] array of common_names
|
26
37
|
def list_certificates
|
27
38
|
raise NotImplementedError
|
28
39
|
end
|
29
40
|
|
41
|
+
# @param common_name [String]
|
42
|
+
# @return [String] array of versions
|
30
43
|
def list_certificate_versions(common_name)
|
31
44
|
raise NotImplementedError
|
32
45
|
end
|
33
46
|
|
47
|
+
# @param common_name [String]
|
48
|
+
# @return [String] current version
|
34
49
|
def get_current_certificate_version(common_name)
|
35
50
|
raise NotImplementedError
|
36
51
|
end
|
@@ -23,7 +23,7 @@ module Acmesmith
|
|
23
23
|
@kms_key_id_account = kms_key_id_account
|
24
24
|
@kms_key_id_certificate_key = kms_key_id_certificate_key
|
25
25
|
|
26
|
-
@s3 = Aws::S3::Client.new({region: region
|
26
|
+
@s3 = Aws::S3::Client.new({region: region}.tap do |opt|
|
27
27
|
opt[:credentials] = Aws::Credentials.new(aws_access_key['access_key_id'], aws_access_key['secret_access_key'], aws_access_key['session_token']) if aws_access_key
|
28
28
|
end)
|
29
29
|
end
|
@@ -85,10 +85,10 @@ module Acmesmith
|
|
85
85
|
put.call certificate_key(cert.common_name, cert.version), "#{h[:certificate].rstrip}\n", false
|
86
86
|
put.call chain_key(cert.common_name, cert.version), "#{h[:chain].rstrip}\n", false
|
87
87
|
put.call fullchain_key(cert.common_name, cert.version), "#{h[:fullchain].rstrip}\n", false
|
88
|
-
put.call private_key_key(cert.common_name, cert.version), "#{h[:private_key].rstrip}\n",
|
88
|
+
put.call private_key_key(cert.common_name, cert.version), "#{h[:private_key].rstrip}\n", use_kms
|
89
89
|
|
90
90
|
if generate_pkcs12?(cert)
|
91
|
-
put.call pkcs12_key(cert.common_name, cert.version), "#{cert.pkcs12(@pkcs12_passphrase).to_der}\n",
|
91
|
+
put.call pkcs12_key(cert.common_name, cert.version), "#{cert.pkcs12(@pkcs12_passphrase).to_der}\n", use_kms, 'application/x-pkcs12'
|
92
92
|
end
|
93
93
|
|
94
94
|
if update_current
|
data/lib/acmesmith/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acmesmith
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Sorah Fukumori
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acme-client
|
@@ -127,7 +127,7 @@ description: 'Acmesmith is an [ACME (Automatic Certificate Management Environmen
|
|
127
127
|
certificate and keys on cloud services (e.g. AWS S3) securely, then allow to deploy
|
128
128
|
issued certificates onto your servers smoothly. This works well on [Let''s encrypt](https://letsencrypt.org).
|
129
129
|
|
130
|
-
'
|
130
|
+
'
|
131
131
|
email:
|
132
132
|
- her@sorah.jp
|
133
133
|
executables:
|
@@ -135,28 +135,42 @@ executables:
|
|
135
135
|
extensions: []
|
136
136
|
extra_rdoc_files: []
|
137
137
|
files:
|
138
|
+
- ".dockerignore"
|
139
|
+
- ".github/workflows/build.yml"
|
138
140
|
- ".gitignore"
|
139
141
|
- ".rspec"
|
140
142
|
- ".travis.yml"
|
141
143
|
- CHANGELOG.md
|
144
|
+
- Dockerfile
|
142
145
|
- Gemfile
|
146
|
+
- Gemfile.lock
|
143
147
|
- LICENSE.txt
|
144
148
|
- README.md
|
145
149
|
- Rakefile
|
146
150
|
- acmesmith.gemspec
|
147
151
|
- bin/acmesmith
|
148
152
|
- config.sample.yml
|
153
|
+
- docs/challenge_responders/route53.md
|
154
|
+
- docs/examples/UpdateWindowsCertificate.ps1
|
155
|
+
- docs/post_issuing_hooks/acm.md
|
156
|
+
- docs/post_issuing_hooks/shell.md
|
157
|
+
- docs/storages/filesystem.md
|
158
|
+
- docs/storages/s3.md
|
149
159
|
- docs/vendor/aws.md
|
150
160
|
- lib/acmesmith.rb
|
151
161
|
- lib/acmesmith/account_key.rb
|
162
|
+
- lib/acmesmith/authorization_service.rb
|
152
163
|
- lib/acmesmith/certificate.rb
|
164
|
+
- lib/acmesmith/challenge_responder_filter.rb
|
153
165
|
- lib/acmesmith/challenge_responders.rb
|
154
166
|
- lib/acmesmith/challenge_responders/base.rb
|
155
167
|
- lib/acmesmith/challenge_responders/manual_dns.rb
|
168
|
+
- lib/acmesmith/challenge_responders/pebble_challtestsrv_dns.rb
|
156
169
|
- lib/acmesmith/challenge_responders/route53.rb
|
157
170
|
- lib/acmesmith/client.rb
|
158
171
|
- lib/acmesmith/command.rb
|
159
172
|
- lib/acmesmith/config.rb
|
173
|
+
- lib/acmesmith/ordering_service.rb
|
160
174
|
- lib/acmesmith/post_issueing_hooks.rb
|
161
175
|
- lib/acmesmith/post_issueing_hooks/base.rb
|
162
176
|
- lib/acmesmith/post_issuing_hooks.rb
|
@@ -191,8 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
205
|
- !ruby/object:Gem::Version
|
192
206
|
version: '0'
|
193
207
|
requirements: []
|
194
|
-
|
195
|
-
rubygems_version: 2.7.7
|
208
|
+
rubygems_version: 3.1.2
|
196
209
|
signing_key:
|
197
210
|
specification_version: 4
|
198
211
|
summary: ACME client (Let's encrypt client) to manage certificate in multi server
|