Re: [PoC] Federated Authn/z with OAUTHBEARER
Jacob Champion <jchampion@timescale.com>
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
meson: Fix install-quiet after clean
- a9ffb35274fb 18.0 landed
- 4ae03be54734 19 (unreleased) landed
-
oauth: Run Autoconf tests with correct compiler flags
- 3d23f68c5529 18.0 landed
- 990571a08b66 19 (unreleased) landed
-
Link libpq with libdl if the platform needs that.
- 4df477153a6b 19 (unreleased) landed
- 7bd752c1fb8e 18.0 landed
-
Doc: correct spelling of meson switch.
- 3faac9d14063 16.9 landed
- 766d2e673342 17.5 landed
- ac557793d478 18.0 landed
-
oauth: Correct SSL dependency for libpq-oauth.a
- 3db68212a393 18.0 landed
-
oauth: Fix Autoconf build on macOS
- 4ea1254f35b2 18.0 cited
-
oauth: Move the builtin flow into a separate module
- b0635bfda053 18.0 landed
-
Remove a stray "pgrminclude" annotation
- 764d501d24ba 18.0 cited
-
oauth: Simplify copy of PGoauthBearerRequest
- 1cf4c56480f8 18.0 landed
-
oauth: Improve validator docs on interruptibility
- 873c0fd67872 18.0 landed
-
oauth: Disallow synchronous DNS in libcurl
- d7e40845f923 18.0 landed
-
oauth: Fix postcondition for set_timer on macOS
- 434dbf6907ec 18.0 landed
-
oauth: Use IPv4-only issuer in oauth_validator tests
- 8d9d5843b55f 18.0 landed
-
Work around OAuth/EVFILT_TIMER quirk on NetBSD.
- c301a0a74a8a 18.0 landed
-
oauth: Fix incorrect const markers in struct
- 03366b61dfe5 18.0 landed
-
Add missing entry to oauth_validator test .gitignore
- 2c53dec7f440 18.0 landed
-
cirrus: Temporarily fix libcurl link error
- 9d9a71002a1c 18.0 landed
-
Add support for OAUTHBEARER SASL mechanism
- b3f0be788afc 18.0 landed
-
libpq: Handle asynchronous actions during SASL
- a99a32e43ed7 18.0 landed
-
require_auth: prepare for multiple SASL mechanisms
- f8d8581ed882 18.0 landed
-
Move PG_MAX_AUTH_TOKEN_LENGTH to libpq/auth.h
- e21d6f297158 18.0 landed
-
Make SASL max message length configurable
- 6d16f9debae0 18.0 landed
-
jsonapi: fully initialize dummy lexer
- 41b023946dfd 18.0 landed
-
common/jsonapi: support libpq as a client
- 0785d1b8b2fa 18.0 landed
-
Remove fe_memutils from libpgcommon_shlib
- f1976df5eaf2 18.0 landed
-
Revert ECPG's use of pnstrdup()
- f0096ef13be2 13.17 landed
- 3557185538fe 14.14 landed
- 2de129b356bf 15.9 landed
- ee2997c678d8 16.5 landed
- e9e05c655069 17.0 landed
- 5388216f6adc 18.0 landed
-
Explicitly require password for SCRAM exchange
- adcdb2c8dda4 17.0 landed
-
Refactor SASL exchange to return tri-state status
- 24178e235ea5 17.0 landed
Attachments
- since-v7.diff.txt (text/plain)
- v8-0001-common-jsonapi-support-FRONTEND-clients.patch.gz (application/gzip) patch v8-0001
- v8-0002-libpq-add-OAUTHBEARER-SASL-mechanism.patch.gz (application/gzip) patch v8-0002
- v8-0003-backend-add-OAUTHBEARER-SASL-mechanism.patch.gz (application/gzip) patch v8-0003
- v8-0004-Add-pytest-suite-for-OAuth.patch.gz (application/gzip) patch v8-0004
- v8-0005-squash-Add-pytest-suite-for-OAuth.patch.gz (application/gzip) patch v8-0005
On 4/27/23 10:35, Jacob Champion wrote: > Moving forward, the first thing I plan to tackle is asynchronous > operation, so that polling clients can still operate sanely. If I can > find a good solution there, the conversations about possible extension > points should get a lot easier. Attached is patchset v8, now with concurrency and 300% more cURL! And many more questions to answer. This is a full reimplementation of the client-side OAuth flow. It's an async-first engine built on top of cURL's multi handles. All pending operations are multiplexed into a single epoll set (the "altsock"), which is exposed through PQsocket() for the duration of the OAuth flow. Clients return to the flow on their next call to PQconnectPoll(). Andrey and Mahendrakar: you'll probably be interested in the conn->async_auth() callback, conn->altsock, and the pg_fe_run_oauth_flow entry point. This is intended to be the foundation for alternative flows. I've kept the blocking iddawc implementation for comparison, but if you're running the tests against it, be aware that the asynchronous tests will, predictably, hang. Skip them with `py.test -k 'not asynchronous'`. = The Good = - PQconnectPoll() is no longer indefinitely blocked on a single connection's OAuth handshake. (iddawc doesn't appear to have any asynchronous primitives in its API, unless I've missed something crucial.) - We now have a swappable entry point. Alternative flows could be implemented by applications without forcing clients to redesign their polling loops (PQconnect* should just work as expected). - We have full control over corner cases in our default flow. Debugging failures is much nicer, with explanations of exactly what has gone wrong and where, compared to iddawc's "I_ERROR" messages. - cURL is not a lightweight library by any means, but we're no longer bundling things like web servers that we're not going to use. = The Bad = - Unsurprisingly, there's a lot more code now that we're implementing the flow ourselves. The client patch has tripled in size, and we'd be on the hook for implementing and staying current with the RFCs. - The client implementation is currently epoll-/Linux-specific. I think kqueue shouldn't be too much trouble for the BSDs, but it's even more code to maintain. - Some clients in the wild (psycopg2/psycopg) suppress all notifications during PQconnectPoll(). To accommodate them, I no longer use the noticeHooks for communicating the user code, but that means we have to come up with some other way to let applications override the printing to stderr. Something like the OpenSSL decryption callback, maybe? = The Ugly = - Unless someone is aware of some amazing Winsock magic, I'm pretty sure the multiplexed-socket approach is dead in the water on Windows. I think the strategy there probably has to be a background thread plus a fake "self-pipe" (loopback socket) for polling... which may be controversial? - We have to figure out how to initialize cURL in a thread-safe manner. Newer versions of libcurl and OpenSSL improve upon this situation, but I don't think there's a way to check at compile time whether the initialization strategy is safe or not (and even at runtime, I think there may be a chicken-and-egg problem with the API, where it's not safe to check for thread-safe initialization until after you've safely initialized). = Next Steps = There are so many TODOs in the cURL implementation: it's been a while since I've done any libcurl programming, it all needs to be hardened, and I need to comb through the relevant specs again. But I don't want to gold-plate it if this overall approach is unacceptable. So, questions for the gallery: 1) Would starting up a background thread (pooled or not) be acceptable on Windows? Alternatively, does anyone know enough Winsock deep magic to combine multiple pending events into one (selectable!) socket? 2) If a background thread is acceptable on one platform, does it make more sense to use one on every platform and just have synchronous code everywhere? Or should we use a threadless async implementation when we can? 3) Is the current conn->async_auth() entry point sufficient for an application to implement the Microsoft flows discussed upthread? 4) Would we want to try to require a new enough cURL/OpenSSL to avoid thread safety problems during initialization, or do we need to introduce some API equivalent to PQinitOpenSSL? 5) Does this maintenance tradeoff (full control over the client vs. a large amount of RFC-governed code) seem like it could be okay? Thanks, --Jacob