On Wed, Jan 22, 2025 at 6:10 AM Matheus Alcantara <matheusssil...@gmail.com> wrote: > The attached patch enables SCRAM authentication for dblink connections when > using dblink_fdw without requiring a plain-text password on user mapping > properties. The implementation is very similar to what was implemented on > postgres_fdw [0].
Not a full review, but I wanted to highlight one aspect of the patch: > - dblink_connstr_check(connstr); > + /* > + * Verify the set of connection parameters only if scram pass-through is > + * not being used because the password is not necessary. > + */ > + if (!useScramPassthrough) > + dblink_connstr_check(connstr); and > - dblink_security_check(conn, rconn, connstr); > + /* > + * Perform post-connection security checks only if scram pass-through is > + * not being used because the password is not necessary. > + */ > + if (!useScramPassthrough) > + dblink_security_check(conn, rconn, connstr); These don't seem right to me. SCRAM passthrough should be considered as _part_ of the connstr/security checks, but I think it should not _bypass_ those checks. We have to enforce the use of the SCRAM credentials on the remote for safety, similarly to GSS delegation. (This might be a good place for `require_auth=scram-sha-256`?) I've attached a failing test to better illustrate what I mean. It looks like the postgres_fdw patch that landed also performs a bypass -- I think that may need an open item to fix? CC'd Peter. Thanks! --Jacob
diff --git a/contrib/dblink/t/001_auth_scram.pl b/contrib/dblink/t/001_auth_scram.pl index 00fd6d85833..58c924f9aff 100644 --- a/contrib/dblink/t/001_auth_scram.pl +++ b/contrib/dblink/t/001_auth_scram.pl @@ -56,8 +56,21 @@ my $rolpassword = $node1->safe_psql('postgres', qq"SELECT rolpassword FROM pg_authid WHERE rolname = '$user';"); $node2->safe_psql('postgres', qq"ALTER ROLE $user PASSWORD '$rolpassword'"); -setup_pghba($node1); -setup_pghba($node2); +unlink($node1->data_dir . '/pg_hba.conf'); +unlink($node2->data_dir . '/pg_hba.conf'); + +$node1->append_conf( + 'pg_hba.conf', qq{ +local db0 all scram-sha-256 +local db1 all scram-sha-256 +}); +$node2->append_conf( + 'pg_hba.conf', qq{ +local db2 all scram-sha-256 +}); + +$node1->restart; +$node2->restart; # End of test setup @@ -67,6 +80,45 @@ test_fdw_auth($node1, $db0, "t", $fdw_server, test_fdw_auth($node1, $db0, "t2", $fdw_server2, "SCRAM auth on a different database cluster must succeed"); +# Ensure that trust connections fail without superuser opt-in. +unlink($node1->data_dir . '/pg_hba.conf'); +unlink($node2->data_dir . '/pg_hba.conf'); + +$node1->append_conf( + 'pg_hba.conf', qq{ +local db0 all scram-sha-256 +local db1 all trust +}); +$node2->append_conf( + 'pg_hba.conf', qq{ +local db2 all trust +}); + +$node1->restart; +$node2->restart; + +my ($ret, $stdout, $stderr) = $node1->psql( + $db0, + "SELECT * FROM dblink('$fdw_server', 'SELECT * FROM t') AS t(a int, b int)", + connstr => $node1->connstr($db0) . " user=$user"); + +is($ret, 3, 'loopback trust fails on the same cluster'); +like( + $stderr, + qr/password or GSSAPI delegated credentials required/, + 'expected error from loopback trust (same cluster)'); + +($ret, $stdout, $stderr) = $node1->psql( + $db0, + "SELECT * FROM dblink('$fdw_server2', 'SELECT * FROM t2') AS t2(a int, b int)", + connstr => $node1->connstr($db0) . " user=$user"); + +is($ret, 3, 'loopback trust fails on a different cluster'); +like( + $stderr, + qr/password or GSSAPI delegated credentials required/, + 'expected error from loopback trust (different cluster)'); + # Helper functions sub test_fdw_auth @@ -84,21 +136,6 @@ sub test_fdw_auth is($ret, '10', $testname); } -sub setup_pghba -{ - my ($node) = @_; - - unlink($node->data_dir . '/pg_hba.conf'); - $node->append_conf( - 'pg_hba.conf', qq{ - local all all scram-sha-256 - host all all $hostaddr/32 scram-sha-256 - host all all ::1/128 scram-sha-256 - }); - - $node->restart; -} - sub setup_user_mapping { my ($node, $db, $fdw) = @_;