This is an implementation of the idea I mentioned in [0]. The naming and description perhaps isn't ideal yet but it works in principle.
The idea is that if you connect over a Unix-domain socket and the local (effective) user is the same as the server's (effective) user, then access should be granted immediately without any checking of pg_hba.conf. Because it's "your own" server and you can do anything you want with it anyway. I included an option to turn this off because (a) people are going to complain, (b) you need this for the test suites to be able to test pg_hba.conf, and (c) conceivably, someone might want to have all access to go through pg_hba.conf for some auditing reasons (perhaps via PAM). This addresses the shortcomings of using peer as the default mechanism in initdb. In a subsequent step, my idea would be to make the default initdb authentication setup to use md5 (or scram, tbd.) for both local and host. [0]: https://www.postgresql.org/message-id/29164e47-8dfb-4737-2a61-e67a18f847f3%402ndquadrant.com -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From d121f818cb0364e1ad006de4ae92c7472bc21878 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <pe...@eisentraut.org> Date: Tue, 6 Aug 2019 20:41:19 +0200 Subject: [PATCH v1] Allow cluster owner to bypass authentication --- doc/src/sgml/client-auth.sgml | 29 +++++++++++++++++++ doc/src/sgml/config.sgml | 21 ++++++++++++++ src/backend/libpq/auth.c | 22 +++++++++++++- src/backend/utils/misc/guc.c | 9 ++++++ src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/libpq/auth.h | 1 + src/test/perl/PostgresNode.pm | 1 + 7 files changed, 83 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index fada7289d4..c84565a115 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -54,6 +54,35 @@ <title>Client Authentication</title> database user names and OS user names. </para> + <sect1 id="auth-cluster-owner"> + <title>Cluster Owner Authentication</title> + + <para> + When connecting over the Unix-domain socket, if the client user is the same + as the user that runs the database server (which is also the same as the + owner of the data directory), then access is immediately granted without + further checking. This allows a database cluster owner to connect to + their own database server without being subject to the rest of client + authentication (described in the rest of this chapter). + </para> + + <para> + This mechanism is only available on operating systems providing the + <function>getpeereid()</function> function, the + <symbol>SO_PEERCRED</symbol> socket parameter, or similar mechanisms. + Currently that includes <systemitem class="osname">Linux</systemitem>, most + flavors of <systemitem class="osname">BSD</systemitem> including + <systemitem class="osname">macOS</systemitem>, and <systemitem + class="osname">Solaris</systemitem>. If it is not available, then cluster + owner connections are subject to the normal client authentication. + </para> + + <para> + This mechanism can be disabled using the configuration parameter <xref + linkend="guc-cluster-owner-bypass-auth"/>. + </para> + </sect1> + <sect1 id="auth-pg-hba-conf"> <title>The <filename>pg_hba.conf</filename> File</title> diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index cdc30fa5e3..df2a08bb16 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1099,6 +1099,27 @@ <title>Authentication</title> </note> </listitem> </varlistentry> + + <varlistentry id="guc-cluster-owner-bypass-auth" xreflabel="cluster_owner_bypass_auth"> + <term><varname>cluster_owner_bypass_auth</varname> (<type>boolean</type>) + <indexterm> + <primary><varname>cluster_owner_bypass_auth</varname> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + If enabled, when connecting over the Unix-domain socket, if the client + user is the same as the user that runs the database server, then + access is immediately granted without further checking. See <xref + linkend="auth-cluster-owner"/>. This is enabled by default and + usually very useful. A possible reason to turn it off might be if all + authentication is through PAM with auditing and one wants even cluster + owner access to go through auditing that way. Another reason to turn + this off is to be able to test a <filename>pg_hba.conf</filename> + configuration more easily. + </para> + </listitem> + </varlistentry> </variablelist> </sect2> diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 0e0a6d8752..af75170606 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -160,11 +160,12 @@ static int CheckCertAuth(Port *port); /*---------------------------------------------------------------- - * Kerberos and GSSAPI GUCs + * GUCs *---------------------------------------------------------------- */ char *pg_krb_server_keyfile; bool pg_krb_caseins_users; +bool cluster_owner_bypass_auth; /*---------------------------------------------------------------- @@ -345,6 +346,25 @@ ClientAuthentication(Port *port) int status = STATUS_ERROR; char *logdetail = NULL; + /* + * If connecting over Unix-domain socket and peer uid matches current + * process uid, then allow connection immediately. + */ + if (cluster_owner_bypass_auth && + IS_AF_UNIX(port->raddr.addr.ss_family)) + { + uid_t peer_uid = -1; + gid_t peer_gid = -1; + int res; + + res = getpeereid(port->sock, &peer_uid, &peer_gid); + if (res == 0 && peer_uid == geteuid()) + { + sendAuthRequest(port, AUTH_REQ_OK, NULL, 0); + return; + } + } + /* * Get the authentication method to use for this frontend/database * combination. Note: we do not parse the file at this point; this has diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index eb78522053..7ea2bf5074 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -1952,6 +1952,15 @@ static struct config_bool ConfigureNamesBool[] = NULL, NULL, NULL }, + { + {"cluster_owner_bypass_auth", PGC_SIGHUP, CONN_AUTH_AUTH, + gettext_noop("Whether cluster owner connecting over Unix-domain socket bypasses authentication."), + }, + &cluster_owner_bypass_auth, + true, + NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 65a6da18b3..65ffb88952 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -90,6 +90,7 @@ #authentication_timeout = 1min # 1s-600s #password_encryption = md5 # md5 or scram-sha-256 #db_user_namespace = off +#cluster_owner_bypass_auth = on # GSSAPI using Kerberos #krb_server_keyfile = '' diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h index 405fd43487..82d65b37b6 100644 --- a/src/include/libpq/auth.h +++ b/src/include/libpq/auth.h @@ -19,6 +19,7 @@ extern char *pg_krb_server_keyfile; extern bool pg_krb_caseins_users; extern char *pg_krb_realm; +extern bool cluster_owner_bypass_auth; extern void ClientAuthentication(Port *port); diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index 270bd6c856..b42af2bd24 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -447,6 +447,7 @@ sub init print $conf "log_statement = all\n"; print $conf "log_replication_commands = on\n"; print $conf "wal_retrieve_retry_interval = '500ms'\n"; + print $conf "cluster_owner_bypass_auth = off\n"; # to enable testing hba etc. # If a setting tends to affect whether tests pass or fail, print it after # TEMP_CONFIG. Otherwise, print it before TEMP_CONFIG, thereby permitting base-commit: fded4773eb60541c6e7dbcf09c9bcb1cd36a063b -- 2.22.0