Bob*_*ten 1 c# postgresql google-app-engine google-cloud-sql google-cloud-platform
这是我从未问过的最令人沮丧的问题。我如何连接这两个?
我有一个 API (ASP.NET Core 3.1),我将此应用程序部署到 Google 的 App Engine 上。我还在 Cloud SQL(PostgreSQL 引擎 12)上连接了一个数据库。如果没有 SSL,连接也可以正常工作。添加 SSL 是一个巨大的痛苦。我不断收到以下错误:
Error Connecting to database FATAL : no pg_hba.conf entry for host"x.x.x.x", user"jiradbuser", database"jiradb", SSL off
Run Code Online (Sandbox Code Playgroud)
上述错误实际上没有任何意义,因为我在 GCP 上没有任何选项来修改此类文件。
我已经下载了 Google 在将数据库配置为仅接受 SSL 连接时提供的 client-cert.pem、client-key.pem 和 server-ca.pem 文件,当我在 PSQL 中运行以下命令时,我连接通过 SSL 就可以了:
psql "sslmode=verify-ca sslrootcert=server-ca.pem sslcert=client-cert.pem sslkey=client-key.pem hostaddr=<cloud sql public ip> port=5432 user=< my username> dbname=<database inside cloud sql instance>"
Run Code Online (Sandbox Code Playgroud)
我尝试使用 NpgSqlConnectionStringBuilder 从配置文件中获取相关的 ----BEGIN CERTIFICATE--------END CERTIFICATE--- 文件来生成包含该信息的连接字符串,但这不起作用:
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString)
{
RootCertificate = Configuration["Google:ServerCA"],
ClientCertificate = Configuration["Google:ClientCert"],
ClientCertificateKey = Configuration["Google:ClientKey"],
SslMode = SslMode.Require,
TrustServerCertificate = true,
IncludeErrorDetails = true
};
Run Code Online (Sandbox Code Playgroud)
以下是错误消息:
"exception\":{\"StackTrace\":\" at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)\\n at Internal.Cryptography.Pal.OpenSslX509CertificateReader.FromFile(String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)\\n at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)\\n at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password)\\n at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)\\n at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)\\n at Npgsql.ConnectorPool.OpenNewConnector(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)\\n at Npgsql.ConnectorPool.<>c__DisplayClass38_0.<<Rent>g__RentAsync|0>d.MoveNext()\\n--- End of stack trace from previous location where exception was thrown ---
Run Code Online (Sandbox Code Playgroud)
我缺少一个步骤吗?我是否需要将这些文件转换为其他格式(例如 .pfx 或 .crt 或 .key)?我不认为我必须这么做,否则谷歌为什么要给我 .pem 文件呢?此外,我倾向于的一件事是将文件本身存储在 Google Secret Manager 中......这会改变什么吗?
我愿意回答您的问题或酌情添加其他信息。谢谢!
过去 24 小时我一直面临同样的问题。我在下面列出了一个可行的解决方案。对第一次尝试表示歉意...那是我大声思考,这在这些论坛中是不合适的。
该解决方案基于在 Windows 10 Professional 上运行的 C# dotnet core SDK 5.0.201 控制台应用程序,并带有 Google SQL Cloud PostgreSQL 13 后端数据库。
Google SQL Cloud 提供 PEM 文件;其中三个。两张证书和一把钥匙。有一个服务器证书颁发机构证书 (server-ca.pem) 和一个具有相应密钥的客户端证书(分别为 client-cert.pem 和 client-key.pem)。
根据你的例子,psql命令建议连接到 SQL Cloud 需要所有这三个。我正在使用 pgAdmin ,它的作用非常相似。
客户端证书和相应的密钥需要转换为 PFX(个人信息交换)格式。此文件格式本质上将客户端证书和密钥配对到一个文件中。
有两种方法可以执行此转换...使用openssl命令或使用 C# 代码执行此转换。
您可以在这篇 StackOverflow 帖子的“答案”中找到这两种方法...
Npgsql与.net core web api中的ssl证书连接
图片来源:Anish-V
首先,设置连接字符串。除了 SSL 证书之外,您还需要提供主机、数据库名称以及数据库用户名和密码等信息。此外,由于我们的目标是与 Google SQL Cloud 进行 SSL 连接,因此您可能会在 Google 控制台中勾选“仅允许 SSL 连接”标志。如果是这样,您还需要将 SslMode 设置为“Require”(或者可能“Prefer”,具体取决于您的要求/配置)。
var _connectionString = new NpgsqlConnectionStringBuilder()
{
Host = settings.Host,
Database = settings.Database,
Username = settings.Username,
Password = settings.Password,
SslMode = SslMode.Require
};
var _pgdb = new NpgsqlConnection(_connectionString.ConnectionString);
Run Code Online (Sandbox Code Playgroud)
查看客户端证书和密钥,上面的 StackOverflow 帖子采用客户端证书 (client-cert.pem) 和密钥 (client-key.pem) 并创建组合的 PFX 证书。如上所述,您可以使用代码openssl或在代码中执行此操作。目前,我正在追求“代码内”方法,以减少将来发布应用程序时的任何手动步骤。不过,我已经测试了该openssl方法并生成了一个 PFX 文件......这也有效。
要将 PFX 证书添加到连接,您可以使用ProvideClientCertificatesCallback该类的方法NpgsqlConnection...
_pgdb.ProvideClientCertificatesCallback += new ProvideClientCertificatesCallback;
_pgdb.Open();
Run Code Online (Sandbox Code Playgroud)
我们现在ProvideClientCertificatesCallback用我们自己的实现重载该方法,如下所示......
public void ProvideClientCertificatesCallback(X509CertificateCollection certificates)
{
var clientCert =
GetCombinedCertificateAndKey(
$@"{certificatePath}\client-cert.pem",
$@"{certificatePath}\client-key.pem");
certificates.Add(clientCert);
Console.WritLine($"client-cert.pem/client-key.perm: {clientCert.Issuer}");
}
Run Code Online (Sandbox Code Playgroud)
该方法GetCombinedCertificateAndKey采用两个参数...客户端证书和客户端密钥的文件名。这个方法是从上面提到的StackOverflow帖子借用的...我稍微调整了一下...
private X509Certificate2 GetCombinedCertificateAndKey(string clientCertPath, string clientKeyPath)
{
using var publicKey = new X509Certificate2(clientCertPath); ;
var privateKeyText = System.IO.File.ReadAllText(clientKeyPath);
var privateKeyBlocks = privateKeyText.Split("-", StringSplitOptions.RemoveEmptyEntries);
var privateKeyBytes = Convert.FromBase64String(privateKeyBlocks[1]);
using var rsa = RSA.Create();
switch (privateKeyBlocks[0]) {
case "BEGIN PRIVATE KEY":
rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _);
break;
case "BEGIN RSA PRIVATE KEY":
rsa.ImportRSAPrivateKey(privateKeyBytes, out _);
break;
}
var keyPair = publicKey.CopyWithPrivateKey(rsa);
var Certificate = new X509Certificate2(keyPair.Export(X509ContentType.Pfx));
return Certificate;
}
Run Code Online (Sandbox Code Playgroud)
很高兴通过 Visual Studio 调试器运行它...您可以检查证书的内容。在我的例子中,Google client-key.pem 似乎是一个 RSA 密钥,它是通过 switch 语句中的此方法拾取的。我怀疑所有谷歌密钥都是一样的。
另请注意,之前的行return...它以组合 PFX 格式导出客户端证书/密钥对,并将其作为证书返回给调用方法。
对于服务器CA证书,我目前的解决方案是绕过该证书的验证。为此,只需将该TrustServerCertificate属性添加到连接字符串中,如下所示。顾名思义,这决定是否信任服务器证书而不验证它。我的想法是,在这种情况下,我相信证书是由信誉良好的来源提供的......谷歌。不过,我将继续寻找更完整的解决方案,以便我可以验证服务器 CA 证书。
var _connectionString = new NpgsqlConnectionStringBuilder()
{
Host = settings.Host,
Database = settings.Database,
Username = settings.Username,
Password = settings.Password,
SslMode = SslMode.Require,
TrustServerCertificate = true,
};
var _pgdb = new NpgsqlConnection(_connectionString.ConnectionString);
Run Code Online (Sandbox Code Playgroud)
就是这样。有用!:-) 我希望它对您有用并节省您一天的时间。
在回答有关将证书存储在 Google Secret Manager 中的问题时,我建议您这样做,尽管那完全是另一个主题。
| 归档时间: |
|
| 查看次数: |
866 次 |
| 最近记录: |