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

Reply via email to