Skip to content

Commit 541c5ca

Browse files
committed
chore: fixup with rebase
1 parent b759523 commit 541c5ca

File tree

5 files changed

+96
-23
lines changed

5 files changed

+96
-23
lines changed

lib/supavisor/client_handler.ex

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,33 @@ defmodule Supavisor.ClientHandler do
620620
end
621621
end
622622

623+
def handle_event(:info, {proto, socket, bin}, :auth_password_wait, data)
624+
when proto in @proto do
625+
auth_context = data.auth_context
626+
{:ok, {ip, _port}} = :inet.peername(socket)
627+
628+
with {:ok, cls_password} <- Auth.parse_auth_message(bin, auth_context.method),
629+
{:ok, key, method} <-
630+
Auth.validate_credentials(
631+
auth_context.method,
632+
auth_context.info.tenant,
633+
auth_context.secrets,
634+
cls_password,
635+
ip
636+
) do
637+
handle_auth_success(
638+
data.sock,
639+
{method, auth_context.secrets},
640+
key,
641+
cls_password,
642+
data
643+
)
644+
else
645+
{:error, reason, _} ->
646+
handle_auth_failure(data.sock, reason, data, :auth_password_wait)
647+
end
648+
end
649+
623650
# SCRAM authentication - waiting for first message
624651
def handle_event(:info, {proto, _socket, bin}, :auth_scram_first_wait, data)
625652
when proto in @proto do
@@ -671,7 +698,12 @@ defmodule Supavisor.ClientHandler do
671698

672699
# Authentication timeout handler
673700
def handle_event(:timeout, :auth_timeout, auth_state, data)
674-
when auth_state in [:auth_md5_wait, :auth_scram_first_wait, :auth_scram_final_wait] do
701+
when auth_state in [
702+
:auth_md5_wait,
703+
:auth_password_wait,
704+
:auth_scram_first_wait,
705+
:auth_scram_final_wait
706+
] do
675707
handle_auth_failure(data.sock, {:timeout, auth_state}, data, auth_state)
676708
end
677709

@@ -795,9 +827,12 @@ defmodule Supavisor.ClientHandler do
795827
end
796828

797829
## Internal functions
798-
799830
defp handle_auth_success(sock, {method, secrets}, client_key, data) do
800-
final_secrets = Auth.prepare_final_secrets(secrets, client_key)
831+
handle_auth_success(sock, {method, secrets}, client_key, nil, data)
832+
end
833+
834+
defp handle_auth_success(sock, {method, secrets}, client_key, password, data) do
835+
final_secrets = Auth.prepare_final_secrets(secrets, client_key, password)
801836

802837
# Only store in TenantCache for pool modes (transaction/session)
803838
# For proxy mode, secrets are passed directly to DbHandler via data.auth

lib/supavisor/client_handler/auth.ex

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,39 +83,38 @@ defmodule Supavisor.ClientHandler.Auth do
8383
else: {:error, :wrong_password}
8484
end
8585

86-
def validate_credentials(:auth_query_jit, secrets, password, ip) do
86+
def validate_credentials(:auth_query_jit, tenant, secrets, password, ip) do
8787
# check if incomming password looks like PAT or a JWT
8888
# otherwise handle as password,
8989
secret = secrets.()
9090

9191
if Helpers.token_matches?(password) do
92-
Logger.debug("Looks like a PAT/JWT - #{inspect(secret.jit_api_url)}")
9392
rhost = ip |> :inet.ntoa() |> to_string()
9493

95-
case Helpers.check_user_has_jit_role(secret.jit_api_url, password, secret.user, rhost) do
94+
case Helpers.check_user_has_jit_role(tenant.jit_api_url, password, secret.user, rhost) do
9695
{:ok, true} ->
9796
# set a fake client_key incase upstream switches away from pam mid auth
98-
{:ok, :crypto.hash(:sha256, password)}
97+
{:ok, :crypto.hash(:sha256, password), :auth_query_jit}
9998

10099
{:ok, false} ->
101100
Logger.debug("User token is valid but can't assume this role")
102-
{:error, :wrong_password}
101+
{:error, :wrong_password, :auth_query_jit}
103102

104103
{:error, :unauthorized_or_forbidden} ->
105-
{:error, :wrong_password}
104+
{:error, :wrong_password, :auth_query_jit}
106105

107106
{:error, _} ->
108107
Logger.debug("Unexpected error while calling API")
109-
{:error, :wrong_password}
108+
{:error, :wrong_password, :auth_query_jit}
110109
end
111110
else
112111
# match against the scram-sha-256 / md5 we have from auth_query
113112
case secret.digest do
114113
:md5 ->
115114
if Helpers.md5([password, secret.user]) == secret.secret do
116-
{:ok, nil}
115+
{:ok, nil, :auth_query_md5}
117116
else
118-
{:error, :wrong_password}
117+
{:error, :wrong_password, :auth_query_md5}
119118
end
120119

121120
_ ->
@@ -128,8 +127,8 @@ defmodule Supavisor.ClientHandler.Auth do
128127
stored_key = :crypto.hash(:sha256, client_key)
129128

130129
if :crypto.hash_equals(stored_key, secret.stored_key),
131-
do: {:ok, client_key},
132-
else: {:error, :wrong_password}
130+
do: {:ok, client_key, :auth_query},
131+
else: {:error, :wrong_password, :auth_query}
133132
end
134133
end
135134
end
@@ -248,6 +247,9 @@ defmodule Supavisor.ClientHandler.Auth do
248247

249248
def parse_auth_message(bin, _scram_method) do
250249
case Server.decode_pkt(bin) do
250+
{:ok, %{tag: :password_message, payload: {:cleartext_password, cls_password}}, _} ->
251+
{:ok, cls_password}
252+
251253
{:ok,
252254
%{
253255
tag: :password_message,
@@ -284,8 +286,19 @@ defmodule Supavisor.ClientHandler.Auth do
284286
}
285287
end
286288

289+
@spec create_auth_context(auth_method(), function(), map()) :: map()
290+
def create_auth_context(:auth_query_jit, secrets, info) do
291+
%{
292+
method: :auth_query_jit,
293+
secrets: secrets,
294+
info: info,
295+
cls_password: nil,
296+
signatures: nil
297+
}
298+
end
299+
287300
def create_auth_context(method, secrets, info)
288-
when method in [:password, :auth_query, :auth_query_jit] do
301+
when method in [:password, :auth_query] do
289302
%{
290303
method: method,
291304
secrets: secrets,
@@ -302,6 +315,14 @@ defmodule Supavisor.ClientHandler.Auth do
302315
%{auth_context | signatures: signatures}
303316
end
304317

318+
@doc """
319+
Updates authentication context with new jit information after first exchange.
320+
"""
321+
@spec update_auth_context_with_jit(map(), map()) :: map()
322+
def update_auth_context_with_jit(auth_context, cls_password) do
323+
%{auth_context | cls_password: cls_password}
324+
end
325+
305326
## Success Response Preparation
306327

307328
@doc """
@@ -327,6 +348,15 @@ defmodule Supavisor.ClientHandler.Auth do
327348
fn -> Map.put(secrets_fn.(), :client_key, client_key) end
328349
end
329350

351+
def prepare_final_secrets(secrets_fn, client_key, password) do
352+
fn ->
353+
Map.merge(secrets_fn.(), %{
354+
client_key: client_key,
355+
cls_password: password
356+
})
357+
end
358+
end
359+
330360
## Private Helpers
331361

332362
@spec fetch_secrets_from_database(Supavisor.id(), map(), String.t()) ::
@@ -365,7 +395,7 @@ defmodule Supavisor.ClientHandler.Auth do
365395
with {:ok, secret} <- Helpers.get_user_secret(conn, tenant.auth_query, db_user) do
366396
auth_type =
367397
case {tenant.use_jit, secret} do
368-
{true, %PasswordSecrets{}} -> :auth_query_jit
398+
{true, _} -> :auth_query_jit
369399
{_, %MD5Secrets{}} -> :auth_query_md5
370400
{_, %SASLSecrets{}} -> :auth_query
371401
end

lib/supavisor/client_handler/auth/password_secrets.ex

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ defmodule Supavisor.ClientHandler.Auth.PasswordSecrets do
66

77
@type t :: %__MODULE__{
88
user: String.t(),
9-
password: String.t(),
10-
use_jit: Bool.t(),
11-
jit_api_url: String.t()
9+
password: String.t()
1210
}
1311
end
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
defmodule Supavisor.ClientHandler.Auth.SASLSecrets do
22
@moduledoc "Secrets for SCRAM-SHA-256 authentication"
33

4-
@derive {Inspect, except: [:client_key, :server_key, :salt, :stored_key]}
5-
defstruct [:user, :client_key, :server_key, :digest, :iterations, :salt, :stored_key]
4+
@derive {Inspect, except: [:client_key, :server_key, :salt, :stored_key, :cls_password]}
5+
defstruct [
6+
:user,
7+
:client_key,
8+
:server_key,
9+
:digest,
10+
:iterations,
11+
:salt,
12+
:stored_key,
13+
:cls_password
14+
]
615

716
@type t :: %__MODULE__{
817
user: String.t(),
@@ -11,6 +20,7 @@ defmodule Supavisor.ClientHandler.Auth.SASLSecrets do
1120
digest: atom(),
1221
iterations: pos_integer(),
1322
salt: binary(),
14-
stored_key: binary()
23+
stored_key: binary(),
24+
cls_password: String.t() | nil
1525
}
1626
end

lib/supavisor/secret_checker.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ defmodule Supavisor.SecretChecker do
129129
{:ok, secret} ->
130130
method =
131131
case {t.use_jit, secret} do
132-
{true, %Auth.PasswordSecrets{}} -> :auth_query_jit
132+
{true, %Auth.SASLSecrets{}} -> :auth_query_jit
133133
{_, %Auth.MD5Secrets{}} -> :auth_query_md5
134134
{_, %Auth.SASLSecrets{}} -> :auth_query
135135
end

0 commit comments

Comments
 (0)