-
Notifications
You must be signed in to change notification settings - Fork 185
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
Unify ca_path and ca_file configuration parameters #4087
Conversation
This pull request has been linked to Shortcut Story #2768: Consolidate certificate configuration parameters, and ensure support in all backends. |
eeb846c
to
fce6483
Compare
905704f
to
3971b6c
Compare
3171b14
to
3390e47
Compare
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 we not consider this option on Windows? I don't think Windows suffers from the issues that necessitate application code customizing the trusted CA path; certificate management on Windows is managed by the system and the trusted root list is automatically updated via Windows update.
@teo-tsirpanis I'm not entirely sure I understand your comment. I think you're asking if we could disable the use of these configuration options on Windows because of the global certificate management that already exists. While I agree with the general sentiment that most users of most operating systems will never have a need for setting this options, there are plenty of valid use cases that do require them. |
abc7ddc
to
11ba60a
Compare
Yes that's what I meant. And looks like curl will ignore these parameters on Windows (and macOS) either way (also saw that you mentioned it in the issue's description):
But we could support |
3a0ebda
to
9064f4a
Compare
So, first off, I think the way to think of this PR is as an abstraction over a set of common library configuration parameters. There are three and each library supports some subset of those three. This PR happens to be related to TLS parameters, but it could just as easily be creating a unified TileDB configuration for HTTP retry semantics or some other common set of configuration parameters shared by each of our object store backends. Thinking of things in that light makes this PR extremely easy to reason about. We create three new TileDB configuration parameters and then plumb those values to the appropriate spots in each object store client library as appropriate where supported. With that framing, the only complexity is in the testing of these parameters being set or not and ensure we're not getting false positives in the test suite because something is configured weirdly. Everything else is super straightforward. Given that these are TLS parameters though, there are a number of things we could concern ourselves with, but shouldn't. A quick non-exhaustive list of things that come to mind:
For 1, there's an interesting case in the Azure library because it exposes both a libcurl and Windows backend transport on Windows. It took me a while to realize this was fine since Azure always includes the libcurl based transport. However, S3 does not use libcurl on Windows at all, it does however still expose the three configuration options in its API. For 2 and 3 which are closely related, we would have to specifically audit the port overlays, build systems, and feature interactions to ensure the same exact libcurl is used by all client libraries. And even then, we'd be relying on the client libraries not doing a runtime configuration to pick a non-default TLS backend. Number 4, not all libraries expose the same set of configuration options. In particular, GCS only exposes the
The bottom line here is that we can worry about these things (keeping them in mind when debugging client issues with TLS for instance), but there's no sense worrying about them for this PR because we really can't do anything about them in reality. Sure, if a customer finds a bug we can submit patches upstream, but its also not like we can monkeypatch our client libraries to ensure every platform is using a FIPS 140-3 compliant TLS implementation. So all of that is why I say its much easier to just think of this as "We take these TileDB configuration parameters and apply them to each client library, beyond that, its up to the library to do the right thing." |
Makes sense, thanks for the explanation! |
9064f4a
to
1d99bc8
Compare
d0f7bd1
to
d43f7cb
Compare
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, but let's get an ACK from @Shelnutt2 (and @teo-tsirpanis for azure) before merging.
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.
Added a few comments, mostly user experience concerns. Very nice work and the housekeeping bits here and there are very appreciated, thank you!
assert(state_ == State::UNINITIALIZED); | ||
|
||
thread_pool_ = thread_pool; | ||
|
||
bool found; | ||
endpoint_ = config.get("vfs.gcs.endpoint", &found); | ||
assert(found); | ||
if (endpoint_.empty() && getenv("TILEDB_TEST_GCS_ENDPOINT")) { |
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 this getenv
result ever be "" or we don't care?
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 don't think we care given its a TileDB specific test feature. There's a separate environment variable used by the GCS library for changing endpoints as well, so if folks do need to change it there's a standard way for doing it.
channel_options.set_ssl_root_path(cert_file); | ||
} | ||
if (!ssl_cfg_.ca_path().empty()) { | ||
LOG_WARN( |
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.
warning is nice here, thanks!
ss << "]"; | ||
} | ||
|
||
ss << " : " << err.GetMessage(); |
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, this will be much appreciated.
// configured by the user. | ||
|
||
// Only set ca_file_ if vfs.s3.ca_file is a non-empty string | ||
auto ca_file = cfg.get<std::string>("vfs.s3.ca_file"); |
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.
Do we have some sort of deprecation mechanism for these config options? Thinking from the user's perspective, when I'd search for options documentation/forums/slack/etc, I'd definitely get a few hits with the old options and I'd get pretty confused on which one of the ssl options would help me. I'm wondering whether we should signal somehow that those options are not to be used anymore (warning/docs comments).
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 see your point, and I have absolutely no idea on the docs side of things. I'd agree that at least adding notes to the s3 specific config variable docs would be useful though. As for how long until we drop the s3 variables, I'd assume that's a 3.x breaking change type of event.
bool ignore_ssl_validation = false; | ||
bool found; | ||
RETURN_NOT_OK(config_->get<bool>( | ||
"rest.ignore_ssl_validation", &ignore_ssl_validation, &found)); |
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.
Same as in the comment above, I understand we now support both for backwards compatibility, but do we want to keep this one around indefinitely in the future? If no, should we discourage users? can we clarify somehow that this was enhanced and replaced by another option so it doesn't get very confusion which option gets the job done?
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 don't think we should discourage the use. Though it occurs to me reading this second comment that maybe a LOG_WARN
about the new config variables might be useful? I.e., something like "Configuration $old_var can now be achieved using $new_var. Support for $old_var will be removed in the future."
d43f7cb
to
49910ea
Compare
tiledb/sm/filesystem/azure.cc
Outdated
} | ||
|
||
auto transport = | ||
make_shared<::Azure::Core::Http::CurlTransport>(HERE(), transport_opts); |
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.
This will cause the Curl transport to be used on Windows, which uses WinHTTP by default. Not sure if we care though; in default builds Curl will be used with serialization either 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.
It looks like the WinHTTPTransportOptions has two settings IgnoreUnknownCertificateAuthority
and IgnoreInvalidCertificateCommonName
which we could disable with ssl.verify = false
. However, there's no option for specifying a certificate chain so it'd end up like GCS in that we only have the one switch on Windows.
There's also TransportOptions::DisableTlsCertificateValidation
that is the more generic interface that we could use instead so that we don't care at all what Azure uses behind the curtain which seems slightly safer.
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 take that back. If we don't use the curl transport here we'll not be able to specify a ca_file option on Linux which defeats the entire point of the PR (at least for Azure). So we can either leave it as it is, or we can do a if constexpr
to pick the curl transport on not Windows and use the default version on Windows? Given it works fine on Windows as is, I'm inclined to leave it.
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 no option for specifying a certificate chain so it'd end up like GCS in that we only have the one switch on Windows.
As said in #4087 (comment) Windows will not honor ca_file
on curl.
or we can do a
if constexpr
to pick the curl transport on not Windows and use the default version on Windows?
I tried to find a comparison between libcurl and WinHTTP but to no avail. I found https://curl.se/libcurl/wininet.html which is for WinINet, another HTTP API. I am split on whether to use curl on Windows. Using it increases consistency among platforms, but not using it keeps the Azure SDK's defaults. Also the AWS SDK uses WinHTTP on Windows.
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.
Windows not honoring the ca_file
isn't really an issue since we're really only concerned that it works on Linux, specifically in Docker containers that might not have the ca_bundle package installed.
@ihnorton Have you got any good arguments for or against libcurl on Windows?
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 guess lean toward WinHTTP, but not a strong preference
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've updated the Azure adapter to use WinHTTP on Windows and the cURL adapter on !Windows. I ended up having to use the preprocessor though since the WinHTTP approach ends up attempting to include winhttp.h which makes things not work on !Windows.
e4ac6d8
to
815bf79
Compare
815bf79
to
e517a90
Compare
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.
Azure VFS looks good, thanks!
if (ssl_cfg.verify() == false) { | ||
transport_opts.IgnoreUnknownCertificateAuthority = true; | ||
} |
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.
if (ssl_cfg.verify() == false) { | |
transport_opts.IgnoreUnknownCertificateAuthority = true; | |
} | |
transport_opts.IgnoreUnknownCertificateAuthority = !ssl_cfg.verify(); |
if (ssl_cfg.verify() == false) { | ||
transport_opts.SslVerifyPeer = false; | ||
} |
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.
if (ssl_cfg.verify() == false) { | |
transport_opts.SslVerifyPeer = false; | |
} | |
transport_opts.SslVerifyPeer = ssl_cfg.verify(); |
This change creates unified configuration settings for ca_file and ca_path while also allowing backwards compatibility with the old `vfs.s3.ca_file`, `vfs.s3.ca_path`, and `rest.ignore_ssl_verification` settings. This adds three new configuration settings: * `ssl.ca_file` - Path to a PEM formatted certificate list * `ssl.ca_path` - Path to a directory of certificates * `ssl.verify` - A boolean indicating wether SSL peer verification should be enabled or not Not all VFS backends support all three options. Notably, the underlying cURL option that `ssl.ca_path` is used for (`CURLOPT_CAPATH`) is documented as not working on Windows. Options supported by each backend are: Azure --- * ssl.ca_file * ssl.verify GCS --- * ssl.ca_file S3 --- * ssl.ca_file * ssl.ca_path * ssl.verify TileDB Cloud --- * ssl.ca_file * ssl.ca_path * ssl.verify ~~I'm still working on trying to figure out how best to write test assertions that these configuration options have been set and are correctly used by the corresponding backends.~~ --- TYPE: IMPROVEMENT DESC: Unify ca_file and ca_path configuration parameters
This change creates unified configuration settings for ca_file and ca_path while also allowing backwards compatibility with the old
vfs.s3.ca_file
,vfs.s3.ca_path
, andrest.ignore_ssl_verification
settings.This adds three new configuration settings:
ssl.ca_file
- Path to a PEM formatted certificate listssl.ca_path
- Path to a directory of certificatesssl.verify
- A boolean indicating wether SSL peer verification should be enabled or notNot all VFS backends support all three options. Notably, the underlying cURL option that
ssl.ca_path
is used for (CURLOPT_CAPATH
) is documented as not working on Windows. Options supported by each backend are:Azure
GCS
S3
TileDB Cloud
I'm still working on trying to figure out how best to write test assertions that these configuration options have been set and are correctly used by the corresponding backends.TYPE: IMPROVEMENT
DESC: Unify ca_file and ca_path configuration parameters