- [Summary](#summary)
  - [as user](#as-user)
- [reference CA.md](#reference-camd)
- [verify client cer's CA 确认我的这个证书的CA是什么](#verify-client-cers-ca-确认我的这个证书的ca是什么)
  - [Using crt get CA](#using-crt-get-ca)
  - [知道签发您证书的 CA 的名称](#知道签发您证书的-ca-的名称)
  - [cat ca.cert](#cat-cacert)
- [Verify User certificate is signed by the CA](#verify-user-certificate-is-signed-by-the-ca)
- [](#)
- [获取指纹](#获取指纹)

# Summary
## as user 
- 使用openssl 验证证书的CA 
  - 使用 openssl x509 -in your_cert.crt -noout -issuer 来读取并知道签发您证书的 CA 的名称
    - 如果是内部 CA，联系您的 IT/安全/PKI 团队，他们会提供你需要的证书和密钥。
    - 如果是公共 CA，访问该 CA 的官方网站下载
- 将上面拿到的证书和密钥文件上传到 Google Cloud 的 `Trust Config` 中。
  - Trust config need
    - root_cert
    - intermediate_cert
- 


# reference [CA.md](./CA.md)

```bash
openssl verify -CAfile root_ca.pem -untrusted intermediate_ca.pem client.crt
```

# verify client cer's CA 确认我的这个证书的CA是什么

好的，当你作为客户端，只有 `.cer`（证书文件）和 `.key`（私钥文件）时，可以通过以下方法使用 `openssl` 来查看颁发该证书的 CA 信息：

**主要方法：使用 `openssl x509` 命令**

1.  **打开终端或命令行界面。**
2.  **执行以下命令：**

    ```bash
    openssl x509 -in your_certificate.cer -noout -issuer -subject
    ```

    *   将 `your_certificate.cer` 替换为你实际的证书文件名（可能是 `.pem`, `.crt` 等扩展名，只要是 PEM 或 DER 格式的证书文件即可）。
    *   `-in your_certificate.cer`: 指定输入的证书文件。
    *   `-noout`: 表示不要输出证书的编码版本，只输出我们要求的信息。
    *   `-issuer`: **这是关键选项，** 它会打印出证书的颁发者（Issuer）信息，也就是签发你这个证书的 CA 的“可分辨名称”（Distinguished Name, DN）。
    *   `-subject`: 同时打印出证书的主题（Subject）信息，也就是这个证书是颁发给谁的（通常是你自己或你的客户端系统），有助于对比区分。

**处理不同的证书格式 (PEM vs DER)**

*   **PEM 格式:** 如果你的 `.cer` 文件是 PEM 格式（文本格式，以 `-----BEGIN CERTIFICATE-----` 开头），上面的命令通常可以直接工作。
*   **DER 格式:** 如果你的 `.cer` 文件是 DER 格式（二进制格式），你需要告诉 `openssl` 输入的格式：

    ```bash
    openssl x509 -inform DER -in your_certificate.cer -noout -issuer -subject
    ```
    *   `-inform DER`: 指定输入文件是 DER 格式。

**解读输出**

命令执行后，你会看到类似这样的输出：

```
issuer=C = US, O = Example Corp, CN = Example Corp Intermediate CA
subject=C = US, ST = California, L = Palo Alto, O = Your Company, OU = Client Systems, CN = my-client-machine.yourcompany.com
```

*   **`issuer=` 后面的内容就是签发你证书的 CA 的信息。** 在这个例子中，CA 是 `CN = Example Corp Intermediate CA, O = Example Corp, C = US`。
*   `subject=` 后面是你这个客户端证书本身的信息。

**重要提示：下一步是获取 CA 证书本身**

知道了 CA 的名字（例如 `Example Corp Intermediate CA`）还不够。为了让服务器（如 GLB）信任你的证书，服务器的管理员需要将**这个 CA 的公共证书文件**（以及可能的更上一级 CA 的证书文件，构成完整的信任链）添加到服务器的 `Trust Config` 中。

*   **你需要向颁发给你 `.cer` 和 `.key` 文件的组织或团队索要对应的 CA 公共证书文件。** 他们必须提供这个（些）文件。通常这会是：
    *   签发你证书的那个 CA 的证书（例如 `Example Corp Intermediate CA.pem`）。
    *   如果该 CA 不是根 CA，还需要其上一级 CA 的证书，一直到根 CA（例如 `Example Corp Root CA.pem`）。
*   将你用 `openssl` 命令找到的 `issuer` 信息提供给他们，可以帮助他们准确地找到你需要哪个 CA 证书。

总之，使用 `openssl x509 -in ... -noout -issuer` 命令可以告诉你**谁**签发了你的证书，但你还需要从签发者那里获取**签发者（CA）自己的证书**，才能完成 mTLS 的配置。


## Using crt get CA 
上面过程我能知道证书的CA.那么我比如要在Trustconf中去导入这些Root CERT和intermidiate_cert那么这2个信息一般从哪里获取?
好的，问得非常好！知道了 CA 的名字（从 `issuer` 字段），下一步就是获取这个 CA 的**实际证书文件**（以及可能的上级 CA 证书文件），以便导入到 Google Cloud 的 `Trust Config` 中。这些文件通常从以下几个来源获取，具体取决于这个 CA 是公共的还是私有的：

1.  **内部/私有 CA (由您自己的组织运营):**
    *   **最直接来源:** 负责管理公司内部 PKI（Public Key Infrastructure）的**IT 部门、安全团队或专门的证书管理团队**。
    *   **你需要联系谁:** 找到负责颁发给你客户端证书 `.cer`/`.key` 的那个团队。
    *   **你需要问什么:**
        *   明确告知他们你需要用于 mTLS 验证的 **CA 公共证书**。
        *   最好提供你通过 `openssl x509 ... -issuer` 命令查到的**颁发者名称 (Issuer DN)**，这能帮助他们准确找到对应的 CA。
        *   明确询问他们需要提供 **① 根 CA (Root CA) 的证书文件** 和 **② 所有相关的中间 CA (Intermediate CA) 的证书文件**。一个完整的信任链可能包含多个中间 CA。
    *   **获取方式:** 他们可能会通过邮件发送 `.pem` 或 `.crt` 文件给你，或者提供一个内部的下载链接或文档库地址。

2.  **公共 CA (如 DigiCert, Let's Encrypt, Sectigo, GoDaddy 等):**
    *   **主要来源:** **CA 的官方网站。** 大多数公共 CA 都会在其网站上提供一个公共存储库 (Repository) 或下载区域，供用户下载它们的根证书和中间证书。
    *   **如何查找:**
        *   访问该 CA 的官方网站（例如 www.digicert.com）。
        *   寻找类似 "Support", "Resources", "Downloads", "Repository", "Root Certificates", "Intermediate Certificates", "CPS (Certificate Policy Statement)" 等链接。
        *   在这些页面中查找与你证书 `issuer` 字段匹配的 CA 证书。例如，如果你看到 `issuer=... CN=DigiCert EV RSA CA G2 ...`，你就需要在 DigiCert 网站上找到名为 "DigiCert EV RSA CA G2" 的中间 CA 证书，以及签发它的根证书（如 "DigiCert Global Root G2"）。
        *   **搜索引擎:** 也可以尝试搜索 "[CA 名称] root certificate download" 或 "[CA 名称] intermediate certificate download"。**务必确保你最终是从 CA 的官方、可信的网站下载！**
    *   **注意:** 公共 CA 的根证书通常已经预装在很多操作系统和浏览器的信任库中，但对于服务器端配置（如 Google Cloud `Trust Config`），你仍然需要**显式地获取并上传**这些证书文件。

3.  **第三方/合作伙伴 CA:**
    *   如果你的客户端证书是由业务合作伙伴颁发的，用于访问他们的系统（或者反过来），那么你需要联系**该合作伙伴的技术联系人或 IT 部门**，按照类似内部 CA 的方式索要他们的 Root CA 和 Intermediate CA 公共证书。

**总结获取步骤:**

1.  **确定 CA 类型:** 根据 `openssl x509 ... -issuer` 的输出判断 CA 是内部的、公共的还是第三方的。看组织名称（O=...）和通用名称（CN=...）通常能提供线索（例如 "DigiCert" vs "MyCompany Internal CA"）。
2.  **联系来源:**
    *   内部 CA -> 联系内部 IT/安全/PKI 团队。
    *   公共 CA -> 访问 CA 官网的证书库/下载区。
    *   第三方 CA -> 联系合作伙伴的技术联系人。
3.  **明确请求:** 要求提供用于建立信任链的**根 CA 公共证书**和所有**中间 CA 公共证书**（通常是 `.pem` 或 `.crt` 格式）。
4.  **获取文件:** 通过邮件、下载链接等方式获取这些证书文件。
5.  **导入 Trust Config:** 将获取到的根 CA 证书文件上传到 `Trust Config` 的 `Trust Anchors`，将中间 CA 证书文件上传到 `Intermediate CAs`。

**关键点:** 你需要的是 CA 的**公共证书**文件（不是私钥！），并且通常需要**完整的信任链**（从直接签发你证书的 CA 一直追溯到自签名的 Root CA）。

## 知道签发您证书的 CA 的名称
那么其实我手里有这个CRT其实是拿不到对应的Root_CERT and Intermediate CA 这个信息的,对么?我仅仅能从CRT知道我的CA是谁颁发的
是的，您的理解基本正确。

您手中的客户端证书文件（`.crt`, `.cer`, `.pem` 等格式通常只包含**该客户端本身**的信息），它确实包含了**谁颁发了它**（Issuer 字段），但这只是一个**名称标识** (Distinguished Name - DN)，比如 `/C=US/O=Example Corp/CN=Example Corp Intermediate CA`。

这个客户端证书文件**通常不会嵌入**：

1.  **颁发它的那个中间 CA 的完整公共证书。**
2.  **该中间 CA 的上级 CA（以及最终的根 CA）的完整公共证书。**

**把证书想象成一张身份证：**

*   你的身份证 (`.crt`) 上写着你的信息 (Subject) 和签发机关 (Issuer) 的名字（比如 “XX市公安局”）。
*   但你的身份证本身并不包含 “XX市公安局” 的公章模板或者更上级部门 “XX省公安厅” 或 “公安部” 的公章模板（Root 和 Intermediate CA 证书）。

**因此：**

*   您可以使用 `openssl x509 -in your_cert.crt -noout -issuer` 来读取并知道签发您证书的 CA 的**名称**。
*   但是，您需要**另外去获取**这个 CA（以及它信任链上的所有上级 CA，直到根 CA）的**实际公共证书文件**（通常是 `.pem` 或 `.crt` 文件），才能将它们导入到 Google Cloud 的 `Trust Config` 中（根证书放入 Trust Anchors，中间证书放入 Intermediate CAs）。

**获取这些 CA 证书文件的途径，正如我们之前讨论的：**

*   如果是内部 CA，联系您的 IT/安全/PKI 团队。
*   如果是公共 CA，访问该 CA 的官方网站下载。
*   如果是合作伙伴 CA，联系合作伙伴。

所以，您需要利用从客户端证书中获取的 `Issuer` 名称信息，去正确的来源索要对应的 Root CA 和 Intermediate CA 的证书文件。


## cat ca.cert
即使你 `cat` 查看 `.crt` 文件的内容（通常是 PEM 格式，看起来像一堆乱码字符夹杂着 `-----BEGIN CERTIFICATE-----` 和 `-----END CERTIFICATE-----`），你看到的只是 **这个客户端证书本身** 的编码表示。

这里面 **不会直接包含** Root CA 或 Intermediate CA 的证书 **内容**。

**你能从 `cat` 的内容（或者更方便地用 `openssl x509 -text` 查看）中获得什么信息？**

1.  **Subject:** 这个证书是颁发给谁的。
2.  **Issuer:** 谁颁发了这个证书（CA 的名称/DN）。**这是你知道要去哪里找 CA 证书的关键线索。**
3.  **Validity Period:** 证书的有效期。
4.  **Public Key:** 属于这个客户端的公钥。
5.  **Serial Number:** 证书的唯一序列号。
6.  **Signature:** 颁发者 CA 对以上信息做的数字签名。
7.  **Extensions (可能包含有用的线索):**
    *   **Authority Information Access (AIA):** *有时* 这个扩展字段会包含一个 URL (`id-ad-caIssuers`)，指向**颁发该证书的那个 CA 的证书**的下载地址。**这是一个潜在的获取中间证书的方法，但并非所有证书都有这个字段，而且它通常只指向直接的颁发者，不一定包含完整的链或根证书。**
    *   **CRL Distribution Points (CDP):** 指向证书吊销列表的地址。
    *   **Key Usage, Extended Key Usage:** 定义证书的用途。

**如何查看 AIA 信息 (如果存在):**

```bash
openssl x509 -in your_cert.crt -noout -text
```

在输出中查找类似 "Authority Information Access" 的部分，看是否有 "CA Issuers - URI:" 后面跟着一个 URL。

**结论:**

*   直接 `cat` 或查看 `.crt` 文件内容，**不能**让你直接复制粘贴出 Root CA 和 Intermediate CA 的证书文本。
*   你能得到的最关键信息是 **Issuer 的名称**。
*   **有时**（如果证书包含 AIA 扩展），你可以从中获得一个下载**直接颁发者 CA 证书**的 URL。但这不能保证获取到完整的信任链（尤其是 Root CA）。
*   获取完整的 Root CA 和 Intermediate CA 证书文件，最可靠的方法仍然是根据 Issuer 名称，去对应的来源（内部 IT、公共 CA 网站、合作伙伴）索要或下载。

所以，你的理解是正确的：`.crt` 文件告诉你“谁发的证”（Issuer Name），但它本身并不附带“发证机关的公章模板”（CA 证书内容）。你得拿着这个“发证机关的名字”去对应的“部门”领取“公章模板”。



# Verify User certificate is signed by the CA 
- 验证某个特定的客户端证书是否真的是由你信任的这个（或这些）CA 签发的
要先要将CA配置到trust config那么我如何确认我允许的这些客户端也就是发起mtls 的用户他们的证书就是我这个对应的ca 签发的？我如何校验？或者明确知道其是否可以通过GLB

问得好！在你将 CA 证书配置到 GCP `TrustConfig` 之后，确实需要一种方法来验证某个特定的客户端证书是否真的是由你信任的这个（或这些）CA 签发的，以及它是否能够通过 GLB 的 mTLS 验证。

你可以使用 `openssl verify` 命令在客户端实际连接 GLB 之前，在本地模拟这个验证过程。

**核心思路：** `openssl verify` 可以检查一个证书（客户端证书）是否能被一个或一组受信任的 CA 证书（对应 `TrustConfig` 中的内容）所验证，并且会检查整个证书链的有效性。

**你需要准备：**

1.  **客户端证书文件:** 你想要验证的那个客户端证书，例如 `client.crt` (PEM 格式)。
2.  **信任锚 CA 证书文件:** 你放入 GCP `TrustConfig` 的那个（或那些）CA 证书。这通常是 Root CA 证书，但也可能是 Intermediate CA 证书（如果你选择直接信任某个 Intermediate CA）。例如 `trust_anchor_ca.pem` (PEM 格式)。
3.  **中间 CA 证书文件 (如果需要):** 如果客户端证书不是由信任锚 CA 直接签发的，你就需要提供从客户端证书到信任锚 CA 之间的所有中间 CA 证书。例如 `intermediate_ca.pem` (PEM 格式)。

**验证命令 (`openssl verify`)**

基本的命令格式是：

```bash
openssl verify -CAfile <信任锚CA证书文件> [-untrusted <中间CA证书文件>] <要验证的客户端证书文件>
```

**参数解释:**

* `-CAfile <信任锚CA证书文件>`: **极其重要**。这里指定的文件必须包含你配置到 GCP `TrustConfig` 中的那个（或那些）**根 CA** 或 **直接信任的中间 CA** 证书。这是 `openssl` 进行验证时的信任起点。
* `-untrusted <中间CA证书文件>`: **通常需要**。如果客户端证书是由中间 CA 签发的（这是常见情况），你需要用这个参数指定包含该中间 CA（以及可能的更上层中间 CA）证书的文件。虽然参数名是 `untrusted`，但这并不意味着这些证书不被信任，而是指它们本身不是最终的信任锚，它们也需要被 `-CAfile` 中的证书来验证。
* `<要验证的客户端证书文件>`: 你想要检查的那个客户端证书文件。

**示例场景:**

**场景 1：客户端证书由 Root CA 直接签发**

* 客户端证书: `client.crt`
* 信任锚 (已放入 TrustConfig): `root_ca.pem`

```bash
openssl verify -CAfile root_ca.pem client.crt
```

**场景 2：客户端证书由 Intermediate CA 签发，而 TrustConfig 中是 Root CA (最常见)**

* 客户端证书: `client.crt` (由 `intermediate_ca.pem` 签发)
* 中间 CA 证书: `intermediate_ca.pem` (由 `root_ca.pem` 签发)
* 信任锚 (已放入 TrustConfig): `root_ca.pem`

```bash
openssl verify -CAfile root_ca.pem -untrusted intermediate_ca.pem client.crt
```
*注意：如果 `intermediate_ca.pem` 文件中包含了多个中间证书（形成一条链），这个命令也能处理。你也可以把所有需要的中间证书合并到一个文件里提供给 `-untrusted`。*

**场景 3：客户端证书由 Intermediate CA 签发，且 TrustConfig 中直接信任这个 Intermediate CA**

* 客户端证书: `client.crt` (由 `intermediate_ca.pem` 签发)
* 信任锚 (已放入 TrustConfig): `intermediate_ca.pem`

```bash
openssl verify -CAfile intermediate_ca.pem client.crt
```
*(这种情况下，因为签发者就是信任锚，理论上不需要 `-untrusted`)*

**如何解读结果:**

* **成功:** 如果命令输出类似 `client.crt: OK`，这表示：
    * 客户端证书的签名有效。
    * 证书链可以成功建立，并且最终连接到了 `-CAfile` 中指定的受信任的 CA。
    * 证书在有效期内。
    * **这强烈表明，如果你的 GCP TrustConfig 配置正确（使用了相同的 `trust_anchor_ca.pem`），GLB 应该会接受这个客户端证书。**

* **失败:** 如果命令输出错误信息，例如：
    * `error ... unable to get issuer certificate`: 通常意味着 `-untrusted` 参数缺失了必要的中间 CA 证书，或者 `-CAfile` 中的 CA 不对。
    * `error ... certificate signature failure`: 签名无效，证书可能被篡改或签发过程有问题。
    * `error ... certificate has expired`: 客户端证书或链中的某个证书已过期。
    * `error ... unable to verify the first certificate`: 无法找到客户端证书的签发者证书，检查 `-untrusted` 和 `-CAfile`。
    * **任何错误输出都意味着 GLB 将会拒绝这个客户端证书的 mTLS 连接。**

**重要注意事项:**

1.  **CA 证书一致性:** `-CAfile` 中使用的 CA 证书必须与你上传到 GCP `TrustConfig` 的证书**完全一致**。
2.  **中间证书的完整性:** 确保证书链所需的所有中间证书都已提供（通过 `-untrusted` 或有时客户端证书文件本身会包含）。
3.  **有效期:** `openssl verify` 会检查证书有效期，确保客户端证书和链中的所有证书都在有效期内。
4.  **吊销检查 (CRL/OCSP):** 默认情况下，`openssl verify` **不执行**证书吊销状态检查。GCP GLB 的 TrustConfig 可以选择性地配置 CRL 检查（尽管不常用），标准的 `openssl verify` 命令无法完全模拟这一点，除非你添加额外的参数（如 `-crl_check`）并提供 CRL 文件。但这对于初步判断证书链是否有效已经足够。
5.  **GLB 配置:** 这个验证只检查证书链本身。它不能保证 GLB 的其他配置（如防火墙规则、Target Proxy 设置）是正确的。

通过 `openssl verify` 命令进行预先检查，是确认客户端证书是否符合 `TrustConfig` 要求、能否通过 GLB mTLS 验证的有效方法。



# 

你可以通过 gcloud certificate-manager trust-configs describe 命令获取 TrustConfig 的详细配置，包括所有已信任的 CA（root 和 intermediate）信息，这是目前校验 TrustConfig 最直接的方式。下面是你可以执行的操作来校验和查看你都信任了哪些证书：

⸻

✅ 1. 查看 TrustConfig 内容（确认信任了哪些 CA）
```bash
gcloud certificate-manager trust-configs describe $TRUSTCONFIG_NAME \
    --location=global \
    --format=json
```

输出中你将看到类似结构：
```json
"trustStores": [
  {
    "trustAnchors": [
      {
        "pemCertificate": "-----BEGIN CERTIFICATE-----\nMIID....\n-----END CERTIFICATE-----"
      }
    ],
    "intermediateCas": [
      {
        "pemCertificate": "-----BEGIN CERTIFICATE-----\nMIIF....\n-----END CERTIFICATE-----"
      }
    ]
  }
]
```
你可以使用 jq 或 shell 解析 pemCertificate 内容提取指纹。

⸻

✅ 2. 校验 TrustConfig 中的证书内容（fingerprint/hash）

有两个方向：

方法 A：提取并生成 SHA256 指纹（推荐方式）

你可以通过下面的 shell 命令快速获取所有证书的 SHA256 指纹进行比对：
```bash
gcloud certificate-manager trust-configs describe $TRUSTCONFIG_NAME \
  --location=global \
  --format="value(trustStores[].trustAnchors[].pemCertificate)" > root.pem

gcloud certificate-manager trust-configs describe $TRUSTCONFIG_NAME \
  --location=global \
  --format="value(trustStores[].intermediateCas[].pemCertificate)" > intermediate.pem
```
# 获取指纹
openssl x509 -noout -fingerprint -sha256 -in root.pem
openssl x509 -noout -fingerprint -sha256 -in intermediate.pem

这可用于比对你当前是否导入了你期望信任的 CA，比如可与你手动计算的值进行比对。

⸻

✅ 3. 自动化比对（结合 GCS fingerprint.json）

如果你已有一份标准的 fingerprint.json（比如结构如下）：

{
  "trusted_certs": [
    {
      "name": "GlobalSign Root CA",
      "fingerprint": "SHA256:AB:CD:EF:..."
    },
    {
      "name": "Some Intermediate",
      "fingerprint": "SHA256:12:34:56:..."
    }
  ]
}

你可以写个脚本读取 trust config 中的证书并计算实际指纹，然后比对这个 json 是否包含或遗漏目标证书。

⸻

✅ 4. 可视化校验方式（备选）

你也可以在 Cloud Console → Certificate Manager → TrustConfig 页面中：
	•	查看所有导入的根证书和中间证书
	•	手动展开每一个证书内容
	•	下载 .pem 内容进行验证

⸻

✅ 总结（推荐方式）

校验内容	推荐操作
已导入哪些证书？	gcloud certificate-manager trust-configs describe
检查证书指纹是否一致？	openssl x509 -fingerprint -sha256 -in cert.pem
与预期证书列表比对？	将 describe 输出证书与 GCS 中 fingerprint.json 比较


⸻

需要我帮你写一个自动校验 trust config 是否包含你定义的 cert 的 shell 脚本吗？可以基于指纹来对比 GCS 中的 JSON。


下面是一个自动化校验 TrustConfig 是否包含你定义的证书的 Shell 脚本，它会执行以下步骤：
	1.	从 TrustConfig 中提取所有 root 和 intermediate 的证书；
	2.	为每个证书计算其 SHA256 指纹；
	3.	下载你定义的 fingerprint.json（从 GCS）；
	4.	校验这些指纹是否都出现在 fingerprint.json 中；
	5.	报告缺失或多余的证书。

⸻

✅ Shell 脚本：校验 TrustConfig 中的 CA 指纹
```bash
#!/bin/bash

set -e

# 设置变量
TRUSTCONFIG_NAME="$1"    # 第一个参数: trust config 名称
GCS_PATH="$2"            # 第二个参数: gs://bucket/path/fingerprint.json
TMP_DIR=$(mktemp -d)
FINGERPRINT_FILE="$TMP_DIR/fingerprint.json"

# 获取 trust config 中的所有 pemCertificate（root + intermediate）
gcloud certificate-manager trust-configs describe "$TRUSTCONFIG_NAME" \
  --location=global \
  --format="value(trustStores[].trustAnchors[].pemCertificate)" \
  > "$TMP_DIR/root.pem"

gcloud certificate-manager trust-configs describe "$TRUSTCONFIG_NAME" \
  --location=global \
  --format="value(trustStores[].intermediateCas[].pemCertificate)" \
  > "$TMP_DIR/intermediate.pem"

# 分离多个证书
awk 'BEGIN {n=0} /BEGIN CERTIFICATE/ {n++; out=sprintf("'"$TMP_DIR"'/cert_%03d.pem",n)} {print > out}' "$TMP_DIR/root.pem" "$TMP_DIR/intermediate.pem"

# 提取指纹
declare -A trustconfig_fingerprints
for cert_file in "$TMP_DIR"/cert_*.pem; do
    fp=$(openssl x509 -noout -fingerprint -sha256 -in "$cert_file" | sed 's/^SHA256 Fingerprint=//;s/://g')
    trustconfig_fingerprints["$fp"]=1
done

# 下载 GCS 中的 fingerprint.json
gsutil cp "$GCS_PATH" "$FINGERPRINT_FILE"
if [[ ! -f "$FINGERPRINT_FILE" ]]; then
    echo "无法下载 fingerprint.json"
    exit 1
fi

# 读取 fingerprint.json 中的指纹
declare -A expected_fingerprints
while read -r line; do
    fp=$(echo "$line" | sed 's/^.*SHA256:\(.*\)".*/\1/;s/://g')
    [[ -n "$fp" ]] && expected_fingerprints["$fp"]=1
done < <(jq -r '.trusted_certs[].fingerprint' "$FINGERPRINT_FILE")

# 比较结果
echo "🔍 比对结果："

for fp in "${!expected_fingerprints[@]}"; do
    if [[ -n "${trustconfig_fingerprints[$fp]}" ]]; then
        echo "✅ 包含预期证书指纹: $fp"
    else
        echo "❌ 缺失证书指纹: $fp"
    fi
done

for fp in "${!trustconfig_fingerprints[@]}"; do
    if [[ -z "${expected_fingerprints[$fp]}" ]]; then
        echo "⚠️ 多余的证书指纹: $fp"
    fi
done

# 清理
rm -rf "$TMP_DIR"
```

⸻

✅ 使用方式

chmod +x verify_trustconfig.sh

./verify_trustconfig.sh my-trustconfig gs://my-bucket/fingerprint.json


⸻

✅ fingerprint.json 示例格式（必须这样写）

{
  "trusted_certs": [
    {
      "name": "GlobalSign Root CA",
      "fingerprint": "SHA256:AB:CD:EF:12:34:56:78:90:..."
    },
    {
      "name": "My Intermediate CA",
      "fingerprint": "SHA256:98:76:54:32:10:FE:DC:BA:..."
    }
  ]
}


⸻

需要我再帮你把这段脚本封装成 Cloud Build 或 Airflow Task 来做定期校验也可以。这个脚本支持你 CI/CD pipeline 中对 TrustConfig 的自动校验场景。是否需要我再帮你加上报告导出（例如 CSV）？


```bash
#!/bin/bash
# get the trust config name
TRUSTCONFIG_NAME=$(gcloud certificate-manager trust-configs list --location=global --format="value(name)")
# format the trust config pem 
gcloud certificate-manager trust-configs describe $TRUSTCONFIG_NAME \
    --location=global \
    |awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/' \
    |sed 's/^[\t]*//' > all_certs.pem
# Using csplit to split the file into individual certificates
csplit -z -f cert- all_certs.pem '/-----BEGIN CERTIFICATE-----/' '{*}'
# Loop through each certificate file
for cert_file in cert-*; do
    # Extract the certificate name
    cert_name=$(openssl x509 -noout -subject -in "$cert_file" | sed -n 's/^.*CN=\(.*\)$/\1/p')
    # Extract the certificate fingerprint
    cert_fingerprint=$(openssl x509 -noout -fingerprint -sha256 -in "$cert_file" | sed 's/^SHA256 Fingerprint=//')
    # Print the certificate name and fingerprint
    echo "Certificate Name: $cert_name"
    echo "Certificate Fingerprint: $cert_fingerprint"
    echo "-------------------------"
done

# housekeeping tmp files
rm cert-* all_certs.pem
```