Elasticsearch.Nest 教程系列 2-4 连接:Working with certificates | 使用凭证连接

  • 本系列博文是“伪”官方文档翻译(更加本土化),并非完全将官方文档进行翻译,而是在查阅、测试原始文档并转换为自己真知灼见后的“准”翻译。有不同见解 / 说明不周的地方,还请海涵、不吝拍砖 :)

  • 官方文档见此:https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/introduction.html

  • 本系列对应的版本环境:ElasticSearch@7.3.1,NEST@7.3.1,IDE 和开发平台默认为 VS2019,.NET CORE 2.1


使用证书

如果你已经通过 Elastic Stack Security 功能在 Elasticsearch 上启用了SSL,或者在 ES 服务上层的代理上启用了SSL,并且生成证书的证书颁发机构(CA)受运行客户端代码的计算机信任,那么你不需要进行任何操作。

如果你使用不受信任的 CA 证书(如你自己生成的CA 证书),默认情况下, .NET 不允许你使用 https 请求终结点,不过你可以使用 ServicePointManager.ServerCertificateValidationCallback 来解决这个问题。大部分的示例可能会让你直接返回一个 true,但并不建议你这样做,因为这么设置会允许所有到你应用程序域的 HTTPS 的流量,且无需验证:

1
2
3
//不建议这么干:
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, errors) => true
  • 这么设置不会对 HTTPS 连接请求jinxing yanzheng

配置验证

可以使用 Elasticsearch.Net 的 ConnectionConfiguration 和使用 NEST 的ConnectionSettings 公开该回调。你也可以在这处理程序中进行自己的验证,也可以使用静态类 CertificateValidations 提供的一些处理器。

最常用的是 AllowAll 和 DenyAll,它们分别允许或拒绝到节点的所有 SSL 流量:

拒绝所有证书验证

eg:在 ConnectionSettings 上设置回调来拒绝所有证书验证:

1
2
3
4
5
6
7
[IntegrationOnly]
public class DenyAllCertificatesCluster : SslAndKpiXPackCluster
{
protected override ConnectionSettings ConnectionSettings(ConnectionSettings s) => s
.ServerCertificateValidationCallback((o, certificate, chain, errors) => false)
.ServerCertificateValidationCallback(CertificateValidations.DenyAll);
}
  • 使用 lambda 表达式:CertificateValidations.DenyAll 来拒绝所有验证。

允许所有证书验证

同样通过 ConnectionSettings 来设置回调

1
2
3
4
5
6
public class AllowAllCertificatesCluster : SslAndKpiXPackCluster
{
protected override ConnectionSettings ConnectionSettings(ConnectionSettings s) => s
.ServerCertificateValidationCallback((o, certificate, chain, errors) => true)
.ServerCertificateValidationCallback(CertificateValidations.AllowAll);
}
  • 使用 lambda 表达式:CertificateValidations.AllowAll 来拒绝所有验证。

允许来自证书颁发机构的证书

如果你的客户端应用程序可以在本地访问公共 CA 证书,则 Elasticsearch.NET 和 NEST 附带了一些方便的帮助程序,可以用来判断服务器提供的证书是否来自本地CA的证书。

如果你使用 elasticsearch-certutil工具 来生成SSL证书,则为了减少 SSL 握手数据尺寸,生成的节点证书并不包含在 CA 的证书链中。在这种情况下,你可以使用 CertificateValidations.AuthorityIsRoot 来验证证书。

1
2
3
4
5
6
7
8
9
10
[IntegrationOnly]
public class CertgenCaCluster : SslAndKpiXPackCluster
{
public CertgenCaCluster() : base() { }
public CertgenCaCluster(SslAndKpiClusterConfiguration configuration) : base(configuration) { }
protected override ConnectionSettings ConnectionSettings(ConnectionSettings s) => s
.ServerCertificateValidationCallback(
CertificateValidations.AuthorityIsRoot(new X509Certificate(this.ClusterConfiguration.FileSystem.CaCertificate))
);
}

如果证书不匹配,客户端会连接失败:

1
2
3
4
5
6
7
8
[IntegrationOnly]
public class BadCertgenCaCluster : SslAndKpiXPackCluster
{
protected override ConnectionSettings ConnectionSettings(ConnectionSettings s) => s
.ServerCertificateValidationCallback(
CertificateValidations.AuthorityPartOfChain(new X509Certificate(this.ClusterConfiguration.FileSystem.UnusedCaCertificate))
);
}

如果你需要使用供应商生成的 SSL 证书,则通常做法是在证书链中包含 CA 和所有中间 CA。使用此类证书时可以通过 CertificateValidations.AuthorityPartOfChain 来验证本地 CA 证书是否存在于证书链中。