过滤区域级 Secret 和 Secret 版本

本页介绍了在 Secret Manager 中过滤 Secret 和 Secret 版本的过程。 在包含大量 secret 的环境中,过滤功能有助于快速识别特定 secret 或版本,而无需手动滚动浏览整个列表。您可以根据标签、创建日期或密钥名称中的特定模式等条件进行过滤,从而有针对性地管理特定组的密钥。

在 Secret Manager 中,您可以使用 Google Cloud 控制台中的过滤选项或在 API 调用中指定过滤条件来过滤密钥和密钥版本。在 Google Cloud CLI 中,您可以在列出密文时添加 filter 字符串,以过滤密文和密文版本。

过滤 Secret

如需过滤 Secret,请使用以下方法之一:

控制台

  1. 转到 Google Cloud 控制台中的 Secret Manager 页面。

    前往 Secret Manager

  2. Secret Manager 页面上,点击 Regional secrets(区域级 Secret)标签页。

  3. 地区性密钥表中,点击过滤字段。

  4. 选择过滤条件属性及其对应的值,例如 Location:asia-east1

    系统会根据输入的值自动过滤表格。结果会按名称升序排列。

gcloud

在使用下面的命令数据之前,请先进行以下替换:

  • LOCATION:密钥的 Google Cloud 位置
  • FILTER:过滤条件字符串,例如 name:asecret OR name:bsecret。 gcloud CLI 还支持正则表达式,例如 name ~ "secret_ab.*"

执行以下命令:

Linux、macOS 或 Cloud Shell

gcloud secrets list --location=LOCATION --filter="FILTER"

Windows (PowerShell)

gcloud secrets list --location=LOCATION --filter="FILTER"

Windows (cmd.exe)

gcloud secrets list --location=LOCATION --filter="FILTER"

REST

在使用任何请求数据之前,请先进行以下替换:

  • LOCATION:密钥的 Google Cloud 位置
  • PROJECT_ID:Google Cloud 项目 ID
  • FILTER:过滤器字符串。过滤条件指定为 filter 查询字符串参数,并且必须采用网址编码。例如,过滤条件 name:asecret OR name:bsecretname%3Aasecret+OR+name%3Absecret 形式进行网址编码。API 不支持正则表达式。

HTTP 方法和网址:

GET https://secretmanager.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/secrets?filter=FILTER

请求 JSON 正文:

{}

如需发送请求,请选择以下方式之一:

curl

将请求正文保存在名为 request.json 的文件中,然后执行以下命令:

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://secretmanager.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/secrets?filter=FILTER"

PowerShell

将请求正文保存在名为 request.json 的文件中,然后执行以下命令:

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method GET `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://secretmanager.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/secrets?filter=FILTER" | Select-Object -Expand Content

您应该收到类似以下内容的 JSON 响应:

{
  "secrets": [
    {
      "name": "projects/PROJECT_ID/locations/LOCATION/secrets/SECRET_ID",
      "createTime": "2024-09-02T07:14:00.281541Z",
      "etag": "\"16211dd90b37e7\""
    }
  ]
}

Go

如需运行此代码,请先设置 Go 开发环境安装 Secret Manager Go SDK。在 Compute Engine 或 GKE 上,您必须使用 cloud-platform 范围进行身份验证

import (
	"context"
	"fmt"
	"io"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
)

// listSecretsWithFilter lists all filter-matching secrets in the given project.
func ListRegionalSecretsWithFilter(w io.Writer, projectId, locationId string, filter string) error {
	// parent := "projects/my-project/locations/my-location"
	// Follow https://cloud.google.com/secret-manager/docs/filtering
	// for filter syntax and examples.
	// filter := "name:name-substring"

	// Create the client.
	ctx := context.Background()
	//Endpoint to send the request to regional server
	endpoint := fmt.Sprintf("secretmanager.%s.rep.googleapis.com:443", locationId)
	client, err := secretmanager.NewClient(ctx, option.WithEndpoint(endpoint))

	if err != nil {
		return fmt.Errorf("failed to create regional secretmanager client: %w", err)
	}
	defer client.Close()

	parent := fmt.Sprintf("projects/%s/locations/%s", projectId, locationId)
	// Build the request.
	req := &secretmanagerpb.ListSecretsRequest{
		Parent: parent,
		Filter: filter,
	}

	// Call the API.
	it := client.ListSecrets(ctx, req)
	for {
		resp, err := it.Next()
		if err == iterator.Done {
			break
		}

		if err != nil {
			return fmt.Errorf("failed to list regional secrets: %w", err)
		}

		fmt.Fprintf(w, "Found regional secret %s\n", resp.Name)
	}

	return nil
}

Java

如需运行此代码,请先设置 Java 开发环境安装 Secret Manager Java SDK。 在 Compute Engine 或 GKE 上,您必须使用 cloud-platform 范围进行身份验证

import com.google.cloud.secretmanager.v1.ListSecretsRequest;
import com.google.cloud.secretmanager.v1.LocationName;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient.ListSecretsPage;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient.ListSecretsPagedResponse;
import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings;
import java.io.IOException;

public class ListRegionalSecretsWithFilter {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.

    // Your GCP project ID.
    String projectId = "your-project-id";
    // Location of the secret.
    String locationId = "your-location-id";
    // Filter to be applied. 
    // See https://cloud.google.com/secret-manager/docs/filtering
    // for filter syntax and examples.
    String filter = "name:your-secret-substring AND expire_time<2022-01-01T00:00:00Z";
    listRegionalSecretsWithFilter(projectId, locationId, filter);
  }

  // List all secrets for a project
  public static ListSecretsPage listRegionalSecretsWithFilter(
      String projectId, String locationId, String filter) throws IOException {

    // Endpoint to call the regional secret manager sever
    String apiEndpoint = String.format("secretmanager.%s.rep.googleapis.com:443", locationId);
    SecretManagerServiceSettings secretManagerServiceSettings =
        SecretManagerServiceSettings.newBuilder().setEndpoint(apiEndpoint).build();

    // Initialize the client that will be used to send requests. This client only needs to be
    // created once, and can be reused for multiple requests.
    try (SecretManagerServiceClient client = 
        SecretManagerServiceClient.create(secretManagerServiceSettings)) {
      // Build the parent name.
      LocationName parent = LocationName.of(projectId, locationId);

      // Get filtered secrets.
      ListSecretsRequest request =
          ListSecretsRequest.newBuilder()
              .setParent(parent.toString())
              .setFilter(filter)
              .build();

      ListSecretsPagedResponse pagedResponse = client.listSecrets(request);

      // List all secrets.
      pagedResponse
          .iterateAll()
          .forEach(
              secret -> {
                System.out.printf("Regional secret %s\n", secret.getName());
              });

      return pagedResponse.getPage();
    }
  }
}

Python

如需运行此代码,请先设置 Python 开发环境安装 Secret Manager Python SDK。在 Compute Engine 或 GKE 上,您必须使用 cloud-platform 范围进行身份验证

# Import the Secret Manager client library.
from google.cloud import secretmanager_v1


def list_regional_secrets_with_filter(
    project_id: str, location_id: str, filter_str: str
) -> None:
    """
    Lists all regional secrets in the given project.
    """

    # Endpoint to call the regional secret manager sever.
    api_endpoint = f"secretmanager.{location_id}.rep.googleapis.com"

    # Create the Secret Manager client.
    client = secretmanager_v1.SecretManagerServiceClient(
        client_options={"api_endpoint": api_endpoint},
    )

    # Build the resource name of the parent project.
    parent = f"projects/{project_id}/locations/{location_id}"

    # List all secrets.
    for secret in client.list_secrets(request={"parent": parent, "filter": filter_str}):
        print(f"Found secret: {secret.name}")

过滤 Secret 版本

如需过滤 Secret 版本,请执行以下操作:

  • 在 Google Cloud 控制台中,选择要访问其版本的密钥,然后使用版本表中的过滤条件选项。

  • 如果您使用的是 Google Cloud CLI 或 Secret Manager API,请在列出 Secret 版本时添加 filter 字符串。

过滤条件示例

使用场景 过滤
名称包含 mysecret 子字符串的密文 name:mysecret
具有特定标签的密文 labels.environment=production
在日期/时间范围内创建的 Secret create_time<2021-01-01T06:00:00Z AND create_time>2021-01-01T12:00:00Z
具有自动复制功能的密文 replication.automatic:*
具有用户管理的复制功能但未存储在任一给定区域中的密文 replication.user_managed.replicas.location:* AND NOT replication.user_managed.replicas.location:(us-central1 OR us-east1)
使用 CMEK 密钥加密的密文 replication.user_managed.replicas.customerManagedEncryption:*
使用特定 CMEK 加密的 Secret replication.user_managed.replicas.customerManagedEncryption.kmsKeyName=projects/p/locations/us-central1/keyRings/kr/cryptoKeys/my-cmek-key
没有轮替周期的密文 NOT rotation.next_rotation_time:*
轮替周期超过 30 天的密文 rotation.rotation_period>259200s
设置了过期时间的密文 expire_time:*
在指定日期之前过期的密文 expire_time<2021-07-31
已启用或已停用的版本 state:(ENABLED OR DISABLED)
已销毁的版本,在指定日期后销毁 state:DESTROYED AND destroy_time>2021-01-01

过滤器语法

过滤器语法由要过滤的对象的一个或多个字段上的表达式组成。

您可以使用以下表达式运算符。

运算符 说明
= 相等。
> 大于。
< 小于。
>= 大于或等于。
<= 小于或等于。
!=
-
NOT
不相等。 以下表达式是等效的:
name!="topsecret"
-name="topsecret"
NOT name="topsecret"
:

包含关系。这是一个不区分大小写的子字符串匹配。

例如,name:"myapp" 用于过滤资源名称中包含 myapp(不区分大小写)的资源。

AND

逻辑与。

空格相当于 AND,因此以下表达式是等效的:
name:"myapp" AND name:"secret1"
name:"myapp" name:"secret1"

OR 逻辑或。
*

通配符。

可用作独立项,其中 field:* 表示已设置 field

与 Cloud Search API 一致,除非使用圆括号明确定义其他顺序,否则 OR 运算会在 AND 运算之前进行求值。

过滤 time 值时,请将时间编码为 RFC 3399 格式的字符串,例如 2020-10-15T01:30:15Z

访问子字段时,请使用点式语法。例如,Secret 资源可能包含 labels 字段,其值为键值对 map。如果使用 color 标签,您可以按子字段 labels.color 过滤 Secret 结果,如下所示:

labels.color=red

如果您只想列出设置了 color 标签的密文,请使用通配符:

labels.color:*

用英文引号引起来的一个字符串会被解释为单个值,而不是一系列值。

过滤字段

您可以按 SecretSecretVersion 对象的任何字段进行过滤。

list 方法 可过滤字段的链接
projects.secrets.list Secret 字段
projects.secrets.versions.list SecretVersion 字段

结果总数

如果在 list 请求中设置了 filter,则响应不会指明结果总数(在响应中,total_size=0)。

后续步骤