From 5ced62aab3d3152e454b866af29f35d93ad70aa2 Mon Sep 17 00:00:00 2001 From: solidDoWant Date: Thu, 24 Apr 2025 02:38:20 -0500 Subject: [PATCH] Support standard libpq environment variables for Auth service (#901) --- .github/workflows/auth-hurl.yml | 2 +- api/.env.example | 4 +-- auth/.env.example | 23 +++++++++++++---- auth/main.go | 44 +++++++++++++++++++++++---------- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/.github/workflows/auth-hurl.yml b/.github/workflows/auth-hurl.yml index 26675789..42de49a9 100644 --- a/.github/workflows/auth-hurl.yml +++ b/.github/workflows/auth-hurl.yml @@ -51,7 +51,7 @@ jobs: wget --retry-connrefused --retry-on-http-error=502 http://localhost:4568/health hurl --error-format long --variable host=http://localhost:4568 tests/* env: - POSTGRES_SERVER: localhost + PGHOST: localhost FIRST_USER_CLAIMS: '{"permissions": ["users.read"]}' KEIBI_APIKEY_HURL: 1234apikey KEIBI_APIKEY_HURL_CLAIMS: '{"permissions": ["apikeys.write", "apikeys.read"]}' diff --git a/api/.env.example b/api/.env.example index ac9db9df..25721a6f 100644 --- a/api/.env.example +++ b/api/.env.example @@ -20,8 +20,8 @@ IMAGES_PATH=./images # https://www.postgresql.org/docs/current/libpq-envars.html PGUSER=kyoo PGPASSWORD=password -PGDB=kyooDB -PGSERVER=postgres +PGDATABASE=kyooDB +PGHOST=postgres PGPORT=5432 # PGOPTIONS=-c search_path=kyoo,public # PGPASSFILE=/my/password # Takes precedence over PGPASSWORD. New line characters are not trimmed. diff --git a/auth/.env.example b/auth/.env.example index 9e3f410f..5f5195d6 100644 --- a/auth/.env.example +++ b/auth/.env.example @@ -29,11 +29,24 @@ PUBLIC_URL=http://localhost:8901 # KEIBI_APIKEY_$YOURNAME_CLAIMS='{"permissions": ["users.read"]}' # Database things -POSTGRES_USER=kyoo -POSTGRES_PASSWORD=password -POSTGRES_DB=kyoo -POSTGRES_SERVER=postgres -POSTGRES_PORT=5432 +# It is recommended to use the below PG environment variables when possible. +# POSTGRES_URL=postgres://user:password@hostname:port/dbname?sslmode=verify-full&sslrootcert=/path/to/server.crt&sslcert=/path/to/client.crt&sslkey=/path/to/client.key + +# The behavior of the below variables match what is documented here: +# https://www.postgresql.org/docs/current/libpq-envars.html +# The "source of truth" for what variables are supported is documented here: +# https://github.com/jackc/pgx/blob/master/pgconn/config.go#L190-L205 +PGUSER=kyoo +PGPASSWORD=password +PGDATABASE=kyoo +PGHOST=postgres +PGPORT=5432 +# PGPASSFILE=/my/password +# PGSSLMODE=verify-full +# PGSSLROOTCERT=/my/serving.crt +# PGSSLCERT=/my/client.crt +# PGSSLKEY=/my/client.key + # Default is keibi, you can specify "disabled" to use the default search_path of the user. # If this is not "disabled", the schema will be created (if it does not exists) and # the search_path of the user will be ignored (only the schema specified will be used). diff --git a/auth/main.go b/auth/main.go index 9c40cf09..837e5a05 100644 --- a/auth/main.go +++ b/auth/main.go @@ -7,7 +7,7 @@ import ( "fmt" "net/http" "os" - "strconv" + "os/user" "strings" "github.com/zoriya/kyoo/keibi/dbc" @@ -73,23 +73,41 @@ func GetenvOr(env string, def string) string { func OpenDatabase() (*pgxpool.Pool, error) { ctx := context.Background() - port, err := strconv.ParseUint(GetenvOr("POSTGRES_PORT", "5432"), 10, 16) + connectionString := GetenvOr("POSTGRES_URL", "") + config, err := pgxpool.ParseConfig(connectionString) if err != nil { - return nil, errors.New("invalid postgres port specified") + return nil, errors.New("failed to create postgres config from environment variables") } - config, _ := pgxpool.ParseConfig("") - config.ConnConfig.Host = GetenvOr("POSTGRES_SERVER", "postgres") - config.ConnConfig.Port = uint16(port) - config.ConnConfig.Database = GetenvOr("POSTGRES_DB", "kyoo") - config.ConnConfig.User = GetenvOr("POSTGRES_USER", "kyoo") - config.ConnConfig.Password = GetenvOr("POSTGRES_PASSWORD", "password") - config.ConnConfig.TLSConfig = nil - config.ConnConfig.RuntimeParams = map[string]string{ - "application_name": "keibi", + // Set default values + if config.ConnConfig.Host == "" { + config.ConnConfig.Host = "postgres" } + if config.ConnConfig.Database == "" { + config.ConnConfig.Database = "kyoo" + } + // The pgx library will set the username to the name of the current user if not provided via + // environment variable or connection string. Make a best-effort attempt to see if the user + // was explicitly specified, without implementing full connection string parsing. If not, set + // the username to the default value of "kyoo". + if os.Getenv("PGUSER") == "" { + currentUserName, _ := user.Current() + // If the username matches the current user and it's not in the connection string, then it was set + // by the pgx library. This doesn't cover the case where the system username happens to be in some other part + // of the connection string, but this cannot be checked without full connection string parsing. + if currentUserName.Username == config.ConnConfig.User && !strings.Contains(connectionString, currentUserName.Username) { + config.ConnConfig.User = "kyoo" + } + } + if config.ConnConfig.Password == "" { + config.ConnConfig.Password = "password" + } + if _, ok := config.ConnConfig.RuntimeParams["application_name"]; !ok { + config.ConnConfig.RuntimeParams["application_name"] = "keibi" + } + schema := GetenvOr("POSTGRES_SCHEMA", "keibi") - if schema != "disabled" { + if _, ok := config.ConnConfig.RuntimeParams["search_path"]; !ok { config.ConnConfig.RuntimeParams["search_path"] = schema }