| From: | Ajit Awekar <ajitpostgres(at)gmail(dot)com> |
|---|---|
| To: | 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-09-17 12:01:41 |
| Message-ID: | CAER375N35XAWLhAiokyVs65bFQgq_n_=LgNs61o+ZtYdEmPEqw@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi Hackers,
Attached is v2 of the series, with three fixes folded into 0001 (no
changes to 0002-0005):
1. Standby servers
CheckCredentialValidity() no longer skips validation under
RecoveryInProgress(). Hot-standby sessions run continuously "in
recovery", so this was silently disabling the feature for read
replicas -- all the checks involved are read-only/local, so
there's no reason to exclude them.
2. Set Session Authorization
ValidateRoleValidity() now checks GetAuthenticatedUserId()
instead of GetSessionUserId(), so a superuser can't mask the
login role's expiry/removal by switching session authorization.
This also keeps it consistent with the method-specific
validators, which always check the fixed login identity. Added
regression coverage.
3. Walsenders
EnableCredentialValidationTimeout() and CheckCredentialValidity()
now explicitly skip AmWalSenderProcess()
Request a review.
Thanks & Best Regards,
Ajit
On Wed, 1 Jul 2026 at 17:45, Ajit Awekar <ajitpostgres(at)gmail(dot)com> wrote:
> Hi,
>
> Following up on the ongoing work for continuous credential validation, I
> would like to propose the next two patches in the series.
>
> These patches extend the continuous validation framework to handle both
> GSSAPI/Kerberos and LDAP (Search+Bind) authenticated sessions.
> Patch 4/5: Add GSS credential expiry to credential validation
>
> This patch introduces method-specific validation for GSSAPI/Kerberos
> sessions (CVT_GSS).The GSS security context established at authentication
> carries a lifetime derived from the client's Kerberos ticket. We introduce
> a helper be_gssapi_get_context_expired() which utilizes gss_context_time()
> on the acceptor context retained on the Port. This is a purely local
> check that requires no round-trip to the KDC. If the context lifetime has
> elapsed, the session is safely terminated.
>
>
> postgres=> select system_user;
> system_user
> -----------------------
> gss:test1(at)EXAMPLE(dot)COM
> (1 row)
>
> postgres=> select current_user;
> current_user
> --------------
> test1
>
> postgres=> select current_time;
> FATAL: session credentials have expired
> HINT: Please reconnect to establish a new authenticated session.
> server closed the connection unexpectedly
> This probably means the server terminated abnormally
> before or while processing the request.
> The connection to the server was lost. Attempting reset: Failed.
> The connection to the server was lost. Attempting reset: Failed.
>
> (1 row)
>
> Patch 5/5: Add LDAP account-existence check to credential validation
>
> This patch adds validation support for LDAP sessions (CVT_LDAP).
>
> Unlike token- or certificate-based authentication, an LDAP session does
> not retain a credential with an intrinsic expiry date. Instead, "validity"
> is defined as the account's continued existence within the directory.
>
> During each validation cycle, the backend connects and re-binds using the
> configured search credentials (ldapbinddn / ldapbindpasswd), then re-runs
> the configured search filter. If the search yields exactly zero entries,
> the account is considered deleted or disabled, and the session is
> terminated.
>
>
> postgres=> SELECT current_user;
> current_user
> --------------
> test1
> (1 row)
>
> postgres=> select system_user;
> system_user
> ----------------------------------
> ldap:uid=test1,dc=example,dc=net. <= After this I fired ldapdelete and got validation error on next validation cycle
> (1 row)
>
> postgres=> select current_time;
> FATAL: session credentials have expired
> HINT: Please reconnect to establish a new authenticated session.
> server closed the connection unexpectedly
> This probably means the server terminated abnormally
> before or while processing the request.
> The connection to the server was lost. Attempting reset: Failed.
> The connection to the server was lost. Attempting reset: Failed.
>
> (1 row)
>
> Thanks & Best regards,
>
> Ajit
>
> On Fri, 26 Jun 2026 at 11:21, Ajit Awekar <ajitpostgres(at)gmail(dot)com> wrote:
>
>> Hi,
>>
>> Attached is v2 of the patch set, rebased on the current master.
>>
>> The only functional change from the previous version is a fix for the
>> cfbot failure. The earlier version src/test/modules/test_misc/t/
>> 003_check_guc.pl
>> due to the tab in the trailing spaces.
>>
>> Thanks & Best Regards,
>> Ajit
>>
>>
>> On Tue, 16 Jun 2026 at 17:44, Ajit Awekar <ajitpostgres(at)gmail(dot)com> wrote:
>>
>>> Hi,
>>>
>>> Today PG validates a client's credentials only once, at connection
>>> time. After that the backend runs until the client disconnects, even if
>>> the
>>> basis for the original authentication decision has gone away. In
>>> particular:
>>>
>>> - the role's VALID UNTIL passes, or the role is dropped (ALTER ROLE
>>> ...
>>> VALID UNTIL / DROP ROLE);
>>> - the OAuth bearer token the session authenticated with expires;
>>> - the TLS client certificate the session authenticated with reaches
>>> its
>>> notAfter date.
>>>
>>> In all of these cases a long-lived session keeps running with
>>> credentials that
>>> would be rejected on a fresh connection. For environments with
>>> short-lived
>>> credentials (OAuth tokens, short-lived certs, time-boxed accounts) this
>>> is a
>>> real gap: revoking access has no effect on already-established sessions.
>>>
>>> This patch series adds an optional mechanism to periodically re-validate
>>> the
>>> credentials of an active session and terminate it (FATAL) once they are
>>> no
>>> longer valid.
>>>
>>> A per-backend timer (CREDENTIAL_VALIDATION_TIMEOUT) fires every
>>> credential_validation_interval seconds and sets a pending flag.
>>>
>>> Validation has two layers:
>>> - A baseline, auth-method-independent check (role still exists and
>>> has not
>>> passed rolvaliduntil), applied to every authenticated session.
>>> - Optional method-specific validators, registered via
>>> RegisterCredentialValidator(), for OAuth token expiry and client
>>> certificate expiry.
>>>
>>> The framework is deliberately extensible: adding re-validation for a new
>>> authentication method needs only three small steps -- add a
>>> CredentialValidationType, implement a "bool validator(void)" callback
>>> that
>>> returns whether the credential is still valid, and register it with
>>> RegisterCredentialValidator(). The certificate and OAuth validators in
>>> 0002
>>> and 0003 are themselves examples of plugging into the framework this
>>> way,
>>> so methods such as LDAP, RADIUS, or GSSAPI/Kerberos credential
>>> lifetimes
>>> could be added later without touching the core.
>>>
>>> Two GUCs :
>>> credential_validation_enabled (bool, default off)
>>> credential_validation_interval (int, 5..3600 s, default 60)
>>>
>>> Patch series
>>> ------------
>>>
>>> 0001 Framework + baseline role-validity check (rolvaliduntil / role
>>> existence). Useful on its own for password/md5/scram sessions.
>>> 0002 TLS client certificate expiry. The cert presented at connect
>>> time is
>>> retained on the Port, so its notAfter is re-checked locally with
>>> no
>>> network round-trip.
>>> 0003 OAuth token expiry. This adds an optional expire_cb callback to
>>> OAuthValidatorCallbacks; to stay ABI-compatible the validator
>>> magic is
>>> versioned (V1 = existing layout, V2 = adds expire_cb), and the
>>> server
>>> accepts both.
>>>
>>> Request a review.
>>>
>>>
>>> Thanks & Best Regards,
>>> Ajit
>>>
>>>
>>>
| Attachment | Content-Type | Size |
|---|---|---|
| v2-0003-Add-OAuth-token-expiry-to-credential-validation.patch | application/octet-stream | 10.8 KB |
| v2-0005-Add-LDAP-account-existence-check-to-credential-valid.patch | application/octet-stream | 17.1 KB |
| v2-0001-Add-continuous-credential-validation-framework.patch | application/octet-stream | 41.3 KB |
| v2-0004-Add-GSS-credential-expiry-to-credential-validation.patch | application/octet-stream | 16.0 KB |
| v2-0002-Add-TLS-client-certificate-expiry-to-credential-vali.patch | application/octet-stream | 12.0 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Vik Fearing | 2026-09-17 12:04:42 | Re: ON EMPTY clause for aggregate and window functions |
| Previous Message | Hayato Kuroda (Fujitsu) | 2026-09-17 11:35:24 | RE: pgoutput: schema cache cleanup after streamed 2PC |