-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[C++] Custom certificate verifier should not depend on presence of root certs #29667
Comments
I have rearranged the initialisation flow as following - I think it makes more sense in cases where there are no root certs readily available anywhere on the system and custom verifier will be present.
|
@ZhenLian ping |
Thanks for bringing up the issue. Please see my comments below.
Yes, I agree this can be improved with the current API, and someone raised a similar concern in an internal platform. We can definitely change the API to not require a fake root certs if "set_verify_server_certs" is false. Currently gRPC security team doesn't have bandwidth to work on this, but let's keep this open until this can be picked up.
To make sure I understand, you are proposing:
Our current behavior is: if
I am not sure I quite get your comment about "the boilerplate of dynamic provider". Would you mind elaborating that? |
For the code diff change, would you mind turning into a PR? It's a bit hard to follow right now... |
I will turn it into PR - my patch fixes the "set_verify_server_certs is false" issue as it is. The more general issue is indeed security. I'm coming from the position, that certificate validation should rely on the platform mandated method of doing so. Right now, the gRPC approach of loading a pemball is only compatible with Linux and BSD, and totally incompatible with everything else (unless user chooses to maintain their own pemball, which is a very problematic thing. To this end, I have implemented platform specific verifiers for OSX flavours (macos/ios), Windows and Android (with a JNI bridge). While Android is problematic, I can contribute the OSX and Windows verifiers, they are plain C++ files with a single "ifdef" for platform detection. I have borrowed the general approach from the Chromium code base. My API change proposal (it does need some further thinking) above comes from the following use pattern (I have in my actual production code):
By looking at such code, somebody may assume that we are not secure. But the contrary is true: we are quite secure, because we actually call the wincrypt api to comply with the platform policy (same on MacOS). I am forced to disable "basic verification" (as you call it) because on those systems we don't have any material to feed into the OpenSSL context. The certs are stored in the policy-guarded platform stores. |
…grpc#29667) Presently, when establishing a TLS connection, gRPC will always attempt to load some CA certificates from the file system or user supplied callback mechanism. However, on popular commercial platforms (MS Windows, Apple OSX) CA certificates are not readily available to be loaded as files. Therefore, requirement to always load the root certs creates a problem: 1. When custom, platform specific verifier is present. 2. When security is not an issue, but TLS connection is nevertheless required (various testing situations).
Pr created as #29810 |
Apologies that this got dropped. Just sent #34859 to fix the core issue, building on top of #29810. Note that we do not want |
In the current situation it explicitly must not be additive. Consider, for example, Windows or MacOS. To use the system certificate store (the right thing to do) I have to do something like:
Whereupon the There's no scenario whereupon some custom pem bundle should override the system policy. |
Thanks for clarifying @oakad. I think there are a couple of issues here:
|
Note that MacOS system trust store was added in #29957. |
I don't see it using |
TL;DR; I propose to make
grpc_tls_certificate_verifier
object, if set by user, an one and only authority on certificate validity. No messing with root cert/crl sets. Just the output ofgrpc_tls_certificate_verifier::Verify
to decide.This was to some extent discussed before, but the issue still applies, despite the refactoring of TLS code.
Consider a system such as OSX/IOS/Windows and to some extent Android which do not expose user certificates as a bunch of pem blobs in readable location (those easily amount to 90%+ of all client installations on this planet). All those systems provide a readily accessible API to verify peer certificate chains in a system dependent manner. In many cases it is critically important to comply with the system specific method of verification.
Right now we have the implementation referenced below.
The main issue with it: it does all the hard work trying to initialize the "root cert" verification set even if
set_verify_server_certs
is set to false. The check for this options happens rather late, so a lot of cycles are wasted for nothing (as verification will not be relying on those certs anyway).Nevertheless, we must provide some "root certs" for the current implementation to work at all. Moreover, we must maintain them in valid state, even though we know them to be non-functional.
Additionally, the naming of an option
set_verify_server_certs
is misleading in such scenarios. We don't want to disable verification, we want to delegate it.Thus, I think, it makes sense to drop the
set_verify_server_certs
option and instead simply check for presence of explicitly setgrpc_tls_certificate_verifier
. If it is set, no root set need to be populated and verification is fully delegated.This will also make
grpc_tls_certificate_provider
use case simpler. Right now, in cases where intermediate root certs are delivered via network (xds style thing) the boilerplate of dynamic provider is pretty bad. It's actually easier to put together a customX509_STORE_CTX
(or whatever runtime platform offers) explicitly in the verifier than jump around the provider.grpc/src/core/tsi/ssl_transport_security.cc
Lines 2073 to 2117 in adfd009
The text was updated successfully, but these errors were encountered: