从 GCP 秘密管理器读取 .DER 值并将其保存到 .DER 文件

Read .DER value from GCP secret manager and save it to .DER file

首先,这是我的第一个 post - 如果这个 post 描述和设计不完善,请见谅。

我的问题是我需要使用 spring 引导通过 SSL 连接连接到 GCP 中的数据库。在 GCP 内部生成三个所需的证书(客户端-cert.pem、客户端-key.pem、服务器-ca.pem)。不幸的是 spring 无法使用存储在 pem 文件中的客户端密钥连接到数据库,因此我必须将 exmaple 的客户端密钥保存在 .DER 证书中。

为了连接到数据库,我使用了这段代码。

return DataSourceBuilder
                .create()
                .url("jdbc:postgresql://XXX:5432/XXX?" +
                        "ssl=true&sslmode=verify-ca&" +
                        "sslrootcert=server-ca.pem&" +
                        "sslcert=client-cert.pem&" +
                        "sslkey=client-key.der")
                .build();
    }

为了从 .PEM 文件生成 .DER,我使用了这个命令:

openssl pkcs8 -topk8 -inform PEM -in client-key.pem -outform DER -nocrypt -out client-key.der

它在本地有效,但我必须将证书保存在 GCP 的秘密管理器 (SM) 中。 SM 只能存储值,所以我保留 .DER 文件中的二进制值

![Take a look at image](https://i.stack.imgur.com/dAjLU.png).

我正在使用 GCP java 库连接到 SM:

 private String getKey(String projectId, String secretCertName, boolean isPEM) {
            try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
                SecretVersionName secretVersionName = SecretVersionName.of(projectId, secretCertName, "latest");
                AccessSecretVersionResponse response = client.accessSecretVersion(secretVersionName);
                return response.getPayload().getData().toStringUtf8();
                
            } catch (IOException e) {
                System.out.println("gcp cant connect !");
            }
            return null;
    }

它使用 PEM 和字符串值,但如果我想将此密钥保存在 .DER 文件中,那么我的客户端-key.der 文件与 openssl 生成的证书不匹配并且 spring 无法连接到带堆栈的数据库:

org.postgresql.util.PSQLException: Could not read SSL key file client-key.der. at org.postgresql.ssl.LazyKeyManager.getPrivateKey(LazyKeyManager.java:284) ~[postgresql-42.3.2.jar:42.3.2] at java.base/sun.security.ssl.AbstractKeyManagerWrapper.getPrivateKey(SSLContextImpl.java:1696) ~[na:na] ...

Caused by: java.io.IOException: Invalid lenByte at java.base/sun.security.util.DerValue.<init>(DerValue.java:374) ~[na:na] at java.base/sun.security.util.DerValue.<init>(DerValue.java:312) ~[na:na] at java.base/javax.crypto.EncryptedPrivateKeyInfo.<init>(EncryptedPrivateKeyInfo.java:86) ~[na:na] at org.postgresql.ssl.LazyKeyManager.getPrivateKey(LazyKeyManager.java:236) ~[postgresql-42.3.2.jar:42.3.2] ... 73 common frames omitted

知道我应该如何从 GCP SM 读取二进制文件(如 .DER 证书)吗?我读到应该编码,但直到现在我都没有成功。

感谢提前,请保持温柔,这是我的第一次 post :)

根据 John 的评论,我将编码的 .DER 文件保存在秘密管理器中。接下来我解码了来自秘密管理器 API 的值。在这种情况下很重要 - 将 byte[] 而不是 String 保存到文件 !

更新: 您不需要在 SM 中保存编码的 .DER 值。您可以保留二进制值,但要从 API 获取这些值,您需要使用:

return response.getPayload().getData().toByteArray();

并保存在 .DER 证书中,然后使用以下行:

try (FileOutputStream stream = new FileOutputStream(path)) { stream.write(Base64.getMimeDecoder().decode(Base64.getEncoder().encode(certValue))); }