4

我有一个正在运行的云运行服务user-service。出于测试目的,我通过环境变量将客户端机密作为纯文本传递。现在,由于一切正常,我想改用一个秘密。

在“编辑修订”选项的“变量”选项卡中,我可以声明环境变量,但我不知道如何传递秘密?我只需要像${my-secret-id}在变量的值字段中一样传递秘密名称吗?此选项卡中没有关于如何使用机密的文档,只有顶部的提示:

Store and consume secrets using Secret Manager

在这种情况下,这不是很有帮助。

4

6 回答 6

2

2021 年更新:现在有一个 Cloud Run 预览版,用于将机密加载到环境变量或卷中。 https://cloud.google.com/run/docs/configuring/secrets

这个问题现在得到了回答,但是我在使用 Cloud Run with Java & Quarkus 以及使用 GraalVM 创建的本机映像时遇到了类似的问题。

虽然 Cloud Run 在撰写本文时是一项非常有趣的技术,但它缺乏通过 Cloud Run 配置加载机密的能力。在进行本地开发时,这无疑增加了我的应用程序的复杂性。

此外,谷歌的文档真的很差。快速入门缺少一个明确的 Java 示例来获取秘密 [1],而无需使用相同的方法进行设置 - 我希望这是最常见的用例!

javadoc 本身似乎在很大程度上是使用 protobuf 语言自动生成的。有各种类似命名的方法,如getSecret,getSecretVersionaccessSecretVersion

我真的很想看到谷歌在这方面做出一些改进。我认为专门的团队为具有适当文档的通用语言制作库并没有太多要求。

这是我用来加载此信息的片段。它需要 GCP Secret 库和 GCP Cloud Core 库来加载项目 ID。

public String getSecret(final String secretName) {
    LOGGER.info("Going to load secret {}", secretName);

    // SecretManagerServiceClient should be closed after request
    try (SecretManagerServiceClient client = buildClient()) {
        // Latest is an alias to the latest version of a secret
        final SecretVersionName name = SecretVersionName.of(getProjectId(), secretName, "latest");
        return client.accessSecretVersion(name).getPayload().getData().toStringUtf8();
    }
}

private String getProjectId() {

    if (projectId == null) {
        projectId = ServiceOptions.getDefaultProjectId();
    }

    return projectId;
}

private SecretManagerServiceClient buildClient() {
    try {
        return SecretManagerServiceClient.create();
    } catch(final IOException e) {
        throw new RuntimeException(e);
    }
}

[1] - https://cloud.google.com/secret-manager/docs/reference/libraries

于 2021-01-23T18:12:24.263 回答
2

您现在可以从 Secret Manager 中读取机密作为 Cloud Run 中的环境变量。这意味着您可以审核您的机密、设置每个机密的权限、版本机密等,并且您的代码不必更改。

您可以通过 Cloud Console GUI (console.cloud.google.com) 指向密钥,或者在从命令行部署 Cloud Run 服务时进行配置:

gcloud beta run deploy SERVICE --image IMAGE_URL --update-secrets=ENV_VAR_NAME=SECRET_NAME:VERSION

六分钟视频概览:https ://youtu.be/JIE89dneaGo

详细文档:https ://cloud.google.com/run/docs/configuring/secrets

于 2021-05-14T21:30:43.143 回答
2

Google 有您可以在 api 中使用的 Secret manager 客户端库的文档。

这应该可以帮助您做您想做的事 https://cloud.google.com/secret-manager/docs/reference/libraries

由于您没有指定语言,我有一个 nodejs 示例,说明如何使用您的项目 ID 和密码名称访问最新版本的密码。我添加这个的原因是因为文档不清楚您需要提供作为名称的字符串。

 const [version] = await this.secretClient.accessSecretVersion({
        name: `projects/${process.env.project_id}/secrets/${secretName}/versions/latest`,
      });
 return version.payload.data.toString()

请务必在您的 IAM 设置中为您的 api 在 GCP 中使用的服务帐户允许 Secret manager 访问。

于 2021-01-23T12:07:05.037 回答
0

I kinda found a way to use secrets as environment variables.

The following doc (https://cloud.google.com/sdk/gcloud/reference/run/deploy) states:

Specify secrets to mount or provide as environment variables. Keys starting with a forward slash '/' are mount paths. All other keys correspond to environment variables. The values associated with each of these should be in the form SECRET_NAME:KEY_IN_SECRET; you may omit the key within the secret to specify a mount of all keys within the secret. For example: '--update-secrets=/my/path=mysecret,ENV=othersecret:key.json' will create a volume with secret 'mysecret' and mount that volume at '/my/path'. Because no secret key was specified, all keys in 'mysecret' will be included. An environment variable named ENV will also be created whose value is the value of 'key.json' in 'othersecret'. At most one of these may be specified

于 2021-03-05T08:12:43.243 回答
0

Cloud Run 对引用 Secret Manager Secrets 的支持现已全面推出 (GA)。

https://cloud.google.com/run/docs/release-notes#November_09_2021

于 2021-11-19T03:38:42.930 回答
0

下面是一段 Java 代码,用于获取 Cloud Run 项目的所有机密。它需要com.google.cloud/google-cloud-secretmanager工件。

Map<String, String> secrets = new HashMap<>();          
String projectId;
String url = "http://metadata.google.internal/computeMetadata/v1/project/project-id";
HttpURLConnection conn = (HttpURLConnection)(new URL(url).openConnection());
conn.setRequestProperty("Metadata-Flavor", "Google");
try {
   InputStream in = conn.getInputStream();
   projectId = new String(in.readAllBytes(), StandardCharsets.UTF_8);
} finally {
   conn.disconnect();
}               
Set<String> names = new HashSet<>();
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
   ProjectName projectName = ProjectName.of(projectId);
   ListSecretsPagedResponse pagedResponse = client.listSecrets(projectName);
    
   pagedResponse
      .iterateAll()
      .forEach(secret -> { names.add(secret.getName()); });
   for (String secretName : names) {
      String name = secretName.substring(secretName.lastIndexOf("/") + 1);
      SecretVersionName nameParam = SecretVersionName.of(projectId, name, "latest");
      String secretValue = client.accessSecretVersion(nameParam).getPayload().getData().toStringUtf8();
      secrets.put(secretName, secretValue);
   }
}

于 2021-03-15T05:56:31.223 回答