Skip to content

Commit 90941f6

Browse files
committed
Fix BadCustomCertificatePerRequestWinsApiTests on older 5.x versions
Looks like Elasticsearch versions < 5.2.0 exhibit different behaviour when a bad client certificate is supplied (cherry picked from commit 199fef0)
1 parent 3a01b50 commit 90941f6

File tree

1 file changed

+47
-31
lines changed

1 file changed

+47
-31
lines changed

src/Tests/ClientConcepts/Certificates/WorkingWithCertificates.doc.cs

+47-31
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,36 @@ namespace Tests.ClientConcepts.Certificates
1616
*
1717
* === Server Certificates
1818
*
19-
* If you've enabled SSL on elasticsearch with x-pack or through a proxy in front of elasticsearch and the Certificate Authority (CA)
19+
* If you've enabled SSL on Elasticsearch with x-pack or through a proxy in front of elasticsearch and the Certificate Authority (CA)
2020
* That generated the certificate is trusted by the machine running the client code there should be nothing you'll have to do to to talk
2121
* to over https with the client. If you are using your own CA which is not trusted .NET won't allow you to make https calls to that endpoint.
2222
*
23-
* .NET allows you to preempt this though through a custom validation through the the global static `ServicePointManager.ServerCertificateValidationCallback`.
23+
* In .NET, you can preempt this though through a custom validation through the the global static `ServicePointManager.ServerCertificateValidationCallback`.
2424
* Most examples you will find on the .NET will simply return `true` from this delegate and call it quits. This is not advisable as this will allow any HTTPS
2525
* traffic in the current AppDomain and not run any validations. Imagine you deploy a web app that talks to Elasticsearch over HTTPS but also some third party
26-
* SOAP/WSDL endpoint setting `ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;` will skip validation of BOTH
27-
* Elasticsearch and that external web service.
28-
29-
* .NET also allows you to set that callback per service endpoint and Elasticsearch.NET/NEST exposes this through connection settings.
30-
* You can do your own validation in that handler or simply assign baked in handler that we ship with out of the box on the static
31-
* class `CertificateValidations`.
26+
* SOAP/WSDL endpoint setting
27+
*
28+
* [source,csharp]
29+
* ----
30+
* ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
31+
* ----
32+
*
33+
* will skip validation for *both* Elasticsearch *and* that external web service.
34+
*
35+
* You can also set a callback per service endpoint with .NET, and Elasticsearch.NET/NEST exposes this through the
36+
* connection settings; You can do your own validation in that handler or simply assign one of the baked in handlers
37+
* that we ship with out of the box, on the static class `CertificateValidations`.
3238
*
33-
* The two most basic ones are `AllowAll` and `DenyAll` which does accept or deny any ssl trafic to our nodes`:
39+
* The two most basic ones are `AllowAll` and `DenyAll`, which accept or deny any SSL traffic to our nodes, respectively
3440
*
3541
*/
3642
public class DenyAllCertificatesCluster : SslAndKpiXPackCluster
3743
{
3844
protected override ConnectionSettings ConnectionSettings(ConnectionSettings s) => s
3945
.ServerCertificateValidationCallback((o, certificate, chain, errors) => false)
40-
.ServerCertificateValidationCallback(CertificateValidations.DenyAll);
46+
.ServerCertificateValidationCallback(CertificateValidations.DenyAll); // <1> synonymous with the previous delegate
4147
}
48+
4249
//hide
4350
[IntegrationOnly]
4451
public class DenyAllSslCertificatesApiTests : ConnectionErrorTestBase<DenyAllCertificatesCluster>
@@ -56,8 +63,9 @@ public class AllowAllCertificatesCluster : SslAndKpiXPackCluster
5663
{
5764
protected override ConnectionSettings ConnectionSettings(ConnectionSettings s) => s
5865
.ServerCertificateValidationCallback((o, certificate, chain, errors) => true)
59-
.ServerCertificateValidationCallback(CertificateValidations.AllowAll);
60-
}
66+
.ServerCertificateValidationCallback(CertificateValidations.AllowAll); // <1> synonymous with the previous delegate
67+
}
68+
6169
//hide
6270
[IntegrationOnly]
6371
public class AllowAllSslCertificatesApiTests : CanConnectTestBase<AllowAllCertificatesCluster>
@@ -66,15 +74,15 @@ public AllowAllSslCertificatesApiTests(AllowAllCertificatesCluster cluster, Endp
6674
[I] public async Task UsedHttps() => await AssertOnAllResponses(r => r.ApiCall.Uri.Scheme.Should().Be("https"));
6775
}
6876

69-
/**
70-
* If your client application however has access to the public CA certificate locally Elasticsearch.NET/NEST ships with handy helpers that assert
71-
* that the certificate that the server presented was one that came from our local CA certificate. If you use x-pack's `certgen` tool to
72-
* [generate SSL certificates](https://www.elastic.co/guide/en/x-pack/current/ssl-tls.html) the generated node certificate does not include the CA in the
77+
/**
78+
* If your client application however has access to the public CA certificate locally, Elasticsearch.NET/NEST ships with handy helpers that assert
79+
* that the certificate that the server presented was one that came from our local CA certificate. If you use X-Pack's `certgen` tool to
80+
* {xpack_current}/ssl-tls.html[generate SSL certificates], the generated node certificate does not include the CA in the
7381
* certificate chain. This to cut back on SSL handshake size. In those case you can use `CertificateValidations.AuthorityIsRoot` and pass it your local copy
7482
* of the CA public key to assert that the certificate the server presented was generated off that.
7583
*/
7684

77-
public class CertgenCaCluster : SslAndKpiXPackCluster
85+
public class CertgenCaCluster : SslAndKpiXPackCluster
7886
{
7987
protected override ConnectionSettings ConnectionSettings(ConnectionSettings s) => s
8088
.ServerCertificateValidationCallback(
@@ -114,18 +122,19 @@ protected override void AssertException(WebException e) =>
114122
protected override void AssertException(HttpRequestException e) { }
115123

116124
}
117-
/**
125+
/**
118126
* If you go for a vendor generated SSL certificate its common practice for them to include the CA and any intermediary CA's in the certificate chain
119127
* in those case use `CertificateValidations.AuthorityPartOfChain` which validates that the local CA certificate is part of that chain and was used to
120128
* generate the servers key.
121129
*/
122130

123131
#if !DOTNETCORE
124-
/**
132+
/**
125133
* === Client Certificates
126-
* X-Pack also allows you to configure a [PKI realm](https://www.elastic.co/guide/en/x-pack/current/pki-realm.html) to enable user authentication
134+
*
135+
* X-Pack also allows you to configure a {xpack_current}/pki-realm.html[PKI realm] to enable user authentication
127136
* through client certificates. The `certgen` tool included with X-Pack allows you to
128-
* [generate client certificates as well](https://www.elastic.co/guide/en/x-pack/current/ssl-tls.html#CO13-4) and assign the distinguished name (DN) of the
137+
* {xpack_current}/ssl-tls.html#CO13-4[generate client certificates as well] and assign the distinguished name (DN) of the
129138
* certificate as a user with a certain role.
130139
*
131140
* certgen by default only generates a public certificate (`.cer`) and a private key `.key`. To authenticate with client certificates you need to present both
@@ -138,10 +147,9 @@ protected override void AssertException(HttpRequestException e) { }
138147
* You can set Client Certificates to use on all connections on `ConnectionSettings`
139148
140149
*/
141-
public class PkiCluster : CertgenCaCluster
150+
public class PkiCluster : CertgenCaCluster
142151
{
143152
public override ConnectionSettings Authenticate(ConnectionSettings s) => s
144-
//.ClientCertificate(this.Node.FileSystem.ClientCertificate);
145153
.ClientCertificate(
146154
ClientCertificate.LoadWithPrivateKey(this.Node.FileSystem.ClientCertificate, this.Node.FileSystem.ClientPrivateKey, "")
147155
);
@@ -152,6 +160,7 @@ public override ConnectionSettings Authenticate(ConnectionSettings s) => s
152160
"xpack.security.http.ssl.client_authentication=required"
153161
}).ToArray();
154162
}
163+
155164
//hide
156165
[IntegrationOnly]
157166
public class PkiApiTests : CanConnectTestBase<PkiCluster>
@@ -170,26 +179,33 @@ public class BadCustomCertificatePerRequestWinsApiTests : ConnectionErrorTestBas
170179
public BadCustomCertificatePerRequestWinsApiTests(BadPkiCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
171180
[I] public async Task UsedHttps() => await AssertOnAllResponses(r => r.ApiCall.Uri.Scheme.Should().Be("https"));
172181

173-
private string BadCertificate => this.Cluster.Node.FileSystem.ClientCertificate;
182+
// a bad certificate
183+
private string Certificate => this.Cluster.Node.FileSystem.ClientCertificate;
174184

175185
protected override RootNodeInfoRequest Initializer => new RootNodeInfoRequest
176186
{
177187
RequestConfiguration = new RequestConfiguration
178188
{
179-
ClientCertificates = new X509Certificate2Collection { new X509Certificate2(this.BadCertificate) }
189+
ClientCertificates = new X509Certificate2Collection { new X509Certificate2(this.Certificate) }
180190
}
181191
};
182192

183193
protected override Func<RootNodeInfoDescriptor, IRootNodeInfoRequest> Fluent => s => s
184194
.RequestConfiguration(r => r
185-
.ClientCertificate(this.BadCertificate)
186-
195+
.ClientCertificate(this.Certificate)
187196
);
188197

189-
protected override void AssertException(WebException e) =>
190-
e.Message.Should().Contain("Could not create SSL/TLS secure channel");
191-
192-
protected override void AssertException(HttpRequestException e) { }
198+
// hide
199+
protected override void AssertException(WebException e)
200+
{
201+
if (e.InnerException != null)
202+
e.InnerException.Message.Should()
203+
.Contain("Authentication failed because the remote party has closed the transport stream");
204+
else
205+
e.Message.Should().Contain("Could not create SSL/TLS secure channel");
206+
}
207+
208+
protected override void AssertException(HttpRequestException e) { }
193209

194210
}
195211
#endif

0 commit comments

Comments
 (0)