Skip to content

Commit ebfa5d3

Browse files
committed
Expose the redis adapter's redis connection in the allow_domain callback
The auto_ssl instance is now passed as the second argument to the `allow_domain` callback. If using the Redis storage adapter, then now the Redis connection can be accessed by `auto_ssl.storage.adapter:get_connection()`. This allows for more easily accessing the same redis connection in this callback function (or anywhere else the auto_ssl instance is available). This rolls back the change in 9703684 to rename the storage adapter instance inside the storage library, so it continues to just be `adapter` (instead of `storage_adapter`). This makes this access a bit easier and also keeps backwards compatibility with the previous release. See: #38
1 parent 4aed490 commit ebfa5d3

File tree

13 files changed

+244
-75
lines changed

13 files changed

+244
-75
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Added
66
- Allow for the Redis `db` number to be configured. Thanks to [@RainFlying](https://github.com/RainFlying). ([#103](https://github.com/GUI/lua-resty-auto-ssl/pull/103))
7+
- Expose the storage adapter instance in the `allow_domain` callback so the Redis connection can be reused. ([#38](https://github.com/GUI/lua-resty-auto-ssl/issues/38))
78
- Add `generate_certs` option to allow for disabling SSL certification generation within specific server blocks. Thanks to [@mklauber](https://github.com/mklauber). ([#91](https://github.com/GUI/lua-resty-auto-ssl/issues/91), [#92](https://github.com/GUI/lua-resty-auto-ssl/pull/92))
89
- Add `json_adapter` option for choosing a different JSON encoder/decoder library. Thanks to [@meyskens](https://github.com/meyskens). ([#85](https://github.com/GUI/lua-resty-auto-ssl/pull/85), [#84](https://github.com/GUI/lua-resty-auto-ssl/issues/84))
910

@@ -12,6 +13,9 @@
1213
- Only call the `allow_domain` callback if a certificate is not present in shared memory. This may improve efficiency in cases where the `allow_domain` callback is more costly or takes longer. Thanks to [@gohai](https://github.com/gohai). ([#107](https://github.com/GUI/lua-resty-auto-ssl/pull/107))
1314
- Upgrade dehydrated to latest version from master to fix redirect issues on the Let's Encrypt staging server.
1415

16+
### Deprecated
17+
- If accessing the storage object off of the auto-ssl instance, use `auto_ssl.storage` instead of `auto_ssl:get("storage")`.
18+
1519
### Fixed
1620
- Fix renewals when using the file adapter and too many certificate files were present for shell globbing ([#109](https://github.com/GUI/lua-resty-auto-ssl/issues/109))
1721

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,18 @@ http {
138138
Additional configuration options can be set on the `auto_ssl` instance that is created:
139139

140140
### `allow_domain`
141-
*Default:* `function(domain) return false end`
141+
*Default:* `function(domain, auto_ssl) return false end`
142142

143143
A function that determines whether the incoming domain should automatically issue a new SSL certificate.
144144

145145
By default, resty-auto-ssl will not perform any SSL registrations until you define the `allow_domain` function. You may return `true` to handle all possible domains, but be aware that bogus SNI hostnames can then be used to trigger an indefinite number of SSL registration attempts (which will be rejected). A better approach may be to whitelist the allowed domains in some way.
146146

147+
When using the Redis storage adapter, you can access the current Redis connection inside the `allow_domain` callback by accessing `auto_ssl.storage.adapter:get_connection()`.
148+
147149
*Example:*
148150

149151
```lua
150-
auto_ssl:set("allow_domain", function(domain)
152+
auto_ssl:set("allow_domain", function(domain, auto_ssl)
151153
return ngx.re.match(domain, "^(example.com|example.net)$", "ijo")
152154
end)
153155
```

lib/resty/auto-ssl.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,25 @@ function _M.new(options)
5252
end
5353

5454
function _M.set(self, key, value)
55+
if key == "storage" then
56+
ngx.log(ngx.ERR, "auto-ssl: DEPRECATED: Don't use auto_ssl:set() for the 'storage' instance. Set directly with auto_ssl.storage.")
57+
self.storage = value
58+
return
59+
end
60+
5561
self.options[key] = value
5662
end
5763

5864
function _M.get(self, key)
65+
if key == "storage" then
66+
ngx.log(ngx.ERR, "auto-ssl: DEPRECATED: Don't use auto_ssl:get() for the 'storage' instance. Get directly with auto_ssl.storage.")
67+
return self.storage
68+
end
69+
5970
return self.options[key]
6071
end
6172

62-
function _M.allow_domain(domain) -- luacheck: ignore
73+
function _M.allow_domain(domain, auto_ssl) -- luacheck: ignore
6374
return false
6475
end
6576

lib/resty/auto-ssl/init_master.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ local function setup_storage(auto_ssl_instance)
9191

9292
local storage = require "resty.auto-ssl.storage"
9393
local storage_instance = storage.new({
94-
storage_adapter = storage_adapter_instance,
94+
adapter = storage_adapter_instance,
9595
json_adapter = json_adapter_instance,
9696
})
97-
auto_ssl_instance:set("storage", storage_instance)
97+
auto_ssl_instance.storage = storage_instance
9898
end
9999

100100
return function(auto_ssl_instance)

lib/resty/auto-ssl/init_worker.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ return function(auto_ssl_instance)
2525
-- background process, which would be nice.
2626
start_sockproc()
2727

28-
local storage = auto_ssl_instance:get("storage")
29-
local storage_adapter = storage.storage_adapter
28+
local storage = auto_ssl_instance.storage
29+
local storage_adapter = storage.adapter
3030
if storage_adapter.setup_worker then
3131
storage_adapter:setup_worker()
3232
end

lib/resty/auto-ssl/jobs/renewal.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ end
136136

137137
local function renew_all_domains(auto_ssl_instance)
138138
-- Loop through all known domains and check to see if they should be renewed.
139-
local storage = auto_ssl_instance:get("storage")
139+
local storage = auto_ssl_instance.storage
140140
local domains, domains_err = storage:all_cert_domains()
141141
if domains_err then
142142
ngx.log(ngx.ERR, "auto-ssl: failed to fetch all certificate domains: ", domains_err)

lib/resty/auto-ssl/servers/challenge.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ return function(auto_ssl_instance)
1515

1616
-- Return the challenge value for this token if it's found.
1717
local domain = ngx.var.host
18-
local storage = auto_ssl_instance:get("storage")
18+
local storage = auto_ssl_instance.storage
1919
local value = storage:get_challenge(domain, token_filename)
2020
if value then
2121
ngx.say(value)

lib/resty/auto-ssl/servers/hook.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ return function(auto_ssl_instance)
1717
end
1818

1919
local path = ngx.var.request_uri
20-
local storage = auto_ssl_instance:get("storage")
20+
local storage = auto_ssl_instance.storage
2121
if path == "/deploy-challenge" then
2222
assert(params["domain"])
2323
assert(params["token_filename"])

lib/resty/auto-ssl/ssl_certificate.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,13 @@ local function get_cert_der(auto_ssl_instance, domain, ssl_options)
122122
-- We may want to consider caching the results of allow_domain lookups
123123
-- (including negative caching or disallowed domains).
124124
local allow_domain = auto_ssl_instance:get("allow_domain")
125-
if not allow_domain(domain) then
125+
if not allow_domain(domain, auto_ssl_instance) then
126126
return nil, "domain not allowed"
127127
end
128128

129129
-- Next, look for the certificate in permanent storage (which can be shared
130130
-- across servers depending on the storage).
131-
local storage = auto_ssl_instance:get("storage")
131+
local storage = auto_ssl_instance.storage
132132
local cert, get_cert_err = storage:get_cert(domain)
133133
if get_cert_err then
134134
ngx.log(ngx.ERR, "auto-ssl: error fetching certificate from storage for ", domain, ": ", get_cert_err)

lib/resty/auto-ssl/ssl_providers/lets_encrypt.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function _M.issue_cert(auto_ssl_instance, domain)
4646

4747
-- The result of running that command should result in the certs being
4848
-- populated in our storage (due to the deploy_cert hook triggering).
49-
local storage = auto_ssl_instance:get("storage")
49+
local storage = auto_ssl_instance.storage
5050
local cert, get_cert_err = storage:get_cert(domain)
5151
if get_cert_err then
5252
ngx.log(ngx.ERR, "auto-ssl: error fetching certificate from storage for ", domain, ": ", get_cert_err)

lib/resty/auto-ssl/storage.lua

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,27 @@ local str = require "resty.string"
44
local _M = {}
55

66
function _M.new(options)
7+
assert(options)
8+
assert(options["adapter"])
9+
assert(options["json_adapter"])
10+
711
return setmetatable(options, { __index = _M })
812
end
913

1014
function _M.get_challenge(self, domain, path)
11-
return self.storage_adapter:get(domain .. ":challenge:" .. path)
15+
return self.adapter:get(domain .. ":challenge:" .. path)
1216
end
1317

1418
function _M.set_challenge(self, domain, path, value)
15-
return self.storage_adapter:set(domain .. ":challenge:" .. path, value)
19+
return self.adapter:set(domain .. ":challenge:" .. path, value)
1620
end
1721

1822
function _M.delete_challenge(self, domain, path)
19-
return self.storage_adapter:delete(domain .. ":challenge:" .. path)
23+
return self.adapter:delete(domain .. ":challenge:" .. path)
2024
end
2125

2226
function _M.get_cert(self, domain)
23-
local json, err = self.storage_adapter:get(domain .. ":latest")
27+
local json, err = self.adapter:get(domain .. ":latest")
2428
if err then
2529
return nil, err
2630
elseif not json then
@@ -55,14 +59,14 @@ function _M.set_cert(self, domain, fullchain_pem, privkey_pem, cert_pem, expiry)
5559
-- Store the cert with the current timestamp, so the old certs are preserved
5660
-- in case something goes wrong.
5761
local time = ngx.now() * 1000
58-
self.storage_adapter:set(domain .. ":" .. time, string)
62+
self.adapter:set(domain .. ":" .. time, string)
5963

6064
-- Store the cert under the "latest" alias, which is what this app will use.
61-
return self.storage_adapter:set(domain .. ":latest", string)
65+
return self.adapter:set(domain .. ":latest", string)
6266
end
6367

6468
function _M.all_cert_domains(self)
65-
local keys, err = self.storage_adapter:keys_with_suffix(":latest")
69+
local keys, err = self.adapter:keys_with_suffix(":latest")
6670
if err then
6771
return nil, err
6872
end
@@ -97,7 +101,7 @@ function _M.issue_cert_lock(self, domain)
97101
local sleep_time = 0.5
98102
local max_time = 30
99103
repeat
100-
local existing_value = self.storage_adapter:get(key)
104+
local existing_value = self.adapter:get(key)
101105
if not existing_value then
102106
unlocked = true
103107
else
@@ -107,7 +111,7 @@ function _M.issue_cert_lock(self, domain)
107111
until unlocked or wait_time > max_time
108112

109113
-- Create a new lock.
110-
local ok, err = self.storage_adapter:set(key, lock_rand_value, { exptime = 30 })
114+
local ok, err = self.adapter:set(key, lock_rand_value, { exptime = 30 })
111115
if not ok then
112116
return nil, err
113117
else
@@ -119,9 +123,9 @@ function _M.issue_cert_unlock(self, domain, lock_rand_value)
119123
local key = domain .. ":issue_cert_lock"
120124

121125
-- Remove the existing lock if it matches the expected value.
122-
local current_value, err = self.storage_adapter:get(key)
126+
local current_value, err = self.adapter:get(key)
123127
if lock_rand_value == current_value then
124-
return self.storage_adapter:delete(key)
128+
return self.adapter:delete(key)
125129
elseif current_value then
126130
return false, "lock does not match expected value"
127131
else

lib/resty/auto-ssl/storage_adapters/redis.lua

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,74 @@ local redis = require "resty.redis"
22

33
local _M = {}
44

5-
local function get_redis_instance(self)
6-
local instance = ngx.ctx.auto_ssl_redis_instance
7-
if instance then
8-
return instance
5+
local function prefixed_key(self, key)
6+
if self.options["prefix"] then
7+
return self.options["prefix"] .. ":" .. key
8+
else
9+
return key
10+
end
11+
end
12+
13+
function _M.new(auto_ssl_instance)
14+
local options = auto_ssl_instance:get("redis") or {}
15+
16+
if not options["host"] then
17+
options["host"] = "127.0.0.1"
18+
end
19+
20+
if not options["port"] then
21+
options["port"] = 6379
22+
end
23+
24+
return setmetatable({ options = options }, { __index = _M })
25+
end
26+
27+
function _M.get_connection(self)
28+
local connection = ngx.ctx.auto_ssl_redis_connection
29+
if connection then
30+
return connection
931
end
1032

11-
instance = redis:new()
33+
connection = redis:new()
1234
local ok, err
1335

1436
if self.options["socket"] then
15-
ok, err = instance:connect(self.options["socket"])
37+
ok, err = connection:connect(self.options["socket"])
1638
else
17-
ok, err = instance:connect(self.options["host"], self.options["port"])
39+
ok, err = connection:connect(self.options["host"], self.options["port"])
1840
end
1941
if not ok then
2042
return false, err
2143
end
2244

2345
if self.options["auth"] then
24-
ok, err = instance:auth(self.options["auth"])
46+
ok, err = connection:auth(self.options["auth"])
2547
if not ok then
2648
return false, err
2749
end
2850
end
2951

3052
if self.options["db"] then
31-
ok, err = instance:select(self.options["db"])
53+
ok, err = connection:select(self.options["db"])
3254
if not ok then
3355
return false, err
3456
end
3557
end
3658

37-
ngx.ctx.auto_ssl_redis_instance = instance
38-
return instance
39-
end
40-
41-
local function prefixed_key(self, key)
42-
if self.options["prefix"] then
43-
return self.options["prefix"] .. ":" .. key
44-
else
45-
return key
46-
end
47-
end
48-
49-
function _M.new(auto_ssl_instance)
50-
local options = auto_ssl_instance:get("redis") or {}
51-
52-
if not options["host"] then
53-
options["host"] = "127.0.0.1"
54-
end
55-
56-
if not options["port"] then
57-
options["port"] = 6379
58-
end
59-
60-
return setmetatable({ options = options }, { __index = _M })
59+
ngx.ctx.auto_ssl_redis_connection = connection
60+
return connection
6161
end
6262

6363
function _M.setup()
6464
end
6565

6666
function _M.get(self, key)
67-
local redis_instance, instance_err = get_redis_instance(self)
68-
if instance_err then
69-
return nil, instance_err
67+
local connection, connection_err = self:get_connection()
68+
if connection_err then
69+
return nil, connection_err
7070
end
7171

72-
local res, err = redis_instance:get(prefixed_key(self, key))
72+
local res, err = connection:get(prefixed_key(self, key))
7373
if res == ngx.null then
7474
res = nil
7575
end
@@ -78,16 +78,16 @@ function _M.get(self, key)
7878
end
7979

8080
function _M.set(self, key, value, options)
81-
local redis_instance, instance_err = get_redis_instance(self)
82-
if instance_err then
83-
return false, instance_err
81+
local connection, connection_err = self:get_connection()
82+
if connection_err then
83+
return false, connection_err
8484
end
8585

8686
key = prefixed_key(self, key)
87-
local ok, err = redis_instance:set(key, value)
87+
local ok, err = connection:set(key, value)
8888
if ok then
8989
if options and options["exptime"] then
90-
local _, expire_err = redis_instance:expire(key, options["exptime"])
90+
local _, expire_err = connection:expire(key, options["exptime"])
9191
if expire_err then
9292
ngx.log(ngx.ERR, "auto-ssl: failed to set expire: ", expire_err)
9393
end
@@ -98,21 +98,21 @@ function _M.set(self, key, value, options)
9898
end
9999

100100
function _M.delete(self, key)
101-
local redis_instance, instance_err = get_redis_instance(self)
102-
if instance_err then
103-
return false, instance_err
101+
local connection, connection_err = self:get_connection()
102+
if connection_err then
103+
return false, connection_err
104104
end
105105

106-
return redis_instance:del(prefixed_key(self, key))
106+
return connection:del(prefixed_key(self, key))
107107
end
108108

109109
function _M.keys_with_suffix(self, suffix)
110-
local redis_instance, instance_err = get_redis_instance(self)
111-
if instance_err then
112-
return false, instance_err
110+
local connection, connection_err = self:get_connection()
111+
if connection_err then
112+
return false, connection_err
113113
end
114114

115-
local keys, err = redis_instance:keys(prefixed_key(self, "*" .. suffix))
115+
local keys, err = connection:keys(prefixed_key(self, "*" .. suffix))
116116

117117
if keys and self.options["prefix"] then
118118
local unprefixed_keys = {}

0 commit comments

Comments
 (0)