-
-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: use simple_connection for auth_query #342
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! :)
@@ -88,7 +88,11 @@ defmodule Supavisor.Helpers do | |||
@spec get_user_secret(pid(), String.t(), String.t()) :: {:ok, map()} | {:error, String.t()} | |||
def get_user_secret(conn, auth_query, user) do | |||
try do | |||
Postgrex.query!(conn, auth_query, [user]) | |||
# sanitize the user input by removing all characters that are not alphanumeric or underscores | |||
user = String.replace(user, ~r/[^a-zA-Z0-9_]/, "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@filipecabaco wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that instead we should reject user
if these characters are present instead of just pretending that these do not exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I already have a check for invalid characters during connection, but it only checks for slashes. I added this sanitization as an additional guard. It might be worth applying the same rule (a-zA-Z0-9_
) during connection as well
supavisor/lib/supavisor/client_handler.ex
Lines 157 to 164 in 61b629d
not_allowed = ["\"", "\\"] | |
if String.contains?(user, not_allowed) or String.contains?(db_name, not_allowed) do | |
reason = "Invalid characters in user or db_name" | |
Logger.error("ClientHandler: #{inspect(reason)}") | |
Telem.client_join(:fail, data.id) | |
HH.send_error(data.sock, "XX000", "Authentication error, reason: #{inspect(reason)}") | |
{:stop, {:shutdown, :invalid_characters}} |
$ psql postgresql://p\"ostgres.tenant:password@localhost:5432/postgres
psql: error: connection to server at "localhost" (::1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL: Authentication error, reason: "Invalid characters in user or db_name"
assert Enum.filter(Process.list(), fn pid -> | ||
Process.info(pid)[:dictionary][:auth_host] == db_conf[:hostname] | ||
end) == [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert Enum.filter(Process.list(), fn pid -> | |
Process.info(pid)[:dictionary][:auth_host] == db_conf[:hostname] | |
end) == [] | |
assert Enum.all?(Process.list(), fn pid -> | |
Process.info(pid)[:dictionary][:auth_host] == db_conf[:hostname] | |
end) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For what is worth, using filter for this test has a tiny benefit that it shows the left side with the failed PIDs in exception reports. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. That indeed may be useful.
@@ -88,7 +88,11 @@ defmodule Supavisor.Helpers do | |||
@spec get_user_secret(pid(), String.t(), String.t()) :: {:ok, map()} | {:error, String.t()} | |||
def get_user_secret(conn, auth_query, user) do | |||
try do | |||
Postgrex.query!(conn, auth_query, [user]) | |||
# sanitize the user input by removing all characters that are not alphanumeric or underscores | |||
user = String.replace(user, ~r/[^a-zA-Z0-9_]/, "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that instead we should reject user
if these characters are present instead of just pretending that these do not exists.
The PID of the Postgrex connection can be lost when ClientHandler terminates in the middle of getting secrets via auth_query. As a result, we may get zombie connections, which can consume all allowed connections to the tenant's database. With this PR, auth_query will be done with SimpleConnection, where the process crashes automatically if the caller (ClientHandler) goes down.