-
Notifications
You must be signed in to change notification settings - Fork 30
User authentication over secure connection #23
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
Conversation
- Consider and use the user id and password in DSN: - Feed these params to libcurl. The authentication mechansim is currently set to "any" (Elasticsearch seems to only support the HTTP Basic mechanism). - Change the initial connection testing to actually perform a query ("SELECT 0"), rather then a simple socket connection estiablishemnt check.
This should allow easier spotting of the build phases
- some test files still need migration to project's style
- configure the needed params for libcurl to be able to connect to a SSL-enabled Elasticsearch. This includes settings for: * checking the CA, hostname, revokation info; these params corespond to a "secure" connection string integer parameter. * reading a public CA file (if server's cert is not part of PKI). - register a debug call back to libcurl; - refactor part of HTTP request/response handling, covering also the initial connection test; - add a few "offline" unit test for a small part of the refactored code (the error handling).
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.
My main comments are about whether password should be optional in the config if username is specified. The other's are minor nits.
driver/connect.c
Outdated
ERRH(dbc, "libcurl: failed to enable host check."); | ||
goto err; | ||
} | ||
/* verify the revokation chain? */ |
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.
Even though "revoke" is spelt with a "k", "revocation" is spelt with a "c". English is very inconsistent.
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.
Thanks, will fix.
driver/connect.c
Outdated
res = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, | ||
/* libcurl (7.61.0) won't pick Basic auth over SSL when | ||
* _ANY is used. -- ??? XXX */ | ||
dbc->secure ? CURLAUTH_BASIC : CURLAUTH_ANY); |
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.
Given that basic auth is all ES supports, would it be safer to always use CURLAUTH_BASIC
in this code branch? If ES did ever add another method I think it would be preferable to have to change this code than to have it silently attempt to use some other authentication method with likely incorrect parameters.
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.
Libcurl will always try to use the safest method if more are available. Without SSL, the next best thing that Elasticsearch could add is Digest, which would work with the same given credentials.
So if that's ever going to be a possibility, ANY would be preferable here (in the unlikely scenario of an old driver, but new Elasticsearch).
In fact, "any" other case than Basic, that would also work would be preferable.
Now, given the fact that other and better mechanisms are available/worked on (Kerberos, LDAP), the chance of this case is rather small.
have it silently attempt to use some other authentication method with likely incorrect parameters.
I don't think there would be a lot of downside (in terms of auth data leakage, at least).
However: it's fixed to Basic if SSL is enabled (=99%+ of use cases, probably) and any change in available auth methods would require a change here too, so I'll fixed it. (I'll keep the note, though, since it cost me some time :-) )
driver/connect.c
Outdated
} | ||
if (secure < ESODBC_SEC_NONE || ESODBC_SEC_MAX <= secure) { | ||
ERRH(dbc, "invalid secure param `" LWPDL "` (not within %d - %d).", | ||
LWSTR(&attrs->secure), ESODBC_SEC_NONE, ESODBC_SEC_CHECK_HOST); |
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.
It might be more future-proof to use ESODBC_SEC_MAX - 1
rather than ESODBC_SEC_CHECK_HOST
, otherwise whoever adds a new enum value needs to remember to change this line too and if they forget then the code will still compile but the error message will be inaccurate.
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.
Good catch. Indeed, that was the intention of adding ESODBC_SEC_MAX
. Thanks.
attrs->uid.cnt, LWSTR(&attrs->uid)); | ||
goto err; | ||
} | ||
if (attrs->pwd.cnt) { |
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.
Is it traditional in ODBC drivers to treat a missing password setting as a password that is an empty string. I think that's what's being done here. The alternative would be to force the user to explicitly set the password setting if username was set, even if the password was an empty string. I doubt many people use empty passwords, so this might be a friendlier way to fail if we expect most cases of username set but password not set are due to people forgetting to set the password rather than not having one. (This idea also requires that it's possible to explicitly set the password setting to an empty string. If not then the way you've got it is the only way.)
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 was initially thinking that the standard doesn't necessarily require a non-empty password.
I now see that Elasticsearch'es API rejects an empty value Validation Failed: 1: passwords must be at least [6] characters long;
.
However, I would think that the right place for this check is (going to be) in the DSN configuration part (the pending GUI to add).
The user could still then edit the registry, true, but that would be a deliberate change, rather than accidental usage of a system unsecure by default.
The driver is pretty much just a proxy for information, rather then a gateway, so I'd think not enforcing it also here would be OK, but don't feel very strong about it. If you still think it's better to restrict it, I'll make the change.
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.
OK fair enough, but maybe you should make the INFOH(dbc, "no password for username
" LCPDL "."
on line 339 of connect.c
into a warning or error so that it is more prominent in the log file if the user ever does get into a situation where username is set but not pasword?
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.
Sure, it's logged as an error now.
driver/connect.c
Outdated
goto err; | ||
} | ||
} else { | ||
INFOH(dbc, "no password for username `" LCPDL "`.", |
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 left a comment in the bit where config options are copied to the database connection saying that if it's not possible in Elasticsearch to have a user without a password then it should be disallowed at the config reading stage. If that's the case then this should be changed to an assertion.
- removed the non-SSL case where _ANY would have been used. - fix a spelling error ('revokation'); - log the correct upper 'secure' (parameter) limit in error message.
- however, allow the call to proceed.
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.
LGTM
This PR adds support for user authenticated and secure connection to a server, both implemented through
libcurl
. A DB connection can now:The connection test part of a DSN validation now also includes a simple
SELECT 0
query, to check if user auth works and that a server with the SQL plug in is indeed running on the other side.The request/response handling has been also refactor to: (a) break the functionality into smaller function and (b) allow for libcurl's error to bubble up into the diagnostics eventually reported to the user.