-
Notifications
You must be signed in to change notification settings - Fork 302
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix #197 - AWSEKSResourceDetector fails to detect resources due to ex…
…ception "The SSL connection could not be established" (#208) * #197 - AWSEKSResourceDetector fails to detect resources due to exception "The SSL connection could not be established" Issue Description: With the current code, it requires an additional step of installing kubernetes self-signed certificate to the trusted store as .NET core expects them to the trsuted store to make a secure connection. Fix Provided: ServerCertificationValidationProvider - Safely loads the certificate to the trusted collection along with ServerSideValidation. This would avoid the unnecessary step of installing the certificate manually. Handler - Creates HttpClientHandler with client certificate. (cherry picked from commit 41e68d3) * PR Review Comments (cherry picked from commit 0b5d9a9) * Address PR comments (cherry picked from commit 4aa1c62) * Remove unused import * Added Unit Tests * Removed unused directive * Added Trait for codecov build * Use temporary files to store test certificate * Fixed File Access Issue in Unit Test * Use TempFileName for Unit Tests * Added Debug logging for build test Fixed For loop tries * Revert "Added Debug logging for build test" This reverts commit b982325. * Fixed tries logic in for loop Co-authored-by: Prashant Srivastava <[email protected]> Co-authored-by: Igor Kiselev <[email protected]>
- Loading branch information
1 parent
055c156
commit 5608616
Showing
9 changed files
with
426 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/Http/Handler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// <copyright file="Handler.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using System.Net.Http; | ||
|
||
namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.Http | ||
{ | ||
internal class Handler | ||
{ | ||
public static HttpClientHandler Create(string certificateFile) | ||
{ | ||
try | ||
{ | ||
ServerCertificateValidationProvider serverCertificateValidationProvider = | ||
ServerCertificateValidationProvider.FromCertificateFile(certificateFile); | ||
|
||
if (!serverCertificateValidationProvider.IsCertificateLoaded) | ||
{ | ||
AWSXRayEventSource.Log.FailedToValidateCertificate(nameof(Handler), "Failed to Load the certificate file into trusted collection"); | ||
return null; | ||
} | ||
|
||
var clientHandler = new HttpClientHandler(); | ||
clientHandler.ServerCertificateCustomValidationCallback = | ||
(sender, x509Certificate2, x509Chain, sslPolicyErrors) => | ||
serverCertificateValidationProvider.ValidationCallback(null, x509Certificate2, x509Chain, sslPolicyErrors); | ||
return clientHandler; | ||
} | ||
catch (Exception ex) | ||
{ | ||
AWSXRayEventSource.Log.ResourceAttributesExtractException($"{nameof(Handler)} : Failed to create HttpClientHandler", ex); | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
} |
161 changes: 161 additions & 0 deletions
161
...elemetry.Contrib.Extensions.AWSXRay/Resources/Http/ServerCertificateValidationProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
// <copyright file="ServerCertificateValidationProvider.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Net.Security; | ||
using System.Security.Cryptography.X509Certificates; | ||
|
||
namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.Http | ||
{ | ||
internal class ServerCertificateValidationProvider | ||
{ | ||
private static readonly ServerCertificateValidationProvider InvalidProvider = | ||
new ServerCertificateValidationProvider(null); | ||
|
||
private readonly X509Certificate2Collection trustedCertificates; | ||
|
||
private ServerCertificateValidationProvider(X509Certificate2Collection trustedCertificates) | ||
{ | ||
if (trustedCertificates == null) | ||
{ | ||
this.trustedCertificates = null; | ||
this.ValidationCallback = null; | ||
this.IsCertificateLoaded = false; | ||
return; | ||
} | ||
|
||
this.trustedCertificates = trustedCertificates; | ||
this.ValidationCallback = (sender, cert, chain, errors) => | ||
this.ValidateCertificate(new X509Certificate2(cert), chain, errors); | ||
this.IsCertificateLoaded = true; | ||
} | ||
|
||
public bool IsCertificateLoaded { get; } | ||
|
||
public RemoteCertificateValidationCallback ValidationCallback { get; } | ||
|
||
public static ServerCertificateValidationProvider FromCertificateFile(string certificateFile) | ||
{ | ||
if (!File.Exists(certificateFile)) | ||
{ | ||
AWSXRayEventSource.Log.FailedToValidateCertificate(nameof(ServerCertificateValidationProvider), "Certificate File does not exist"); | ||
return InvalidProvider; | ||
} | ||
|
||
var trustedCertificates = new X509Certificate2Collection(); | ||
if (!LoadCertificateToTrustedCollection(trustedCertificates, certificateFile)) | ||
{ | ||
AWSXRayEventSource.Log.FailedToValidateCertificate(nameof(ServerCertificateValidationProvider), "Failed to load certificate in trusted collection"); | ||
return InvalidProvider; | ||
} | ||
|
||
return new ServerCertificateValidationProvider(trustedCertificates); | ||
} | ||
|
||
private static bool LoadCertificateToTrustedCollection(X509Certificate2Collection collection, string certFileName) | ||
{ | ||
try | ||
{ | ||
collection.Import(certFileName); | ||
return true; | ||
} | ||
catch (Exception) | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
private bool ValidateCertificate(X509Certificate2 cert, X509Chain chain, SslPolicyErrors errors) | ||
{ | ||
var isSslPolicyPassed = errors == SslPolicyErrors.None || | ||
errors == SslPolicyErrors.RemoteCertificateChainErrors; | ||
if (!isSslPolicyPassed) | ||
{ | ||
if ((errors | SslPolicyErrors.RemoteCertificateNotAvailable) == errors) | ||
{ | ||
AWSXRayEventSource.Log.FailedToValidateCertificate(nameof(ServerCertificateValidationProvider), "Failed to validate certificate due to RemoteCertificateNotAvailable"); | ||
} | ||
|
||
if ((errors | SslPolicyErrors.RemoteCertificateNameMismatch) == errors) | ||
{ | ||
AWSXRayEventSource.Log.FailedToValidateCertificate(nameof(ServerCertificateValidationProvider), "Failed to validate certificate due to RemoteCertificateNameMismatch"); | ||
} | ||
} | ||
|
||
chain.ChainPolicy.ExtraStore.AddRange(this.trustedCertificates); | ||
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; | ||
|
||
// building the chain to process basic validations e.g. signature, use, expiration, revocation | ||
var isValidChain = chain.Build(cert); | ||
|
||
if (!isValidChain) | ||
{ | ||
var chainErrors = string.Empty; | ||
foreach (var element in chain.ChainElements) | ||
{ | ||
foreach (var status in element.ChainElementStatus) | ||
{ | ||
chainErrors += | ||
$"\nCertificate [{element.Certificate.Subject}] Status [{status.Status}]: {status.StatusInformation}"; | ||
} | ||
} | ||
|
||
AWSXRayEventSource.Log.FailedToValidateCertificate(nameof(ServerCertificateValidationProvider), $"Failed to validate certificate due to {chainErrors}"); | ||
} | ||
|
||
// check if at least one certificate in the chain is in our trust list | ||
var isTrusted = this.HasCommonCertificate(chain, this.trustedCertificates); | ||
if (!isTrusted) | ||
{ | ||
var serverCertificates = string.Empty; | ||
foreach (var element in chain.ChainElements) | ||
{ | ||
serverCertificates += " " + element.Certificate.Subject; | ||
} | ||
|
||
var trustCertificates = string.Empty; | ||
foreach (var trustCertificate in this.trustedCertificates) | ||
{ | ||
trustCertificates += " " + trustCertificate.Subject; | ||
} | ||
|
||
AWSXRayEventSource.Log.FailedToValidateCertificate( | ||
nameof(ServerCertificateValidationProvider), | ||
$"Server Certificates Chain cannot be trusted. The chain doesn't match with the Trusted Certificates provided. Server Certificates:{serverCertificates}. Trusted Certificates:{trustCertificates}"); | ||
} | ||
|
||
return isSslPolicyPassed && isValidChain && isTrusted; | ||
} | ||
|
||
private bool HasCommonCertificate(X509Chain chain, X509Certificate2Collection collection) | ||
{ | ||
foreach (var chainElement in chain.ChainElements) | ||
{ | ||
foreach (var certificate in collection) | ||
{ | ||
if (Enumerable.SequenceEqual(chainElement.Certificate.GetPublicKey(), certificate.GetPublicKey())) | ||
{ | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.