Add an optional `target_name_override` to support multiple-endpoints with SSL. (#89)

Resolves #87.

Signed-off-by: Tao He <sighingnow@gmail.com>
This commit is contained in:
Tao He 2021-09-24 02:41:46 +08:00 committed by GitHub
parent 6eed82a766
commit a949dec288
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 5 deletions

View File

@ -238,6 +238,39 @@ transport security using openssl.
We also provide a tool [`setup-ca.sh`](./security-config/setup-ca.sh) as a helper for development and testing.
#### transport security & Multiple endpoints
If you want to use multiple `https://` endpoints, and you are working with self-signed certificates, you
may encountered errors like
```
error: 14: connections to all backends failing
```
That means your DNS have some problems with your DNS resolver and SSL authority, you could put a domain
name (a host name) to the `SANS` field when self-signing your certificate, e.g,
```
"sans": [
"etcd",
"127.0.0.1",
"127.0.0.2",
"127.0.0.3"
],
```
And pass a `target_name_override` arguments to `WithSSL`,
```cpp
etcd::Client *etcd = etcd::Client::WithSSL(
"https://127.0.0.1:2379,https://127.0.0.2:2479",
"example.rootca.cert", "example.cert", "example.key", "etcd");
```
For more discussion about this feature, see also [#87](https://github.com/etcd-cpp-apiv3/etcd-cpp-apiv3/issues/87),
[grpc#20186](https://github.com/grpc/grpc/issues/20186) and [grpc#22119](https://github.com/grpc/grpc/issues/22119).
### Reading a value
You can read a value with the `get()` method of the client instance. The only parameter is the

View File

@ -98,6 +98,7 @@ namespace etcd
std::string const & ca,
std::string const & cert,
std::string const & key,
std::string const & target_name_override,
std::string const & load_balancer);
/**
@ -108,12 +109,16 @@ namespace etcd
* @param ca root CA file for SSL/TLS connection.
* @param cert cert chain file for SSL/TLS authentication, could be empty string.
* @param key private key file for SSL/TLS authentication, could be empty string.
* @param target_name_override Override the target host name if you want to pass multiple address
* for load balancing with SSL, and there's no DNS. The @target_name_override@ must exist in the
* SANS of your SSL certificate.
* @param load_balancer is the load balance strategy, can be one of round_robin/pick_first/grpclb/xds.
*/
static etcd::Client *WithSSL(std::string const & etcd_url,
std::string const & ca,
std::string const & cert = "",
std::string const & key = "",
std::string const & target_name_override = "",
std::string const & load_balancer = "round_robin");
/**

View File

@ -239,6 +239,7 @@ etcd::Client::Client(std::string const & address,
std::string const & ca,
std::string const & cert,
std::string const & key,
std::string const & target_name_override,
std::string const & load_balancer)
{
// create channels
@ -249,6 +250,9 @@ etcd::Client::Client(std::string const & address,
std::shared_ptr<grpc::ChannelCredentials> creds = grpc::SslCredentials(
etcd::detail::make_ssl_credentials(ca, cert, key));
grpc_args.SetLoadBalancingPolicyName(load_balancer);
if (!target_name_override.empty()) {
grpc_args.SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, target_name_override);
}
this->channel = grpc::CreateCustomChannel(addresses, creds, grpc_args);
// setup stubs
@ -264,8 +268,9 @@ etcd::Client *etcd::Client::WithSSL(std::string const & etcd_url,
std::string const & ca,
std::string const & cert,
std::string const & key,
std::string const & target_name_override,
std::string const & load_balancer) {
return new etcd::Client(etcd_url, ca, cert, key, load_balancer);
return new etcd::Client(etcd_url, ca, cert, key, target_name_override, load_balancer);
}
pplx::task<etcd::Response> etcd::Client::head()