Re: Continuous re-validation of session credentials

From: Jakub Wartak <jakub(dot)wartak(at)enterprisedb(dot)com>
To: Ajit Awekar <ajitpostgres(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Jacob Champion <jacob(dot)champion(at)enterprisedb(dot)com>, Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com>, Daniel Gustafsson <daniel(at)yesql(dot)se>
Subject: Re: Continuous re-validation of session credentials
Date: 2026-10-14 11:28:30
Message-ID: CAKZiRmzn4DgE03cAoMCMqhz+xKtM4ZxbhdHTg1GM2sZEDa4fwA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, Sep 29, 2026 at 2:12 PM Ajit Awekar <ajitpostgres(at)gmail(dot)com> wrote:
>
> Thanks a lot Jakub for the detailed review.
>
> 1. Repeated errors resetting the timeout. Fixed: the next-validation
> deadline is now tracked independently of disable_all_timeouts(); error
> recovery re-arms at that same deadline instead of granting a fresh
> interval.
>
> 2. Superuser silently disables validation. Fixed: the two GUCs are now
> PGC_SU_BACKEND, not PGC_SUSET — settable only at session start, not via
> SET afterward. Rationale documented in config.sgml
>
> 3. Logical replication skipping validation. Confirmed and fixed. The
> walsender skip was unconditional; now scoped to
> AmWalSenderProcess() && !am_db_walsender, so only physical replication
> stays exempt. A logical walsender's streaming loop is serviced by a new
> hook alongside the existing config-reload handling. New regression test
> added, plus manual verification against an actively-streaming
> pg_recvlogical session.
>
> 4. Idle sessions are not terminated in real time. Fixed: validation also
> runs from the idle-wait point (ProcessClientReadInterrupt()), not only
> at the next command boundary.
>
> 5. Test runtime (~57s/~23s). Down to ~22-30s by consolidating
> independent scenarios into shared validation windows, without
> shortening any timeout/interval values.
>
> 6. "CVT" unexplained. Comment added: CVT_ = CredentialValidationType.
>
> 7. Insufficient log detail. Each validator now logs specifics via
> errdetail_log() (which check, which user, why).
>
> 8. Combined auth methods (clientcert=verify-full alongside
> scram-sha-256). Fixed: the client cert is now explicitly re-checked
> whenever the HBA line required one, regardless of the primary method's
> validator.
>
> 9. CRL revocation never rechecked mid-session. Fixed for the core case
> (ssl_crl_file, rechecked periodically). Two related items are
> deliberately out of scope, now documented in config.sgml:
> intermediate-CA revocation (the initial handshake already validates the
> full chain) and ssl_crl_dir (not consulted by the periodic recheck).
>
> 10. PAM is not addressed yet proposing to keep it out of
> scope as a follow-up patch
>
> Please find the attached V3 patchset. Request a review.

Hi Ajit, this is just about v3-0002 TLS tests mainly, I haven't looked
at the code of v3 yet nor verified the above, but for now:

0. As it stands this won't even compile with v3-0001 applied alone, it
complains with:

../src/backend/libpq/auth-validate-methods.c: In function
‘ValidateRoleValidity’:
../src/backend/libpq/auth-validate-methods.c:58:17: warning:
implicit declaration of function
‘SetCredentialValidationFailureDetail’
[-Wimplicit-function-declaration]
58 | SetCredentialValidationFailureDetail("role
validity check failed for user \"%s\": role no longer exists",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SetCredentialValidationFailureDetail() is defined later in v3-0002

../src/backend/libpq/auth-validate-methods.c:59:114: error: invalid
use of undefined type ‘struct Port’
59 |
MyProcPort ? MyProcPort->user_name :
"?");

it's because +#include "libpq/libpq-be.h" is missing in v3-0001

1. The cfbot complains that thing won't fly on Windows (both MSVC and mingw),
so I've started looking if I can repro 005_cert_continuous_validation:

# Running: pg_ctl --pgdata
D:/a/postgres-cfbot/postgres-cfbot/build/testrun/ssl/005_cert_continuous_validation/data/t_005_cert_continuous_validation_main_data/pgdata
--mode immediate stop
waiting for server to shut down.............. failed
pg_ctl: server does not shut down
# pg_ctl stop failed: 256
# Stale postmaster.pid file for node "main": PID 7204 no longer exists
[00:08:07.665](11.073s) # Looks like your test exited with 25 just after 3.
Warning: unable to close filehandle GEN6 properly: Bad file
descriptor during global destruction.
Warning: unable to close filehandle GEN11 properly: Bad file
descriptor during global destruction.

1b.Dunno what's happening in the above, because I've got even different error
in my env at first:

[10:18:38.476](0.347s) # === Test 1: pure client-certificate
authentication ===
# Running: openssl req -new -key
C:/git/postgres-public-ci/src/test/ssl/ssl/client.key -subj
/CN=ssltestuser -out
C:\git\postgres-public-ci\build\testrun\ssl\005_cert_continuous_validation\data\tmp_test_cK2y/short1.csr
Can't open "Z:/extlib/_5040x__/ssl\/openssl.cnf" for reading, No
such file or directory
30070000:error:80000003:system library:BIO_new_file:No such
process:crypto/bio/bss_file.c:67:calling
fopen(Z:/extlib/_5040x__/ssl\/openssl.cnf, r)
30070000:error:10000080:BIO routines:BIO_new_file:no such
file:crypto/bio/bss_file.c:75:

the issue seems to be that there seems to be no "-config" in openssl in
that new mint function for openssl req and at least here for some reason
this distribtution of OpenSSL tries to use some arbirary non-existent path
and fails (Z:\)

1c.Then I've got the similiar error as cfbot:
Running: openssl ca -batch -notext -config
C:\git\postgres-public-ci\build\testrun\ssl\005_cert_continuous_validation\data\tmp_test__8AE/ca.config
-name short_client_ca -startdate 0261014101030Z -enddate
20261014101545Z -in
C:\git\postgres-public-ci\build\testrun\ssl\005_cert_continuous_validation\data\tmp_test__8AE/short1.csr
-out C:\git\postgres-public-i\build\testrun\ssl\005_cert_continuous_validation\data\tmp_test__8AE/short1.crt
[..]
Write out database with 1 new entries
Database updated
[11:15:30.186](0.150s) # die: process ended prematurely at
C:/git/postgres-public-ci/src/test/perl/PostgreSQL/Test/BackgroundPsql.pm
line 163.
[11:15:30.187](0.000s) 1..3
[..]
# Stale postmaster.pid file for node "main": PID 7080 no longer exists
[11:15:41.442](11.255s) # Looks like your test exited with 25 just after 3.
Warning: unable to close filehandle GEN5 properly: Bad file
descriptor during global destruction.
Warning: unable to close filehandle GEN10 properly: Bad file
descriptor during global destruction.

so it's just all noise because pg log has:

2026-10-14 11:15:30.178 BST client backend[3588] [unknown] LOG:
connection received: host=DESKTOP-485UKSK port=52761
2026-10-14 11:15:30.186 BST client backend[3588] [unknown] FATAL:
connection requires a valid client certificate

so the whole setup just didn't work out? It looks like somehow the 005 even
the "test1" (short1) CA setup didn't even connect in the first place? (it was
not valid from start?)

2. Which brought me to this summary: I think the whole
005_cert_continuous_validation.pl test should be somehow refactored:
the other ssl tests simply rely on already generated/existing CA and mostly
nothing is generated in the tests runtime (see ../sslfiles.mk and somehow
use sslconfig.conf (that's ncluded from postgresql.conf). I'm not expert on
that, but test possibly could be much easier to follow/debug/understand if
it used generic parts of ssl testing infrastructure and just generate
CRL where necessary instead of repeating whole openssl config/CA setup
thing, which causes those portability issues above, but YMMV.

-J.

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Fujii Masao 2026-10-14 11:36:26 Re: Fix doc: explanation of how postgres works when OOM killer is invoked
Previous Message Chao Li 2026-10-14 11:16:38 Fix numeric log() with an infinite value and 0<base<=1