使用SSL连接AWS RDS PostgreSQL时PEM证书解析异常求助
AWS PostgreSQL SSL连接时PEM证书处理异常问题
上下文
尝试使用AWS推荐的证书通过SSL连接AWS上的PostgreSQL实例,处理pem文件时抛出System.Security.Cryptography相关异常。复用Npgsql内部连接逻辑复现后,得到相同异常结果。
复现步骤
- 使用如下连接配置:
config = { "SslMode": "Require", "TrustServerCertificate": true, "SslCertificate": "rds-ca-2019-root.pem" // ... 其他配置项 }
- 使用AWS官方提供的RDS根CA证书
问题描述
无法建立数据库连接,抛出核心异常:
System.Security.Cryptography.CryptographicException: '证书内容不包含带有CERTIFICATE标签的PEM,或内容格式错误。'
完整堆栈跟踪:
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)
技术细节
- Npgsql版本:6.0.6
- PostgreSQL版本:13
- 操作系统:Debian
解决方案
1. 修正配置参数
SslCertificate用于指定客户端证书,而AWS根CA证书是用来验证服务器身份的,应配置到RootCertificate参数中,同时关闭TrustServerCertificate以启用证书验证:
config = { "SslMode": "Require", "TrustServerCertificate": false, "RootCertificate": "rds-ca-2019-root.pem" // ... 其他配置项 }
2. 验证证书文件完整性
打开下载的rds-ca-2019-root.pem文件,确认:
- 包含完整的
-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----标签 - 标签之间的Base64编码内容无截断、乱码或多余换行
- 若文件损坏,重新下载证书
3. 转换证书格式(可选)
如果系统对PEM文件处理存在兼容性问题,可通过OpenSSL将PEM转换为PFX格式:
openssl pkcs12 -export -out rds-ca-2019-root.pfx -in rds-ca-2019-root.pem -nokeys
之后将RootCertificate配置为该PFX文件路径。
4. 升级Npgsql版本
Npgsql 6.0.6存在部分证书处理的已知缺陷,升级到6.0.x系列的后续稳定版或更高主版本(如7.x)可修复相关兼容性问题。
内容的提问来源于stack exchange,提问作者EdCastanio
相关产品推荐
相关产品推荐

