New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GSS/KRB5 Encryption support when connecting to a backend server #743
base: master
Are you sure you want to change the base?
Add GSS/KRB5 Encryption support when connecting to a backend server #743
Conversation
more implementation of gssenc
FYI you have to configure it thus, after installing the relevant krb5 dev package(s) depending on distro: ./configure --with-server-gssenc You can see all the details in my test bench (KDC included), I forgot I already committed most of this: |
Some testing details (I took from the PostgreSQL Kerberos test suite; slow because I'm running in the debugger on my local machine):
|
I haven't looked much at the code and I'm not really familiar with GSSAPI/Kerberos. In any case this needs some tests in the test suite. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs tests before I can look at it further
Will work on the tests more this coming week. |
I've got the testing working. |
@JelteF PTAL |
I'll try to take a look in the somewhat near future, but it's a big enough PR that it'll take me some time to review. |
|
@JelteF PTAL - I've posted a bunch of documentation about the patch |
@JelteF is this still on the radar? It would be really unfortunate for this branch to get so far out of sync with the main branch that it is too difficult to merge. I work at Astronomer, same place that @coryastronomer worked. I understand that this is a large PR and takes time to go through, and I wouldn't want you to take any shortcuts on reviewing it, but at the same time this is an enterprise feature that was high priority enough that we hired somebody specifically to implement it, and it would be a shame for that to go to waste. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry that it took so long to actually take a look at this PR. Thanks a lot for this work. I now took some time to go over the new code and left a few small comments. But the main thing that I'm thinking is that this is quite complex code and it's hard to review. Especially since I have pretty much zero knowledge on how GSS actually works.
I think the problem of me being unable to review everything is relatively easy to work around though. Because what I can fairly easily review is the changes needed to go from the GSS implementation in libpq implementation to the implementation in PgBouncer. Lots of the code is clearly copied from fe-secure-gssapi.c
in the Postgres codebase. I think if we structure the PR in the following way I will actually be able to review it:
- Create a single commit in which we create an
sbuf_gssapi.c
file which is an exact copy offe-secure-gssapi.c
- Do any changes necessary to make this code work with PgBouncer on top of that.
Afaict this would greatly reduce the amount of code that's needed to review. And the code that needs to be reviewed would mostly be code specific to PgBouncer, instead of code specific to GSSAPI.
;; disable, allow, require | ||
;server_gssencmode = disable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
;; disable, allow, require | |
;server_gssencmode = disable | |
;; disable, prefer, require | |
;server_gssencmode = prefer |
@@ -29,6 +29,8 @@ | |||
#include <usual/safeio.h> | |||
#include <usual/slab.h> | |||
|
|||
//#include <postgresql/libpq-fe.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be removed
CF_ABS("server_idle_timeout", CF_TIME_USEC, cf_server_idle_timeout, 0, "600"), | ||
CF_ABS("server_gssencmode", CF_LOOKUP(gssencmode_map), cf_server_gssencmode, 0, "prefer"), /* libpq default */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Items in this list are ordered alphabetically
CF_ABS("server_idle_timeout", CF_TIME_USEC, cf_server_idle_timeout, 0, "600"), | |
CF_ABS("server_gssencmode", CF_LOOKUP(gssencmode_map), cf_server_gssencmode, 0, "prefer"), /* libpq default */ | |
CF_ABS("server_gssencmode", CF_LOOKUP(gssencmode_map), cf_server_gssencmode, 0, "prefer"), /* libpq default */ | |
CF_ABS("server_idle_timeout", CF_TIME_USEC, cf_server_idle_timeout, 0, "600"), |
} else if (!!gssapi_spn != !!db->gssapi_spn | ||
|| (gssapi_spn && strcmp(gssapi_spn, db->gssapi_spn) != 0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's now the strings_equal
function in the codebase to do this check.
@@ -1242,6 +1282,7 @@ static int tls_sbufio_close(struct SBuf *sbuf) | |||
return 0; | |||
} | |||
|
|||
// TODO: handle gssapi somehow, respecting macros etc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's up with this TODO? What needs to still happen here?
@@ -0,0 +1,223 @@ | |||
#! /bin/sh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the tests should be rewritten to the python testing framework. But before doing that lets first focus on the new code itself.
{ | ||
log_noise("gss_close"); | ||
if (sbuf->gss) { | ||
// TODO: free gss memory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seemingly important TODO
Hello, we have used this code to successfully connect to a GSSAPI/Kerberos authenticated and encrypted PostgreSQL server from pgbouncer, while allowing a non-GSSAPI/Kerberos client to avail itself of a kerberized PostgreSQL in addition to the other pgbouncer functions.
I added a couple fields to pgbouncer.ini:
server_gssencmode (need to flesh this out; I should be able to do that this week; the goal is to allow requiring GSSAPI authentication and encryption from pgbouncer's side, not just having "hostgssenc" in pg_hba.conf)
gssapi_spn (GSSAPI/Kerberos Service Principal Name; per-database in [databases] section)
I initially created a synchronized I/O version of this patch. Right now sending/receiving data is asynchronous I/O except for the initial connection. I could probably re-engineer that at some point. Most of the async code is a modified copy of how libpq does a GSSAPI Authenticated+Encrypted connection. I considered using the libpq-fe.h API directly but it doesn't seem to be a great match for pgbouncer as-is. I imagine there is some history related to libpq that I'm not aware of.
At this time it does not support, say, making a server connection with GSSAPI auth alone or with any other method (i.e. TLS). It does not add any abilities to client connections.
I have this working in both Vagrant and docker-compose with a minimal KDC; after some cleanup I should be able to share those as well, for automated testing purposes.
I am sure there are bugs and some rough edges in the code, but so far I can't get my connections to fail or crash. I'd be happy to help smooth anything out, if this patch is of any value to the community.
N.B. So far I've only tested with pkt_buf = 16384; per the postgresql.org spec, that is how long GSSAPI encrypted messages can be.