Search code examples
c#asp.net-corenpgsql

Error when trying to connect using SSL with AWS RDS. Cannot read the pem certificate


Context I am trying to connect to postgres instance in AWS using the certificate suggested by AWS to make that kind of connection possible. But I cannot process the pem file because it is trowing and exception related with System.Security.Cryptography. I try to use the same logic you are using here to reproduce it faster: https://github.com/npgsql/npgsql/blob/3d41e7b629d727349218226a0f99489e6ffa05bb/src/Npgsql/Internal/NpgsqlConnector.cs#L747

and I am getting the same result.

Steps to reproduce

config = {
    "SslMode": "Require",
    "TrustServerCertificate" : true,
    "SslCertificate" : "rds-ca-2019-root.pem"
     ... other config 
}

the certificate can be obtained from here: https://s3.amazonaws.com/rds-downloads/rds-ca-2019-root.pem

The issue Cannot even test if it is connecting because of the pem file processing exception.

    Exception message: The certificate contents do not contain a PEM with a CERTIFICATE label, or the content is malformed.
    Stack trace:    at System.Security.Cryptography.X509Certificates.X509Certificate2.ExtractKeyFromPem[TAlg](ReadOnlySpan`1 keyPem, String[] labels, Func`1 factory, Func`2 import)
       at System.Security.Cryptography.X509Certificates.X509Certificate2.CreateFromPem(ReadOnlySpan`1 certPem, ReadOnlySpan`1 keyPem)
       at System.Security.Cryptography.X509Certificates.X509Certificate2.CreateFromPemFile(String certPemFilePath, String keyPemFilePath)
       at Npgsql.Internal.NpgsqlConnector.RawOpen(SslMode sslMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken, Boolean isFirstAttempt)
       at Npgsql.Internal.NpgsqlConnector.<Open>g__OpenCore|191_1(NpgsqlConnector conn, SslMode sslMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken, Boolean isFirstAttempt)
       at Npgsql.Internal.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
       at Npgsql.ConnectorPool.OpenNewConnector(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
       at Npgsql.ConnectorPool.<Get>g__RentAsync|28_0(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
       at Npgsql.NpgsqlConnection.<Open>g__OpenAsync|45_0(Boolean async, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
       at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQueryAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync(DatabaseFacade databaseFacade, String sql, IEnumerable`1 parameters, CancellationToken cancellationToken)
       at Starbucks.Pse.Menu.WebApi.Controllers.DebugController.Postgres() in /codebuild/output/src291905476/src/scm.starbucks.com/dpapi/pse-menu-service/Pse.Menu.WebApi/Controllers/DebugController.cs:line 71
       at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)


System.Security.Cryptography.CryptographicException: 'The certificate contents do not contain a PEM with a CERTIFICATE label, or the content is malformed.'

System.Security.Cryptography.CryptographicException: 'The certificate contents do not contain a PEM with a CERTIFICATE label, or the content is malformed.'

Further technical details Npgsql version: 6.0.6 PostgreSQL version: 13 Operating system: debian

This has also been posted in Github as an issue: https://github.com/npgsql/npgsql/issues/4675


Solution

  • I had a misunderstanding about the different SSL configuration that postgres has.

    For this specific configuration

    config = {
        "SslMode": "Require",
        "TrustServerCertificate" : true,
        "SslCertificate" : "rds-ca-2019-root.pem"
         ... other config 
    }
    

    You will need to use the SSL key, otherwise it won´t be possible to load and understand properly the pem file.

    Because the escenario with the AWS cert is, basically, trust the root authority and use a cert, you will need to configure it as follows:

    config = {
            "SslMode": "VerifyCA",
            // Delete this
            // "TrustServerCertificate" : true,
            "SslCertificate" : "rds-ca-2019-root.pem"
             ... other config 
        }
    

    another thing that you have to do is include that pem file in you valid CA authorities.

    Hope this help.