puma-acme 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +28 -12
- data/LICENSE.txt +1 -1
- data/README.md +33 -40
- data/lib/puma/acme/plugin.rb +16 -16
- data/lib/puma/acme/version.rb +1 -1
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb2015bc7d0607d5b5c295e0dcd66db310fe8cbeedc8eaba728cbe8a22531580
|
4
|
+
data.tar.gz: 9b68efe0b7fcc76d5a990cbab2c01f40b842fde9ce99dc05c98fd9b02fb88a44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f21ec6c93e596e7383e3f089ed49e18266ae512c90b4915bc8036c5ab36c560ff56ce1090b56a87a57038f947a950468a056be5beb715176a553d386bf10054
|
7
|
+
data.tar.gz: 1cab79a891cf25c1cfad5bc332f0f613ea1154e7e025bac94b415156d26b733a7f76d4df343a7367f39f001405b9e25f0a06d8ebcd6fc338848b61bea768072f
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,50 +1,65 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
puma-acme (0.1.
|
4
|
+
puma-acme (0.1.2.pre)
|
5
5
|
acme-client (~> 2.0.13)
|
6
6
|
pstore (~> 0.1)
|
7
|
-
puma (~> 6
|
7
|
+
puma (~> 5.6)
|
8
8
|
sinatra (~> 3.1)
|
9
9
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
acme-client (2.0.
|
13
|
+
acme-client (2.0.16)
|
14
14
|
faraday (>= 1.0, < 3.0.0)
|
15
15
|
faraday-retry (>= 1.0, < 3.0.0)
|
16
|
+
addressable (2.8.6)
|
17
|
+
public_suffix (>= 2.0.2, < 6.0)
|
16
18
|
base64 (0.2.0)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
faraday-net_http (3.0
|
19
|
+
crack (0.4.5)
|
20
|
+
rexml
|
21
|
+
faraday (2.9.0)
|
22
|
+
faraday-net_http (>= 2.0, < 3.2)
|
23
|
+
faraday-net_http (3.1.0)
|
24
|
+
net-http
|
22
25
|
faraday-retry (2.2.0)
|
23
26
|
faraday (~> 2.0)
|
27
|
+
hashdiff (1.1.0)
|
24
28
|
http.rb (0.12.0)
|
25
29
|
minitest (5.20.0)
|
26
30
|
minitest-mock_expectations (1.2.0)
|
27
31
|
mustermann (3.0.0)
|
28
32
|
ruby2_keywords (~> 0.0.1)
|
33
|
+
net-http (0.4.1)
|
34
|
+
uri
|
29
35
|
nio4r (2.7.0)
|
30
36
|
pstore (0.1.3)
|
31
|
-
|
37
|
+
public_suffix (5.0.4)
|
38
|
+
puma (5.6.8)
|
32
39
|
nio4r (~> 2.0)
|
33
40
|
rack (2.2.8)
|
34
|
-
rack-protection (3.
|
41
|
+
rack-protection (3.2.0)
|
42
|
+
base64 (>= 0.1.0)
|
35
43
|
rack (~> 2.2, >= 2.2.4)
|
36
44
|
rake (13.1.0)
|
45
|
+
rexml (3.2.6)
|
37
46
|
ruby2_keywords (0.0.5)
|
38
|
-
sinatra (3.
|
47
|
+
sinatra (3.2.0)
|
39
48
|
mustermann (~> 3.0)
|
40
49
|
rack (~> 2.2, >= 2.2.4)
|
41
|
-
rack-protection (= 3.
|
50
|
+
rack-protection (= 3.2.0)
|
42
51
|
tilt (~> 2.0)
|
43
52
|
tilt (2.3.0)
|
53
|
+
uri (0.13.0)
|
44
54
|
vcr (6.2.0)
|
55
|
+
webmock (3.19.1)
|
56
|
+
addressable (>= 2.8.0)
|
57
|
+
crack (>= 0.3.2)
|
58
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
45
59
|
|
46
60
|
PLATFORMS
|
47
61
|
arm64-darwin-23
|
62
|
+
x86_64-linux
|
48
63
|
|
49
64
|
DEPENDENCIES
|
50
65
|
http.rb (~> 0.12)
|
@@ -53,6 +68,7 @@ DEPENDENCIES
|
|
53
68
|
puma-acme!
|
54
69
|
rake (~> 13.0)
|
55
70
|
vcr (~> 6.1)
|
71
|
+
webmock (~> 3.19)
|
56
72
|
|
57
73
|
BUNDLED WITH
|
58
74
|
2.3.26
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c)
|
3
|
+
Copyright (c) 2024 Anchor Security, Inc.
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,28 +1,24 @@
|
|
1
1
|
# puma-acme
|
2
2
|
|
3
|
-
A [Puma](https://puma.io/) plugin for
|
4
|
-
[ACME](https://www.rfc-editor.org/rfc/rfc8555.html).
|
3
|
+
A [Puma](https://puma.io/) plugin for adding HTTPS support to a Puma server
|
4
|
+
with SSL certs via [ACME](https://www.rfc-editor.org/rfc/rfc8555.html).
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
provisioning. A rack handler for
|
6
|
+
To use, configure the server name(s), accept the TOS, and add a bind directive.
|
7
|
+
The plugin will handle ACME account creation, order handling, challenge
|
8
|
+
responses, and certificate provisioning. A
|
10
9
|
[HTTP-01](https://letsencrypt.org/docs/challenge-types/#http-01-challenge)
|
11
|
-
|
12
|
-
challenges.
|
10
|
+
rack handler also allows non-SSL addresses to automatically answer challenges.
|
13
11
|
|
14
|
-
On first boot, the server will
|
15
|
-
|
16
|
-
|
17
|
-
and binds to the SSL port.
|
12
|
+
On first boot, the server will start without SSL and run the ACME workflow in a
|
13
|
+
background thread. When the workflow finishes, the server will gracefully
|
14
|
+
restart and bind to the SSL port.
|
18
15
|
|
19
16
|
If the configured cache contains an unexpired certificate that matches the
|
20
17
|
algorithm and server name(s), it will use the cert to bind a listener at server
|
21
18
|
boot.
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
directive for details.
|
20
|
+
Setting a renewal interval based on the remaining time as a duration or a
|
21
|
+
fraction will enable automatic renewal. See `acme_renew_at` for details.
|
26
22
|
|
27
23
|
Supports standalone and cluster mode, along with graceful & rolling restarts.
|
28
24
|
|
@@ -45,7 +41,7 @@ config.bind 'tcp://0.0.0.0:80'
|
|
45
41
|
|
46
42
|
plugin :acme
|
47
43
|
|
48
|
-
acme_server_name 'puma-acme.example.org'
|
44
|
+
acme_server_name 'puma-acme.example.org'
|
49
45
|
acme_tos_agreed true
|
50
46
|
|
51
47
|
config.bind 'acme://0.0.0.0:443'
|
@@ -60,22 +56,21 @@ advanced:
|
|
60
56
|
# Recommended for account recovery and revocation.
|
61
57
|
acme_contact 'mailto:acme-user@exmaple.org'
|
62
58
|
|
63
|
-
# Specify
|
59
|
+
# Specify server names (SAN extension).
|
64
60
|
acme_server_names 'puma-acme.example.org', 'www.puma-acme.example.org'
|
65
61
|
|
66
62
|
# Enable automatic renewal based on an amount of time or fraction of life
|
67
|
-
# remaining. For an amount of time, use
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
# certificate lifetime.
|
63
|
+
# remaining. For an amount of time, use Integer seconds, for example the value
|
64
|
+
# 2592000 will set renewal to 30 days before certificate expiry. For a fraction
|
65
|
+
# of life remaining, use a Float between 0 and 1, for example the value 0.75
|
66
|
+
# will set renewal at 75% of the way through the certificate lifetime.
|
72
67
|
acme_renew_at 0.75
|
73
68
|
|
74
|
-
# URL of ACME server's directory URL,
|
69
|
+
# URL of ACME server's directory URL, defaults to LetsEncrypt.
|
75
70
|
acme_directory 'https://acme.example.org/directory'
|
76
71
|
|
77
|
-
# Accept the Terms of Service (TOS) of an ACME server
|
78
|
-
#
|
72
|
+
# Accept the Terms of Service (TOS) of an ACME server with the server's
|
73
|
+
# directory URL as a string or true to accept any server's TOS.
|
79
74
|
acme_tos_agreed 'https://acme.example.org/directory'
|
80
75
|
|
81
76
|
# External Account Binding (EAB) token KID & secret HMAC key for the ACME
|
@@ -83,29 +78,27 @@ acme_tos_agreed 'https://acme.example.org/directory'
|
|
83
78
|
acme_eab_kid ENV['ACME_KID']
|
84
79
|
acme_eab_hmac_key ENV['ACME_HMAC_KEY']
|
85
80
|
|
86
|
-
# Encryption key algorithm, :ecdsa
|
81
|
+
# Encryption key algorithm, either :ecdsa or :rsa, defaults to :ecdsa.
|
87
82
|
acme_algorithm :ecdsa
|
88
83
|
|
89
|
-
# Provision mode, :background
|
90
|
-
#
|
91
|
-
#
|
92
|
-
# Foreground mode blocks all binding listeners until a certificate
|
93
|
-
#
|
94
|
-
acme_mode :background
|
84
|
+
# Provision mode, either :background or :foreground, defaults to :background.
|
85
|
+
# Background mode provisions certificates in a background thread without
|
86
|
+
# blocking binding or request serving for non-acme listeners.
|
87
|
+
# Foreground mode blocks all binding listeners until a certificate
|
88
|
+
# provisions, compatible only with zero-challenge ACME flow.
|
89
|
+
acme_mode :background
|
95
90
|
|
96
|
-
# Store account, order, and
|
97
|
-
#
|
91
|
+
# ActiveSupport::Cache::Store compatible cache to store account, order, and
|
92
|
+
# certificate data. Defaults to a local filesystem based cache.
|
98
93
|
acme_cache Rails.cache
|
99
94
|
|
100
|
-
# Path to the cache directory for the default cache, 'tmp/acme'
|
95
|
+
# Path to the cache directory for the default cache, defaults to 'tmp/acme'.
|
101
96
|
acme_cache_dir 'tmp/acme'
|
102
97
|
|
103
|
-
# Time to wait in seconds before
|
104
|
-
# is the default.
|
98
|
+
# Time to wait in seconds before rechecking order status, defaults to 1 second.
|
105
99
|
acme_poll_interval 1
|
106
100
|
|
107
|
-
# Time to wait in seconds before checking for
|
108
|
-
# hour.
|
101
|
+
# Time to wait in seconds before checking for renewal, defaults to 1 hour.
|
109
102
|
acme_renew_interval 60 * 60
|
110
103
|
```
|
111
104
|
|
@@ -117,5 +110,5 @@ acme_renew_interval 60 * 60
|
|
117
110
|
|
118
111
|
## License
|
119
112
|
|
120
|
-
|
113
|
+
puma-acme is available as open source under the terms of the [MIT
|
121
114
|
License](http://opensource.org/licenses/MIT).
|
data/lib/puma/acme/plugin.rb
CHANGED
@@ -41,11 +41,11 @@ module Puma
|
|
41
41
|
manager: @manager
|
42
42
|
)
|
43
43
|
|
44
|
-
@
|
44
|
+
@logger = launcher.respond_to?(:log_writer) ? launcher.log_writer : launcher.events
|
45
45
|
|
46
46
|
cert = @manager.cert!(identifiers: identifiers, algorithm: algorithm)
|
47
47
|
if cert.usable?
|
48
|
-
@
|
48
|
+
@logger.debug 'Acme: cert already provisioned'
|
49
49
|
|
50
50
|
bind_to(launcher, cert)
|
51
51
|
|
@@ -57,17 +57,17 @@ module Puma
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
elsif mode == :background
|
60
|
-
@
|
60
|
+
@logger.log 'Puma background provisioning cert via puma-acme plugin...'
|
61
61
|
|
62
62
|
in_background do
|
63
63
|
provision(cert, poll_interval: poll_interval)
|
64
64
|
|
65
|
-
@
|
65
|
+
@logger.log 'Puma restarting after provisioning cert via puma-acme plugin...'
|
66
66
|
|
67
67
|
launcher.restart
|
68
68
|
end
|
69
69
|
elsif mode == :foreground
|
70
|
-
@
|
70
|
+
@logger.log 'Puma foreground provisioning cert via puma-acme plugin...'
|
71
71
|
|
72
72
|
provision(cert, poll_interval: poll_interval)
|
73
73
|
bind_to(launcher, cert)
|
@@ -92,7 +92,7 @@ module Puma
|
|
92
92
|
'cert_pem' => cert.cert_pem
|
93
93
|
}
|
94
94
|
|
95
|
-
ctx = MiniSSL::ContextBuilder.new(params, @
|
95
|
+
ctx = MiniSSL::ContextBuilder.new(params, @logger).context
|
96
96
|
|
97
97
|
launcher.binder.before_parse_hook do
|
98
98
|
@acme_binds.each do |str|
|
@@ -100,16 +100,16 @@ module Puma
|
|
100
100
|
|
101
101
|
if (fd = launcher.binder.inherited_fds.delete(str))
|
102
102
|
io = launcher.binder.inherit_ssl_listener(fd, ctx)
|
103
|
-
@
|
103
|
+
@logger.log "* Inherited #{str}"
|
104
104
|
elsif (fd = launcher.binder.activated_sockets.delete([:acme, uri.host, uri.port]))
|
105
105
|
io = launcher.binder.inherit_ssl_listener(fd, ctx)
|
106
|
-
@
|
106
|
+
@logger.log "* Activated #{str}"
|
107
107
|
else
|
108
108
|
io = launcher.binder.add_ssl_listener(uri.host, uri.port, ctx)
|
109
109
|
end
|
110
110
|
|
111
111
|
cert.identifiers.each do |identifier|
|
112
|
-
@
|
112
|
+
@logger.log "* Listening on ssl://#{uri.host}:#{uri.port} for https://#{identifier.value}:#{uri.port} (puma-acme)"
|
113
113
|
end
|
114
114
|
|
115
115
|
launcher.binder.listeners << [str, io]
|
@@ -119,13 +119,13 @@ module Puma
|
|
119
119
|
|
120
120
|
def provision(cert, poll_interval:)
|
121
121
|
unless @manager.account
|
122
|
-
@
|
122
|
+
@logger.debug 'Acme: creating account'
|
123
123
|
|
124
124
|
@manager.account!
|
125
125
|
end
|
126
126
|
|
127
127
|
if cert.order.nil?
|
128
|
-
@
|
128
|
+
@logger.debug 'Acme: creating order'
|
129
129
|
@manager.order!(cert)
|
130
130
|
else
|
131
131
|
@manager.reload!(cert)
|
@@ -134,23 +134,23 @@ module Puma
|
|
134
134
|
loop do
|
135
135
|
case cert.order.status.to_sym
|
136
136
|
when :valid
|
137
|
-
@
|
137
|
+
@logger.debug 'Acme: downloading cert'
|
138
138
|
|
139
139
|
@manager.download!(cert)
|
140
140
|
|
141
141
|
return
|
142
142
|
when :processing, :pending
|
143
|
-
@
|
143
|
+
@logger.debug "Acme: waiting on #{cert.order.status} order"
|
144
144
|
|
145
145
|
sleep poll_interval
|
146
146
|
|
147
147
|
@manager.reload!(cert)
|
148
148
|
when :ready
|
149
|
-
@
|
149
|
+
@logger.debug 'Acme: finalizing ready order'
|
150
150
|
|
151
151
|
@manager.finalize!(cert)
|
152
152
|
when :invalid
|
153
|
-
@
|
153
|
+
@logger.debug 'Acme: invalid order, re-ordering'
|
154
154
|
|
155
155
|
@manager.order!(cert)
|
156
156
|
end
|
@@ -171,7 +171,7 @@ module Puma
|
|
171
171
|
|
172
172
|
next unless cert.renewable?(renew_at)
|
173
173
|
|
174
|
-
@
|
174
|
+
@logger.debug 'Acme: creating renewal order'
|
175
175
|
|
176
176
|
@manager.order!(cert)
|
177
177
|
|
data/lib/puma/acme/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma-acme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anchor Security, Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acme-client
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '6
|
47
|
+
version: '5.6'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '6
|
54
|
+
version: '5.6'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: sinatra
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '6.1'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: webmock
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '3.19'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '3.19'
|
139
153
|
description: A Puma webserver plugin for automatic access to certificates from Let's
|
140
154
|
Encrypt and any other ACME-based CA.
|
141
155
|
email:
|
@@ -183,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
197
|
- !ruby/object:Gem::Version
|
184
198
|
version: '0'
|
185
199
|
requirements: []
|
186
|
-
rubygems_version: 3.
|
200
|
+
rubygems_version: 3.4.10
|
187
201
|
signing_key:
|
188
202
|
specification_version: 4
|
189
203
|
summary: Puma plugin for ACME.
|