Skip to content

Commit 311883e

Browse files
committed
upgrade lua-resty-session and lua-resty-openidc
1 parent a0fddda commit 311883e

22 files changed

Lines changed: 278 additions & 336 deletions

File tree

db/schema.sql

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,12 +1271,10 @@ ALTER SEQUENCE api_umbrella.published_config_id_seq OWNED BY api_umbrella.publis
12711271
--
12721272

12731273
CREATE TABLE api_umbrella.sessions (
1274-
id_hash character varying(64) NOT NULL,
1275-
data_encrypted bytea NOT NULL,
1276-
data_encrypted_iv character varying(12) NOT NULL,
1277-
expires_at timestamp with time zone NOT NULL,
1278-
created_at timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,
1279-
updated_at timestamp with time zone DEFAULT transaction_timestamp() NOT NULL
1274+
sid text NOT NULL,
1275+
name text,
1276+
data text,
1277+
exp timestamp with time zone
12801278
);
12811279

12821280

@@ -1842,7 +1840,7 @@ ALTER TABLE ONLY api_umbrella.rate_limits
18421840
--
18431841

18441842
ALTER TABLE ONLY api_umbrella.sessions
1845-
ADD CONSTRAINT sessions_pkey PRIMARY KEY (id_hash);
1843+
ADD CONSTRAINT sessions_pkey PRIMARY KEY (sid);
18461844

18471845

18481846
--
@@ -2034,7 +2032,7 @@ CREATE UNIQUE INDEX distributed_rate_limit_counters_version_idx ON api_umbrella.
20342032
-- Name: sessions_expires_at_idx; Type: INDEX; Schema: api_umbrella; Owner: -
20352033
--
20362034

2037-
CREATE INDEX sessions_expires_at_idx ON api_umbrella.sessions USING btree (expires_at);
2035+
CREATE INDEX sessions_exp_idx ON api_umbrella.sessions USING btree (exp);
20382036

20392037

20402038
--
@@ -2618,13 +2616,6 @@ CREATE TRIGGER published_config_stamp_record BEFORE INSERT OR DELETE OR UPDATE O
26182616
CREATE TRIGGER rate_limits_stamp_record BEFORE INSERT OR DELETE OR UPDATE ON api_umbrella.rate_limits FOR EACH ROW EXECUTE FUNCTION api_umbrella.stamp_record('[{"table_name":"api_backend_settings","primary_key":"id","foreign_key":"api_backend_settings_id"},{"table_name":"api_user_settings","primary_key":"id","foreign_key":"api_user_settings_id"}]');
26192617

26202618

2621-
--
2622-
-- Name: sessions sessions_stamp_record; Type: TRIGGER; Schema: api_umbrella; Owner: -
2623-
--
2624-
2625-
CREATE TRIGGER sessions_stamp_record BEFORE UPDATE ON api_umbrella.sessions FOR EACH ROW EXECUTE FUNCTION api_umbrella.update_timestamp();
2626-
2627-
26282619
--
26292620
-- Name: website_backends website_backends_stamp_record; Type: TRIGGER; Schema: api_umbrella; Owner: -
26302621
--

src/api-umbrella-git-1.rockspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ dependencies = {
1616
"lua-resty-mail ~> 1.1.0",
1717
"lua-resty-mlcache ~> 2.7.0",
1818
"lua-resty-nettle ~> 2.1",
19-
"lua-resty-openidc ~> 1.7.6",
20-
"lua-resty-session ~> 3.10",
19+
"lua-resty-openidc ~> 1.8.0",
20+
"lua-resty-session ~> 4.0",
2121
"lua-resty-txid ~> 1.0.0",
2222
"lua-resty-uuid ~> 1.1",
2323
"lua-resty-validation ~> 2.7",

src/api-umbrella/proxy/jobs/db_expirations.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ local function do_run()
1010
"DELETE FROM analytics_cache WHERE expires_at IS NOT NULL AND expires_at < now()",
1111
"DELETE FROM cache WHERE expires_at IS NOT NULL AND expires_at < now()",
1212
"DELETE FROM distributed_rate_limit_counters WHERE expires_at < now()",
13-
"DELETE FROM sessions WHERE expires_at < now()",
13+
"DELETE FROM sessions WHERE exp < now()",
1414
}
1515
for _, query in ipairs(queries) do
1616
local result, err = pg_utils.query(query, nil, { quiet = true })

src/api-umbrella/utils/pg_utils.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,12 @@ function _M.connect()
198198

199199
_M.setup_type_casting(pg)
200200

201-
-- The first time this socket is used (but not when reusing keepalive
202-
-- sockets), setup any session variables on the connection.
203-
if pg.sock:getreusedtimes() == 0 then
204-
_M.setup_socket_timeouts(pg)
205-
_M.setup_session_vars(pg, "api-umbrella")
206-
end
201+
-- Always setup session variables on the connection, even for reused
202+
-- keepalive sockets. Other libraries (e.g., lua-resty-session's postgres
203+
-- storage) may share the same connection pool and return connections without
204+
-- the expected search_path set.
205+
_M.setup_socket_timeouts(pg)
206+
_M.setup_session_vars(pg, "api-umbrella")
207207

208208
return pg
209209
end

src/api-umbrella/web-app/actions/admin/sessions.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,12 @@ end
139139

140140
function _M.destroy(self)
141141
self:init_session_db()
142-
local _, _, open_err = self.session_db:start()
143-
if open_err then
142+
local ok, open_err = self.session_db:open()
143+
if not ok and open_err and open_err ~= "missing session cookie" then
144144
ngx.log(ngx.ERR, "session open error: ", open_err)
145145
end
146146

147-
local sign_in_provider = self.session_db.data["sign_in_provider"]
147+
local sign_in_provider = self.session_db:get("sign_in_provider")
148148
self.session_db:destroy()
149149

150150
flash.session(self, "info", t("Signed out successfully."))
@@ -173,8 +173,8 @@ function _M.logout_callback(self)
173173
local state = ngx.var.arg_state
174174
if state then
175175
self:init_session_cookie()
176-
self.session_cookie:start()
177-
local session_state = self.session_cookie.data["openid_connect_state"]
176+
self.session_cookie:open()
177+
local session_state = self.session_cookie:get("openid_connect_state")
178178
if state ~= session_state then
179179
ngx.log(ngx.WARN, "state from argument: " .. (state or "nil") .. " does not match state restored from session: " .. (session_state or "nil"))
180180

src/api-umbrella/web-app/app.lua

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@ local resty_session = require "resty.session"
1616
local t = require("api-umbrella.web-app.utils.gettext").gettext
1717
local table_keys = require("pl.tablex").keys
1818

19-
require "resty.session.ciphers.api_umbrella"
20-
require "resty.session.hmac.api_umbrella"
21-
require "resty.session.identifiers.api_umbrella"
22-
require "resty.session.storage.api_umbrella_db"
23-
require "resty.session.serializers.api_umbrella"
24-
2519
local supported_languages = table_keys(LOCALE_DATA)
2620

2721
-- Custom error handler so we only show the default lapis debug details in
@@ -78,24 +72,27 @@ end
7872
-- server-side control on expiring sessions, and it can't be spoofed even with
7973
-- knowledge of the encryption secret key.
8074
local session_db_options = {
81-
storage = "api_umbrella_db",
82-
cipher = "api_umbrella",
83-
hmac = "api_umbrella",
84-
serializer = "api_umbrella",
85-
identifier = "api_umbrella",
86-
name = "_api_umbrella_session",
87-
secret = assert(config["secret_key"]),
88-
random = {
89-
length = 40,
90-
},
91-
cookie = {
92-
samesite = "Lax",
93-
secure = true,
94-
httponly = true,
95-
idletime = 30 * 60, -- 30 minutes
96-
lifetime = 12 * 60 * 60, -- 12 hours
97-
renew = -1, -- Disable renew
75+
storage = "postgres",
76+
postgres = {
77+
host = pg_utils.db_config.host,
78+
port = pg_utils.db_config.port,
79+
database = pg_utils.db_config.database,
80+
username = pg_utils.db_config.user,
81+
password = pg_utils.db_config.password,
82+
ssl = pg_utils.db_config.ssl,
83+
ssl_verify = pg_utils.db_config.ssl_verify,
84+
ssl_required = pg_utils.db_config.ssl_required,
85+
table = "api_umbrella.sessions",
86+
pool = "session_db",
9887
},
88+
secret = assert(config["secret_key"]),
89+
cookie_name = "_api_umbrella_session",
90+
cookie_same_site = "Lax",
91+
cookie_secure = true,
92+
cookie_http_only = true,
93+
idling_timeout = 30 * 60, -- 30 minutes
94+
rolling_timeout = 0, -- disabled, matches v3 renew=-1
95+
absolute_timeout = 12 * 60 * 60, -- 12 hours
9996
}
10097
local function init_session_db(self)
10198
if not self.session_db then
@@ -113,22 +110,14 @@ end
113110
-- session records in the database for the CSRF token).
114111
local session_cookie_options = {
115112
storage = "cookie",
116-
cipher = "api_umbrella",
117-
hmac = "api_umbrella",
118-
serializer = "api_umbrella",
119-
identifier = "api_umbrella",
120-
name = "_api_umbrella_session_client",
121113
secret = assert(config["secret_key"]),
122-
random = {
123-
length = 40,
124-
},
125-
cookie = {
126-
samesite = "Lax",
127-
secure = true,
128-
httponly = true,
129-
lifetime = 48 * 60 * 60, -- 48 hours
130-
renew = 1 * 60 * 60, -- 1 hour
131-
},
114+
cookie_name = "_api_umbrella_session_client",
115+
cookie_same_site = "Lax",
116+
cookie_secure = true,
117+
cookie_http_only = true,
118+
idling_timeout = 0, -- disabled for cookie-only sessions
119+
rolling_timeout = 1 * 60 * 60, -- 1 hour
120+
absolute_timeout = 48 * 60 * 60, -- 48 hours
132121
}
133122
local function init_session_cookie(self)
134123
if not self.session_cookie then
@@ -139,17 +128,19 @@ end
139128
local function current_admin_from_session(self)
140129
local current_admin
141130
self:init_session_db()
142-
local _, _, open_err = self.session_db:start()
143-
if open_err then
144-
if open_err == "session cookie idle time has passed" or open_err == "session cookie has expired" then
145-
flash.session(self, "info", t("Your session expired. Please sign in again to continue."))
146-
else
147-
ngx.log(ngx.ERR, "session open error: ", open_err)
131+
local ok, open_err = self.session_db:open()
132+
if not ok then
133+
if open_err and open_err ~= "missing session cookie" then
134+
if open_err == "session idling timeout exceeded" or open_err == "session absolute timeout exceeded" then
135+
flash.session(self, "info", t("Your session expired. Please sign in again to continue."))
136+
else
137+
ngx.log(ngx.ERR, "session open error: ", open_err)
138+
end
148139
end
149140
end
150141

151-
if self.session_db and self.session_db.data and self.session_db.data["admin_id"] then
152-
local admin_id = self.session_db.data["admin_id"]
142+
local admin_id = self.session_db:get("admin_id")
143+
if admin_id then
153144
local admin = Admin:find({ id = admin_id })
154145
if admin and not admin:is_access_locked() then
155146
current_admin = admin

src/api-umbrella/web-app/hooks/init_preload_modules.lua

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,6 @@ require "resty.http"
179179
require "resty.mlcache"
180180
require "resty.openidc"
181181
require "resty.session"
182-
require "resty.session.ciphers.api_umbrella"
183-
require "resty.session.hmac.api_umbrella"
184-
require "resty.session.identifiers.api_umbrella"
185-
require "resty.session.serializers.api_umbrella"
186-
require "resty.session.storage.api_umbrella_db"
187182
require "resty.uuid"
188183
require "resty.validation"
189184
require "resty.validation.ngx"

src/api-umbrella/web-app/utils/auth_external_oauth2.lua

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ end
8989
function _M.authorize(self, strategy_name, url, params)
9090
local state = random_token(64)
9191
self:init_session_cookie()
92-
self.session_cookie:start()
93-
self.session_cookie.data["oauth2_state"] = state
92+
self.session_cookie:open()
93+
self.session_cookie:set("oauth2_state", state)
9494
self.session_cookie:save()
9595

9696
local callback_url = build_url(auth_external_path(strategy_name, "/callback"))
@@ -119,17 +119,16 @@ function _M.userinfo(self, strategy_name, options)
119119
end
120120

121121
self:init_session_cookie()
122-
local _, _, open_err = self.session_cookie:start()
123-
if open_err then
122+
local ok, open_err = self.session_cookie:open()
123+
if not ok and open_err and open_err ~= "missing session cookie" then
124124
ngx.log(ngx.ERR, "session open error: ", open_err)
125125
end
126126

127-
if not self.session_cookie or not self.session_cookie.data or not self.session_cookie.data["oauth2_state"] then
127+
local stored_state = self.session_cookie:get("oauth2_state")
128+
if not stored_state then
128129
ngx.log(ngx.ERR, "oauth2 state not available")
129130
return nil, t("Cross-site request forgery detected")
130131
end
131-
132-
local stored_state = self.session_cookie.data["oauth2_state"]
133132
local state = self.params["state"]
134133
if state ~= stored_state then
135134
ngx.log(ngx.ERR, "oauth2 state does not match")

src/api-umbrella/web-app/utils/auth_external_openid_connect.lua

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ function _M.authenticate(self, strategy_name, callback)
4343
-- Call the provider-specific callback logic, which should handle
4444
-- authorizing the API Umbrella session and redirecting as appropriate.
4545
callback({
46-
id_token = session["data"]["id_token"],
47-
user = session["data"]["user"],
46+
id_token = session:get("id_token"),
47+
user = session:get("user"),
4848
})
4949

5050
-- This shouldn't get hit, since callback should perform it's own
@@ -83,13 +83,14 @@ function _M.authenticate(self, strategy_name, callback)
8383
if discovery and discovery["end_session_endpoint"] then
8484
-- Generate the state parameter to send.
8585
self:init_session_cookie()
86-
self.session_cookie:start()
87-
self.session_cookie.data["openid_connect_state"] = random_token(64)
86+
self.session_cookie:open()
87+
local oidc_state = random_token(64)
88+
self.session_cookie:set("openid_connect_state", oidc_state)
8889
self.session_cookie:save()
8990

9091
-- Add the "state" param to the logout URL.
9192
local extra_logout_args = {
92-
state = self.session_cookie.data["openid_connect_state"]
93+
state = oidc_state
9394
}
9495

9596
-- Add the "client_id" param to the logout URL if id_token_hint won't be
@@ -121,7 +122,7 @@ function _M.authenticate(self, strategy_name, callback)
121122
-- Create a separate session for lua-resty-openidc's storage so it doesn't
122123
-- conflict with any of our sessions.
123124
local session_options = deepcopy(self.session_db_options)
124-
session_options["name"] = "_api_umbrella_openidc"
125+
session_options["cookie_name"] = "_api_umbrella_openidc"
125126

126127
-- In the test environment allow mocking the login process.
127128
if config["app_env"] == "test" and ngx.var.cookie_test_mock_userinfo then

src/api-umbrella/web-app/utils/csrf.lua

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,18 @@ local _M = {}
1717

1818
function _M.generate_token(self)
1919
self:init_session_cookie()
20-
self.session_cookie:start()
21-
local csrf_token_key = self.session_cookie.data["csrf_token_key"]
22-
local csrf_token_iv = self.session_cookie.data["csrf_token_iv"]
20+
self.session_cookie:open()
21+
local csrf_token_key = self.session_cookie:get("csrf_token_key")
22+
local csrf_token_iv = self.session_cookie:get("csrf_token_iv")
2323
if not csrf_token_key or not csrf_token_iv then
2424
if not csrf_token_key then
2525
csrf_token_key = random_token(40)
26-
self.session_cookie.data["csrf_token_key"] = csrf_token_key
26+
self.session_cookie:set("csrf_token_key", csrf_token_key)
2727
end
2828

2929
if not csrf_token_iv then
3030
csrf_token_iv = random_token(12)
31-
self.session_cookie.data["csrf_token_iv"] = csrf_token_iv
31+
self.session_cookie:set("csrf_token_iv", csrf_token_iv)
3232
end
3333

3434
self.session_cookie:save()
@@ -41,12 +41,12 @@ end
4141

4242
local function validate_token(self)
4343
self:init_session_cookie()
44-
local _, _, open_err = self.session_cookie:start()
45-
if open_err then
44+
local ok, open_err = self.session_cookie:open()
45+
if not ok and open_err and open_err ~= "missing session cookie" then
4646
ngx.log(ngx.ERR, "session open error: ", open_err)
4747
end
4848

49-
local key = self.session_cookie.data["csrf_token_key"]
49+
local key = self.session_cookie:get("csrf_token_key")
5050
if not key then
5151
return false, "Missing CSRF token key"
5252
end

0 commit comments

Comments
 (0)