Skip to content

pgsql: Remove explicit user option from exec_sql #2050

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

okamoto-sansan
Copy link

What i did

Removed the direct usage of -U $OCF_RESKEY_pgdba within the
exec_sql() function for specifying the psql user.

This change ensures that exec_sql() consistently uses the database
user defined in the global $psql_options. It simplifies user
management by relying on a single source for psql connection
parameters, including credentials, for operations invoked via
this function.

Problem Description

When the monitor_user attribute is configured in the pgsql RA, the main() function exports PGUSER (set to $OCF_RESKEY_monitor_user) and PGPASSWORD (set to $OCF_RESKEY_monitor_password) as global environment variables during resource startup.

The psql_options variable is set as follows:

# In main()
if [ -n "$OCF_RESKEY_monitor_user" ]; then
    PGUSER=$OCF_RESKEY_monitor_user; export PGUSER
    PGPASSWORD=$OCF_RESKEY_monitor_password; export PGPASSWORD
    # Note: -U is NOT included here when monitor_user is set
    psql_options="-p $OCF_RESKEY_pgport $OCF_RESKEY_pgdb"
else
    psql_options="-p $OCF_RESKEY_pgport -U $OCF_RESKEY_pgdba $OCF_RESKEY_pgdb"
fi

During the PostgreSQL startup sequence initiated by the RA (pgsql_real_start() → pgsql_real_monitor()), the exec_sql() function is called to check the database's recovery status (by running SELECT pg_is_in_recovery()).

The exec_sql() function, as seen in heartbeat/pgsql#L534, constructs a psql command that explicitly includes the -U $OCF_RESKEY_pgdba option:

# Snippet from exec_sql()
exec_sql() {
    local sql="$1"
    local output
    local rc

    output=`$SU $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; \
                $OCF_RESKEY_psql $psql_options -U $OCF_RESKEY_pgdba \
                -Atc \"$sql\""`
    rc=$?

    echo $output
    return $rc
}

This leads to an authentication issue due to the interaction of psql command-line options and environment variables:

  1. The psql command is executed with -U $OCF_RESKEY_pgdba, so it attempts to connect as the database administrator user (e.g., postgres).
  2. However, the PGPASSWORD environment variable (which was previously exported and set to the password of $OCF_RESKEY_monitor_user) is present in the environment where psql runs.
  3. psql uses the value of the PGPASSWORD environment variable for authentication if it is set.

Consequently, psql attempts to authenticate as the $OCF_RESKEY_pgdba user but uses the password intended for $OCF_RESKEY_monitor_user. If these passwords differ, the authentication fails. This prevents the RA from obtaining the recovery status, ultimately causing the pgsql resource agent to report an error.

The effective psql invocation attempts the following:
Connect as user: $OCF_RESKEY_pgdba
Using password: Value of PGPASSWORD (which is $OCF_RESKEY_monitor_password)

If the monitor_user's password does not match the pgdba's password, the connection fails, and the RA cannot determine the recovery status, as shown in the logs (see also heartbeat/pgsql#L978):

May 21 12:29:46  pgsql(pgsql)[9024]:    WARNING: Can't get PostgreSQL recovery status. rc=2
May 21 12:29:46  pgsql(pgsql)[9024]:    WARNING: Connection error (connection to the server went bad and the session was not interactive) occurred while executing the psql command.

May 21 12:29:47.510 dev-data-a302 pacemaker-controld  [8773] (log_executor_event)  notice: pgsql_start_0@dev-data-a302 output [ psql: error: connection to server at "localhost" (10.1.10.302), port 5432 failed: FATAL:  password authentication failed for user "postgres" ]

If you use the same password for monitor_password and pgdba(postgres), you can get the recovery status without any problem.

Node Attributes:
  * Node: dev-data-a302:
    * master-pgsql                      : 1000
    * pgsql-data-status                 : LATEST
    * pgsql-receiver-status             : normal (master)
    * pgsql-status                      : PRI
  * Node: dev-data-c302:
    * master-pgsql                      : 100
    * pgsql-data-status                 : STREAMING|ASYNC
    * pgsql-receiver-status             : normal
    * pgsql-status                      : HS:async

Enviroment

  • Pacemaker: 2.1.8-3.el9
  • pcs: 0.11.8-1.el9_5.2
  • PostgreSQL: 17.4-1PGDG.rhel9

Copy link

knet-jenkins bot commented May 22, 2025

Can one of the admins check and authorise this run please: https://ci.kronosnet.org/job/resource-agents/job/resource-agents-pipeline/job/PR-2050/1/input

@oalbrigt
Copy link
Contributor

I will look into adding a password parameter for the 2nd user, and make sure it also works for current setups.

@okamoto-sansan
Copy link
Author

Thanks for your consideration, my understanding is that the pgdba parameter is assumed to be an OS user, and only if monitor_user is not specified is it also used as a DB user.

User that owns PostgreSQL.

I was of the opinion that pgdba should exist only as an OS user, but considering the existing RA behavior and many usage scenarios, I think the best suggestion is to assume that pgdba is also used as a DB user name (when monitor_user is not specified) and to support password authentication in that case. I reconsider that the best suggestion is to support password authentication in that case.

You are free to close this PR, Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants