核發可證明第三方身分的憑證

本教學課程示範如何使用身分反映工作負載身分集區,核發可驗證第三方身分的憑證。

您可以使用身分反映功能,建立與憑證要求者已驗證身分相符的憑證。使用身分反映功能,您可以限制沒有權限的憑證要求者,只能要求主體別名 (SAN) 與其憑證中的身分相符的憑證。

目標

本教學課程提供相關資訊,說明如何搭配使用 CA 服務和工作負載身分集區,以聯盟第三方身分並取得證明該身分的憑證。

事前準備

開始之前,請務必瞭解下列概念:

  • 工作負載身分集區:工作負載身分集區可讓您管理第三方身分識別提供者。詳情請參閱「管理 workload identity pool 和提供者」。
  • Workload Identity 聯盟:Workload Identity 聯盟會運用工作負載身分集區,授予第三方身分服務的存取權。 Google Cloud詳情請參閱「Workload Identity 聯盟」。
  • Security Token Service (STS):Security Token Service 可讓您將第三方憑證換成第一方 (Google Cloud) 權杖。詳情請參閱「安全性權杖服務」。
  • 身分反映:身分反映功能可讓經過驗證的憑證要求者身分,繼續用於所要求的憑證。詳情請參閱「身分反映」。

請確認您擁有下列 IAM 角色

  • 如要管理憑證授權單位 (CA) 和 CA 集區,以及要求憑證,您必須具備 CA 服務作業管理員 (privateca.caManager) 角色。如要進一步瞭解 CA 服務的 IAM 角色,請參閱「使用 IAM 控管存取權」一文。
  • 如要管理 Workload Identity 集區和提供者,您必須具備 Workload Identity 集區管理員 (iam.workloadIdentityPoolAdmin) 角色。
  • 如要建立服務帳戶,您必須具備「服務帳戶管理員」iam.serviceAccountAdmin角色。

如要瞭解如何授予 IAM 角色,請參閱「管理專案、資料夾和機構的存取權」一文。您可以將必要的 IAM 角色授予 Google 帳戶、服務帳戶、Google 群組、Google Workspace 帳戶或 Cloud Identity 網域。

設定工作負載身分集區和提供者

本教學課程說明如何使用 Google OpenID Connect (OIDC) 提供者搭配服務帳戶,做為第三方身分。Google 帳戶 OIDC 提供者會做為第三方身分識別提供者 (IDP),而 Google Cloud 服務帳戶則是這個 IDP 聲明的第三方身分識別範例。

Workload Identity 集區支援各種識別資訊提供者,包括 Microsoft Azure/地端 Active Directory、AWS 和以 SAML 為基礎的識別資訊提供者。

如要設定工作負載身分集區和提供者,請按照下列步驟操作: 1. 如要代表一組受信任的聯盟身分,請建立工作負載身分集區:

```
gcloud iam workload-identity-pools create IDENTITY_POOL_ID --location global --display-name "tutorial-wip"
```

Replace the following:

- <var>IDENTITY_POOL_ID</var>: The unique identifier of the new workload
  identity pool.
  1. 為第三方身分識別提供者建立工作負載身分識別集區提供者:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID --location global --workload-identity-pool IDENTITY_POOL_ID --display-name "tutorial-oidc" --attribute-mapping "google.subject=assertion.sub" --issuer-uri="https://accounts.google.com"
    

    更改下列內容:

    • PROVIDER_ID:您要在 workload identity pool 中建立的身分提供者專屬 ID。

    您可以根據使用情況自訂下列標記:

    • attribute-mapping:這個標記會設定第三方聲明與 Google 主體聲明 google.subject 之間的對應關係。google.subject 是必要對應,您可以使用 CEL 運算式,將其設為任何一或多項聲明。詳情請參閱「定義屬性對應和條件」。
    • issuer-uri:對於 OIDC 提供者,這個標記是公開可存取的端點,Google 會連線至這個端點,驗證第三方權杖。詳情請參閱「準備外部身分識別提供者」。

    如要進一步瞭解如何設定 workload identity 供應商,請參閱「設定 workload identity federation」。

建立 CA 集區和核發 CA

本節說明如何建立 CA 集區,並在其中新增根 CA。您可以使用這個 CA 集區核發反映身分的憑證。如要使用現有的 CA 集區和 CA,可以略過本節。

您也可以選擇建立從屬 CA,而非根 CA。建立根 CA 有助於縮短程序。

  1. 在「DevOps tier」(開發運作層級) 中建立 CA 集區:

    gcloud privateca pools create CA_POOL_ID --location LOCATION --tier devops
    

    更改下列內容:

    • CA_POOL_ID - 簽發憑證的 CA 服務 CA 集區 ID。
    • LOCATION - CA 集區的位置。

    如要進一步瞭解如何建立 CA 集區,請參閱「建立 CA 集區」。

  2. 建立根 CA:

    gcloud privateca roots create CA_ID --pool CA_POOL_ID  --location LOCATION --subject "CN=test,O=test-org"
    

    更改下列內容:

    • CA_ID - 核發憑證的憑證授權單位 ID。
    • CA_POOL_ID - 簽發憑證的 CA 服務 CA 集區 ID。
    • LOCATION - CA 集區的位置。

    如要進一步瞭解如何建立根 CA,請參閱建立根 CA

  3. 啟用從工作負載身分集區聯合的身分,從 CA 集區核發憑證。如要反映身分,要求者必須擁有 CA 服務工作負載憑證要求者 (roles/privateca.workloadCertificateRequester) IAM 角色,才能要求 CreateCertificate

    您可以採用各種精細程度來表示 workload identity pool 主體,從單一主體到集區中所有提供者的身分皆可。詳情請參閱可用的主體或主體集 (使用 Google Cloud CLI 分頁),找出最符合您用途的項目。

    gcloud privateca pools add-iam-policy-binding CA_POOL_ID \
        --location LOCATION \
        --role "roles/privateca.workloadCertificateRequester" \
        --member "group:PROJECT_ID.svc.id.goog:/allAuthenticatedUsers/"
    

    更改下列內容:

    • LOCATION:CA 集區的位置
    • PROJECT_ID:您在其中建立 workload identity pool 的 Google Cloud 專案 ID

建立代表第三方身分的服務帳戶

下列程序假設服務帳戶代表第三方。本節說明如何使用 GenerateIdToken IAM 端點,以 OIDC 權杖的形式擷取第三方身分。視您的用途而定,您可能需要採取不同步驟來取得所選的第三方身分識別權杖。

gcloud iam service-accounts create SERVICE_ACCOUNT

更改下列內容:

  • SERVICE_ACCOUNT - 代表第三方身分的服務帳戶 ID。

核發證明第三方身分的憑證

開始之前,請確認您擁有「服務帳戶符記建立者」roles/iam.serviceAccountTokenCreator身分與存取權管理角色。您需要這個 IAM 角色才能呼叫 GenerateIdToken API。

如要取得第三方身分認證,請按照下列步驟操作:

  1. 向第三方識別資訊提供者取得第三方識別資訊權杖。

    curl

    export ID_TOKEN=`curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;print(json.load(sys.stdin)['token'])"`
    

    更改下列內容:

    • PROJECT_ID:您要在其中建立資源的專案 ID。 Google Cloud

    用戶端程式庫

    如要透過程式輔助方式存取第三方權杖,可以從檔案來源憑證或網址來源憑證取得權杖。詳情請參閱透過用戶端程式庫、gcloud CLI 或 Terraform 進行驗證。在本教學課程中,我們將按照檔案來源憑證工作流程操作。

    將憑證載入憑證要求者可讀取的路徑:

    curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;       print(json.load(sys.stdin)['token']) > /tmp/oidc_token.txt
    

    更改下列內容:

    • PROJECT_ID:要在其中建立資源的專案 ID。
  2. 使用 STS token 端點,將第三方權杖換成同盟 OAuth 權杖:

    curl

    export STS_TOKEN=`curl -L -X POST 'https://sts.googleapis.com/v1/token' -H 'Content-Type: application/json' \
    -d '{
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID",
        "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
        "scope": "https://www.googleapis.com/auth/cloud-platform",
        "subject_token": "'$ID_TOKEN'",
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt"
    }' | python3 -c "import sys;import json; print(json.load(sys.stdin)['access_token'])"`
    

    用戶端程式庫

    1. 建立名為 oidc_token.txt 的憑證設定檔,憑證要求程式碼可讀取該檔案,以執行權杖交換作業。
    gcloud iam workload-identity-pools create-cred-config projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID --output-file=/tmp/cred_config.json --credential-source-file=/tmp/oidc_token.txt
    
    1. 讀取 oidc_token.txt 檔案,在用戶端程式庫中設定授權機制:

    python

    import json
    
    from google.auth import identity_pool
    
    with open('/tmp/cred_config.json', 'r') as f:
      json_config_info = json.loads(f.read())
    credentials = identity_pool.Credentials.from_info(json_config_info)
    scoped_credentials = credentials.with_scopes(
        ['https://www.googleapis.com/auth/cloud-platform'])
    
  3. REFLECTED_SPIFFE主體要求模式向 CA 服務發出要求:

    curl

    1. 選用:如果您沒有 CSR,請執行下列指令來建立 CSR。

      export TUTORIAL_CSR=$(openssl req -newkey rsa:2048 -nodes -subj / -keyout tutorial_do_not_use.key)
      
    2. 使用 CSR、生命週期和反映的主體要求模式要求憑證:

      curl -H "Authorization: Bearer $(echo $STS_TOKEN)" https://privateca.googleapis.com/v1/projects/PROJECT_NUMBER/locations/LOCATION/caPools/CA_POOL_ID/certificates\?alt\=json  -X POST -H "Content-Type: application/json" -H 'Accept: application/json' --data '{"lifetime": "100s", "pemCsr": "'$TUTORIAL_CSR'", "subjectMode": "REFLECTED_SPIFFE"}'
      

    用戶端程式庫

    如要將第一方權杖轉送至 CA 服務,您必須建立具備憑證的用戶端。接著,您可以使用這個經過驗證的用戶端提出憑證要求:

    1. 啟動已通過驗證的 CA 服務用戶端:

      python

      caServiceClient = privateca_v1.CertificateAuthorityServiceClient(credentials=scoped_credentials)
      
    2. 要求憑證。

      Python

      如要向 CA 服務進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

      import google.cloud.security.privateca_v1 as privateca_v1
      from google.protobuf import duration_pb2
      
      
      def create_certificate(
          project_id: str,
          location: str,
          ca_pool_name: str,
          ca_name: str,
          certificate_name: str,
          common_name: str,
          domain_name: str,
          certificate_lifetime: int,
          public_key_bytes: bytes,
      ) -> None:
          """
          Create a Certificate which is issued by the Certificate Authority present in the CA Pool.
          The key used to sign the certificate is created by the Cloud KMS.
      
          Args:
              project_id: project ID or project number of the Cloud project you want to use.
              location: location you want to use. For a list of locations, see: https://cloud.google.com/certificate-authority-service/docs/locations.
              ca_pool_name: set a unique name for the CA pool.
              ca_name: the name of the certificate authority which issues the certificate.
              certificate_name: set a unique name for the certificate.
              common_name: a title for your certificate.
              domain_name: fully qualified domain name for your certificate.
              certificate_lifetime: the validity of the certificate in seconds.
              public_key_bytes: public key used in signing the certificates.
          """
      
          caServiceClient = privateca_v1.CertificateAuthorityServiceClient()
      
          # The public key used to sign the certificate can be generated using any crypto library/framework.
          # Also you can use Cloud KMS to retrieve an already created public key.
          # For more info, see: https://cloud.google.com/kms/docs/retrieve-public-key.
      
          # Set the Public Key and its format.
          public_key = privateca_v1.PublicKey(
              key=public_key_bytes,
              format_=privateca_v1.PublicKey.KeyFormat.PEM,
          )
      
          subject_config = privateca_v1.CertificateConfig.SubjectConfig(
              subject=privateca_v1.Subject(common_name=common_name),
              subject_alt_name=privateca_v1.SubjectAltNames(dns_names=[domain_name]),
          )
      
          # Set the X.509 fields required for the certificate.
          x509_parameters = privateca_v1.X509Parameters(
              key_usage=privateca_v1.KeyUsage(
                  base_key_usage=privateca_v1.KeyUsage.KeyUsageOptions(
                      digital_signature=True,
                      key_encipherment=True,
                  ),
                  extended_key_usage=privateca_v1.KeyUsage.ExtendedKeyUsageOptions(
                      server_auth=True,
                      client_auth=True,
                  ),
              ),
          )
      
          # Create certificate.
          certificate = privateca_v1.Certificate(
              config=privateca_v1.CertificateConfig(
                  public_key=public_key,
                  subject_config=subject_config,
                  x509_config=x509_parameters,
              ),
              lifetime=duration_pb2.Duration(seconds=certificate_lifetime),
          )
      
          # Create the Certificate Request.
          request = privateca_v1.CreateCertificateRequest(
              parent=caServiceClient.ca_pool_path(project_id, location, ca_pool_name),
              certificate_id=certificate_name,
              certificate=certificate,
              issuing_certificate_authority_id=ca_name,
          )
          result = caServiceClient.create_certificate(request=request)
      
          print("Certificate creation result:", result)
      
      

    3. 驗證憑證。您的憑證應包含單一 URI SAN 的主體。驗證身分的 SAN 格式如下:

      spiffe://IDENTITY_POOL_ID.PROJECT_NUMBER.global.workload.id.goog/subject/<oidc_subject_number>
      

      取代:

      • IDENTITY_POOL_ID:Workload Identity 集區的專屬 ID。
      • PROJECT_NUMBER:您建立工作負載身分集區的專案編號。

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取您按照本文建立的 CA 服務資源費用,請使用 Google Cloud CLI 執行下列作業:

  1. 刪除您建立的 CA。

    1. 停用 CA:

      gcloud privateca roots disable CA_ID --pool CA_POOL_ID  --location LOCATION
      

      取代:

      • CA_ID:CA 的專屬 ID。
      • CA_POOL_ID:CA 集區的專屬 ID。
      • LOCATION:CA 集區的位置。
    2. 刪除 CA:

      gcloud privateca roots delete CA_ID --pool CA_POOL_ID  --location LOCATION --ignore-active-certificates
      

      取代:

      • CA_ID:CA 的專屬 ID。
      • CA_POOL_ID:CA 集區的專屬 ID。
      • LOCATION:CA 集區的位置。
  2. 刪除您建立的 CA 集區。

    gcloud privateca pools delete CA_POOL_ID --location LOCATION
    

    取代:

    • CA_POOL_ID:CA 集區的專屬 ID。
    • LOCATION:CA 集區的位置。

    如要進一步瞭解 gcloud privateca pools delete 指令,請參閱 gcloud privateca pools delete

  3. 刪除您建立的工作負載身分集區:

    gcloud iam workload-identity-pools delete IDENTITY_POOL_ID --location global
    

    取代:

    • IDENTITY_POOL_ID:Workload Identity Pool 的專屬 ID。
  4. 刪除您建立的服務帳戶:

    gcloud iam service-accounts delete SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com
    

    取代:

    • SERVICE_ACCOUNT:workload identity pool 的專屬 ID。
    • PROJECT_ID:擁有服務帳戶的專案。

CA 服務工作負載憑證要求者 (privateca.workloadCertificateRequester) IAM 角色會將核發憑證的主體限制為要求者的身分。確保使用身分反映功能的使用者或工作負載,只獲授 CA 服務工作負載憑證要求者 (privateca.workloadCertificateRequester) IAM 角色。為遵守最低權限原則,您可以避免授予 CA Service Certificate Requester (privateca.certificateRequester) IAM 角色。

後續步驟