-
Notifications
You must be signed in to change notification settings - Fork 341
Cannot connect to AWS RDS Aurora 3 (Mysql8) using SslCa=<file> and SslMode=VerifyCA #1462
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
Comments
I just found this helpful link : dotnet/runtime#26449 (comment) which suggests
|
(even more digging...) |
This looks to be the key change that is necessary. Instead of calling It's a bit ugly, but you can use // load the AWS PEM bundle
var caCollection = new X509Certificate2Collection();
caCollection.ImportFromPemFile(@"C:\Path\To\global-bundle.pem");
// construct a chain that allows us to use our own root CA
X509Chain certificateChain = new()
{
ChainPolicy =
{
RevocationMode = X509RevocationMode.NoCheck,
VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority,
},
};
certificateChain.ChainPolicy.ExtraStore.AddRange(caCollection);
using (var connection = new MySqlConnection(csb.ConnectionString))
{
// use a custom RemoteCertificateValidationCallback
connection.RemoteCertificateValidationCallback = (object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors) =>
{
// same as MySqlConnector's implementation but builds using chain.ChainElements[^1]
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0 &&
certificate is not null &&
certificateChain is not null &&
certificateChain.Build(chain.ChainElements[^1].Certificate) &&
certificateChain.ChainStatus.Length > 0)
{
// now also verify that the root is part of the SSL CA bundle
var rootCertificate = certificateChain.ChainElements[^1].Certificate;
foreach (var sslCaCertificate in certificateChain.ChainPolicy.ExtraStore)
{
if (rootCertificate.RawData.SequenceEqual(sslCaCertificate.RawData))
{
var chainStatus = certificateChain.ChainStatus[0].Status & ~X509ChainStatusFlags.UntrustedRoot;
if (chainStatus == X509ChainStatusFlags.NoError)
sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
break;
}
}
}
return sslPolicyErrors == SslPolicyErrors.None;
};
connection.Open();
} |
Wow, that was very responsive. |
Thanks for the well-written bug report with helpful diagnosis! |
Fixed in 2.3.6. |
Software versions
MySqlConnector version: 2.3.5
Server type (MySQL, MariaDB, Aurora, etc.) and version: Aurora MySQL 3.04.0 (Compatible with MySQL 8.0.28)
.NET version: 8.0
(Optional) ORM NuGet packages and versions:
Describe the bug
Following our industry's leading security practices, I tried to upgrade from
SslMode=Required
toSslMode=VerifyCA
. To do that I downloaded the AWS RDS "CA Bundle" at https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem (see doc) .Unfortunately it did not work, it gives the exception
The remote certificate was rejected by the provided RemoteCertificateValidationCallback
After a lot of debugging, I tried one more thing : instead of passing the
SslCa
file, I imported it into the Windows Trusted Root Certificate Store. And it worked; proofing that the CA bundle is valid and sufficient. That is a good confirmation, but is not a portable solution.See the additional context for the rest of the info.
Exception
Code sample
Expected behavior
I expect that the certificate present by AWS is validated by the CA bundle provided by AWS. It should be possible to do that via the
SslCa
option.Additional context
The certificate chain presented by the AWS RDS server looks like (actual hostname redacted because... security...)
and the CA Bundle for us-east-1 looks like (the full global bundle is has 131 certs instead of 5, but we only care about 1 here):
However, in the custom certificate validation code around https://github.com/mysql-net/MySqlConnector/blob/master/src/MySqlConnector/Core/ServerSession.cs#L1390
, we have variable
caCertificateChain
built with the 5 root certificates inExtraStore
(see https://github.com/mysql-net/MySqlConnector/blob/master/src/MySqlConnector/Core/ServerSession.cs#L1368). This is okay.But at line 1390, the callback receives as
rcbCertificate
only the base certificate (thumbprint 424B43DAA5E6431865CB20664410539CC6A4F852), issued by "Subordinate CA", and the other variablercbChain
contains both the base server certificate and the subordinate certificate.Later at line 1398 when doing
caCertificateChain.Build((X509Certificate2) rcbCertificate)
we are attempting to verify the base certificate, but the chain is missing the subordinate, so it will always fail.I am no expert on the .NET
X509Chain
API, but I would think that we must start withrcbChain.ChainElements.Last()
, verify that one, and then work our way back the input chain until we hit the leaf.The text was updated successfully, but these errors were encountered: