Skip to content
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

No credentials are available in the security package #1278

Closed
ingted opened this issue Jan 9, 2023 · 14 comments
Closed

No credentials are available in the security package #1278

ingted opened this issue Jan 9, 2023 · 14 comments
Assignees
Labels

Comments

@ingted
Copy link

ingted commented Jan 9, 2023

Software versions
MySqlConnector version: latest git cloned repository
Server type (MySQL, MariaDB, Aurora, etc.) and version: GCS 5.7
.NET version: .NET 7

Describe the bug
Unable to open a connection due to auth issue. "No credentials are available in the security package"

Code sample

        let myBuilder = 
            new MySqlConnectionStringBuilder(@"Server=XXXXX;User ID=YYYY;Password=ZZZZZZ;Database=QQQQQ")

        myBuilder.SslCert <- @"G:\Downloads\data-team\client-cert.pem"
        myBuilder.SslKey <- @"G:\Downloads\data-team\client-key.pem"
        myBuilder.SslCa <- @"G:\Downloads\data-team\server-ca.pem"
        myBuilder.SslMode <- MySqlSslMode.VerifyFull
        
        let myConn = new MySqlConnection(myBuilder.ConnectionString)

        myConn.Open()

Exception

Exception thrown: 'System.Security.Authentication.AuthenticationException' in System.Private.CoreLib.dll

image

image

image

image

@ingted
Copy link
Author

ingted commented Jan 9, 2023

Workaround (according to dotnet/runtime#23749)

Modify this file src\MySqlConnector\Core\ServerSession.cs

			m_clientCertificate = X509Certificate2.CreateFromPemFile(sslCertificateFile, sslKeyFile);
                        //add the following line
			m_clientCertificate = new X509Certificate2(m_clientCertificate.Export(X509ContentType.Pkcs12)); //add this line

			return new() { m_clientCertificate };

@bgrainger
Copy link
Member

The ConnectSslClientCertificatePem integration tests are passing on Linux; need to check if they're tested for the Windows build.

https://github.com/mysql-net/MySqlConnector/blob/master/tests/IntegrationTests/SslTests.cs#L76-L95

@bgrainger bgrainger self-assigned this Jan 9, 2023
@bgrainger bgrainger added the bug label Jan 9, 2023
@bgrainger
Copy link
Member

bgrainger commented Jan 9, 2023

Thanks for the bug report; the workaround that you identified seems like the right approach. In the meantime, you can use ProvideClientCertificatesCallback as a workaround (example in C#):

var myBuilder =
    new MySqlConnectionStringBuilder(@"Server=XXXXX;User ID=YYYY;Password=ZZZZZZ;Database=QQQQQ");

myBuilder.SslCa = @"G:\Downloads\data-team\server-ca.pem";
myBuilder.SslMode = MySqlSslMode.VerifyFull;

// don't set these:
// myBuilder.SslKey = @"G:\Downloads\data-team\client-key.pem";
// myBuilder.SslCert = @"G:\Downloads\data-team\client-cert.pem";
        
using var myConn = new MySqlConnection(myBuilder.ConnectionString);

// do this instead:
myConn.ProvideClientCertificatesCallback = collection =>
{
    var certificate = X509Certificate2.CreateFromPemFile(@"G:\Downloads\data-team\client-cert.pem", @"G:\Downloads\data-team\client-key.pem");
    collection.Add(new X509Certificate2(certificate.Export(X509ContentType.Pkcs12)));
    return default;
};

myConn.Open();

@ingted
Copy link
Author

ingted commented Jan 10, 2023

Not sure why, but not work for me...

image

@ingted
Copy link
Author

ingted commented Jan 10, 2023

Seems like ProvideClientCertificatesCallback has never been invoked... (step-into never touches break point inside it)

@bgrainger
Copy link
Member

In order for ProvideClientCertificatesCallback to be called, the CertificateFile, SslCert, or SslKey options must not be specified in the connection string. (The documentation could be clearer about this.) It's OK to set SslCa, but not any of the others.

@ingted
Copy link
Author

ingted commented Jan 10, 2023

After removing path from connection string, callback works. Thank you so much!!!

@bgrainger
Copy link
Member

I thought of another workaround (that may be easier):

Use openssl to combine the two PEM files into one PFX file, then use the CertificateFile connection string option to reference that:

openssl pkcs12 -in client-cert.pem -inkey client-key.pem -export -out client.pfx

Connection string becomes: Server=XXXXX;User ID=YYYY;Password=ZZZZZZ;Database=QQQQQ;Certificate File=G:\Downloads\data-team\client.pfx

@ingted
Copy link
Author

ingted commented Jan 12, 2023

Should I close this issue?

@bgrainger
Copy link
Member

No, I'll close it once the fix is shipped (likely in 2.2.6).

@bgrainger
Copy link
Member

Fixed in 2.2.6.

@MA-Maddin
Copy link

MA-Maddin commented Nov 26, 2023

Hey, I came across this issue several times the past days, as I am currently (and still) struggling with the Pomelo.EntityFrameworkCore.MySql package also with SslMode=VerifyFull.

Since I am using it in an ASP.NET Core-Web-API project, where the MySqlConnection is created by Pomelo's .UseMySql() extension method, I didn't really had an easy chance to try out the ProvideClientCertificatesCallback solution that was mentioned here.
But I tried the other mentioned workaround to combine client key and cert into one pkcs12 file and to use only that. But that didn't work either.

Today, I was playing around with just using MySqlConnector (2.3.1) in a .NET 8 console app and was finally able to connect via crt and key file (the first success past 3 days [thanks for that]).
But I also tested the pkcs12/CertificateFile way. And it seems that this way still doesn't work, so I just wanted to mention it here:

MySqlConnectionStringBuilder mcsb = new MySqlConnectionStringBuilder()
{
    Server = "example.org",
    Port = 3306,
    Database = "dbName",
    UserID = "userName",
    Password = "abc123",
    SslMode = MySqlSslMode.VerifyFull,
    SslCa = "CA.crt.pem",
};

MySqlConnectionStringBuilder working = new MySqlConnectionStringBuilder(mcsb.ConnectionString)
{
    SslCert = "client.crt.pem",
    SslKey = "client.key.pem"
};

MySqlConnectionStringBuilder notWorking = new MySqlConnectionStringBuilder(mcsb.ConnectionString)
{
    CertificateFile = "bundle.pfx"
};

using MySqlConnection connection = new MySqlConnection(notWorking.ConnectionString);

connection.Open();

I am running the client on Windows side.
All certificates and keys were created on Debian using OpenSSL.
The bundle.pfx was created with:
openssl pkcs12 -in client.crt.pem -inkey client.key.pem -export -out bundle.pfx

@bgrainger
Copy link
Member

I followed these steps to generate a new client certificate and key: https://dev.mysql.com/doc/refman/8.0/en/creating-ssl-files-using-openssl.html#creating-ssl-files-using-openssl-unix-command-line. (Using Ubuntu 20.04 under WSL on Windows 10.)

I then used the command you provided above to create bundle.pfx.

I had no problem connecting to mysql:8.2.0 running in a Docker container on Windows 10 using a .NET 8.0 console application, either using CertificateFile or using SslCert+SslKey.

If you can provide thorough steps to reproduce, or failing certificate files, I can try to investigate further.

@ingted
Copy link
Author

ingted commented Dec 1, 2023

https://decoder.link/converter

You could also use this online tool provided by Namecheap to perform the format conversion.

ref. https://www.namecheap.com/support/knowledgebase/article.aspx/9617/69/how-to-convert-certificates-into-different-formats-using-openssl/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants