连接到 Bitbucket Cloud 主机

本页介绍了如何将 Bitbucket Cloud 主机连接到 Cloud Build。

准备工作

  • 启用 Cloud Build、Secret Manager 和 Compute Engine API。

    启用 API 所需的角色

    如需启用 API,您需要拥有 serviceusage.services.enable 权限。如果您创建了项目,则可能已经通过 Owner 角色 (roles/owner) 获得了此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获得此权限。了解如何授予角色

    启用 API

必需的 IAM 权限

为了确保 具有连接所需的权限,请让您的管理员为您的用户账号上的 授予 Cloud Build Connection Admin (cloudbuild.connectionAdmin) IAM 角色。 如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

您的管理员还可以通过自定义角色或其他预定义角色授予所需的权限。

创建 Bitbucket Cloud 访问令牌

在 Bitbucket Cloud 中创建以下两个访问令牌:

  • 管理员访问令牌 - 用于连接和断开代码库。
  • 读取访问令牌 - 允许 Cloud Build 访问您的源代码。

如需创建这些令牌,请按以下步骤操作:

  1. 登录 Bitbucket Cloud

  2. 按照 Bitbucket Cloud 说明创建与您的代码库项目工作区相关联的访问令牌。

    授予以下权限:

    • 管理员访问令牌:

      • 代码库:读取管理员
      • 拉取请求:读取
      • Webhook:读取写入
    • 读取访问令牌:

      • 代码库:读取
  3. 复制您的令牌,以便在后续程序中使用。

连接到 Bitbucket Cloud 主机

控制台

如需将 Cloud Build 连接到 Bitbucket Cloud 主机,请完成以下步骤:

  1. 在 Google Cloud 控制台中打开代码库页面。

    打开“代码库”页面

    您将看到代码库页面。

  2. 在项目选择器中,选择您的 Google Cloud 项目。

  3. 选择页面顶部的第 2 代标签页。

  4. 点击创建主机连接,将新主机连接到 Cloud Build。

  5. 在左侧面板中,选择 Bitbucket 作为您的来源提供方。

  6. 配置连接部分中,输入以下信息:

    • 区域:为连接选择一个区域。

    • 名称:输入连接的名称。

  7. 主机详细信息部分中,输入以下信息:

    • 选择 Bitbucket Cloud 作为您的托管类型。

    • 工作区:输入 Bitbucket Cloud 代码库的工作区 ID

  8. 可选:如果您想管理用于加密 Bitbucket Cloud 代码库的访问令牌的加密密钥,请前往加密部分,然后选择 Cloud Key Management Service 密钥。如需了解详情,请参阅为 Secret Manager 启用客户管理的加密密钥

  9. 访问令牌部分中,输入以下内容:

    • 管理员访问令牌:输入您之前创建的管理员访问令牌。

    • 读取访问令牌:输入您之前创建的读取访问令牌。

  10. 点击连接

    新关联会显示在代码库页面中。

gcloud

  1. 请完成以下步骤来存储您的凭据:

    1. 通过运行以下命令,将访问令牌存储在Google Cloud 项目的 Secret Manager 中:

      echo -n ADMIN_TOKEN | gcloud secrets create ADMIN_SECRET_NAME --data-file=-
      
      echo -n READ_TOKEN | gcloud secrets create READ_SECRET_NAME --data-file=-
      

      其中:

      • ADMIN_TOKEN 是您的管理员访问令牌。
      • ADMIN_SECRET_NAME 是您要在 Secret Manager 中为管理员访问令牌 Secret 指定的名称。
      • READ_TOKEN 是您的读取访问令牌。
      • READ_SECRET_NAME 是您要在 Secret Manager 中为读取访问令牌 Secret 指定的名称。
    2. 运行以下命令,在 Secret Manager 中创建网络钩子 Secret,其中 WEBHOOK_SECRET_NAME 是您要为网络钩子 Secret 指定的名称:

      echo -n ${ex.(random-uuid)} | gcloud secrets create WEBHOOK_SECRET_NAME --data-file=-
      
    3. 如果您的所有 Secret 不在同一项目中,请运行以下命令,向 Cloud Build 服务代理授予访问权限:

      PN=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)")
      CLOUD_BUILD_SERVICE_ACCOUNT="service-${PN}@gcp-sa-cloudbuild."
      gcloud secrets add-iam-policy-binding ADMIN_SECRET_NAME \
          --member="serviceAccount:${CLOUD_BUILD_SERVICE_ACCOUNT}" \
          --role="roles/secretmanager.secretAccessor"
      
      gcloud secrets add-iam-policy-binding READ_SECRET_NAME \
          --member="serviceAccount:${CLOUD_BUILD_SERVICE_ACCOUNT}" \
          --role="roles/secretmanager.secretAccessor"
      
      gcloud secrets add-iam-policy-binding WEBHOOK_SECRET_NAME \
          --member="serviceAccount:${CLOUD_BUILD_SERVICE_ACCOUNT}" \
          --role="roles/secretmanager.secretAccessor"
      

      其中:

      • PROJECT_ID 是您的 Google Cloud 项目 ID
      • ADMIN_SECRET_NAME 是管理员令牌 Secret 的名称。
      • READ_SECRET_NAME 是读取令牌 Secret 的名称。
      • WEBHOOK_SECRET_NAME 是您的网络钩子 Secret 的名称。
  2. 使用以下命令将 Cloud Build 连接到您的 Bitbucket Cloud 主机:

    gcloud builds connections create bitbucket-cloud CONNECTION_NAME \
        --workspace=WORKSPACE_ID \
        --project=PROJECT_ID \
        --region=REGION \
        --authorizer-token-secret-version=projects/PROJECT_ID/secrets/ADMIN_SECRET_NAME/versions/latest \
        --read-authorizer-token-secret-version=projects/PROJECT_ID/secrets/READ_SECRET_NAME/versions/latest \
        --webhook-secret-secret-version=projects/PROJECT_ID/secrets/WEBHOOK_SECRET_NAME/versions/1
    

    其中:

    • CONNECTION_NAME 是您要为与 Bitbucket Cloud 主机的连接指定的名称。
    • WORKSPACE_ID 是您的 Bitbucket Cloud 代码库的工作区 ID。
    • PROJECT_ID 是您的 Google Cloud 项目 ID
    • REGION 是宿主连接的区域
    • ADMIN_SECRET_NAME 是管理员令牌 Secret 的名称。
    • READ_SECRET_NAME 是读取访问令牌 Secret 的名称。
    • WEBHOOK_SECRET_NAME 是您的网络钩子 Secret 的名称。

Terraform

您可以使用 Terraform 将 Bitbucket Cloud 主机连接到 Cloud Build。

在以下示例中,相应代码段会执行以下操作:

  • 配置 Terraform Google 提供程序。
  • 创建 Secret Manager Secret 以存储 Bitbucket 令牌。
  • 向 Cloud Build 服务代理授予访问 Secret 的必要权限。
  • 创建 Bitbucket Cloud 连接。

    // Configure the Terraform Google provider
    terraform {
      required_providers {
        google = {}
      }
    }
    
    provider "google" {
      project = "PROJECT_ID"
      region = "REGION"
    }
    
    // Create secrets and grant permissions to the Cloud Build service agent
    resource "google_secret_manager_secret" "admin-token-secret" {
        project = "PROJECT_ID"
        secret_id = "ADMIN_TOKEN_NAME"
    
        replication {
            auto {}
        }
    }
    
    resource "google_secret_manager_secret_version" "admin-token-secret-version" {
        secret = google_secret_manager_secret.admin-token-secret.id
        secret_data = "ADMIN_TOKEN_VALUE"
    }
    
    resource "google_secret_manager_secret" "read-token-secret" {
        project = "PROJECT_ID"
        secret_id = "READ_TOKEN_NAME"
    
        replication {
            auto {}
        }
    }
    
    resource "google_secret_manager_secret_version" "read-token-secret-version" {
        secret = google_secret_manager_secret.read-token-secret.id
        secret_data = "READ_TOKEN_VALUE"
    }
    
    resource "google_secret_manager_secret" "webhook-secret-secret" {
        project = "PROJECT_ID"
        secret_id = "WEBHOOK_SECRET_NAME"
    
        replication {
            auto {}
        }
    }
    
    resource "google_secret_manager_secret_version" "webhook-secret-secret-version" {
        secret = google_secret_manager_secret.webhook-secret-secret.id
        secret_data = "WEBHOOK_SECRET_VALUE"
    }
    
    data "google_iam_policy" "p4sa-secretAccessor" {
        binding {
            role = "roles/secretmanager.secretAccessor"
            members = ["serviceAccount:service-PROJECT_NUMBER@gcp-sa-cloudbuild."]
        }
    }
    
    resource "google_secret_manager_secret_iam_policy" "policy-pak" {
      project = google_secret_manager_secret.admin-token-secret.project
      secret_id = google_secret_manager_secret.admin-token-secret.secret_id
      policy_data = data.google_iam_policy.p4sa-secretAccessor.policy_data
    }
    
    resource "google_secret_manager_secret_iam_policy" "policy-rpak" {
      project = google_secret_manager_secret.read-token-secret.project
      secret_id = google_secret_manager_secret.read-token-secret.secret_id
      policy_data = data.google_iam_policy.p4sa-secretAccessor.policy_data
    }
    
    resource "google_secret_manager_secret_iam_policy" "policy-whs" {
      project = google_secret_manager_secret.webhook-secret-secret.project
      secret_id = google_secret_manager_secret.webhook-secret-secret.secret_id
      policy_data = data.google_iam_policy.p4sa-secretAccessor.policy_data
    }
    
    // Create the connection and add the repository resource
    resource "google_cloudbuildv2_connection" "my-connection" {
        project = "PROJECT_ID"
        location = "REGION"
        name = "CONNECTION_NAME"
    
        bitbucket_cloud_config {
            workspace = "WORKSPACE_ID"
            authorizer_credential {
                user_token_secret_version = google_secret_manager_secret_version.admin-token-secret-version.id
            }
            read_authorizer_credential {
                user_token_secret_version = google_secret_manager_secret_version.read-token-secret-version.id
            }
            webhook_secret_secret_version = google_secret_manager_secret_version.webhook-secret-secret-version.id
        }
    
        depends_on = [
            google_secret_manager_secret_iam_policy.policy-pak,
            google_secret_manager_secret_iam_policy.policy-rpak,
            google_secret_manager_secret_iam_policy.policy-whs
        ]
    }
    

其中:

  • PROJECT_ID 是您的 Google Cloud 项目 ID
  • PROJECT_NUMBER 是您的 Google Cloud 项目编号。
  • ADMIN_TOKEN_NAME 是具有 webhookrepositoryrepository:adminpullrequest 范围访问权限的令牌的名称。
  • ADMIN_TOKEN_VALUEADMIN_TOKEN_NAME 的值。
  • READ_TOKEN_NAME 是具有 repository:read 范围的令牌的名称。
  • READ_TOKEN_VALUEREAD_TOKEN_NAME 的值。
  • WEBHOOK_SECRET_NAME 是您的网络钩子 Secret 的名称。
  • WEBHOOK_SECRET_VALUEWEBHOOK_SECRET_NAME 的值。
  • REGION 是连接的区域
  • CONNECTION_NAME 是连接的名称。
  • WORKSPACE_ID 是 Bitbucket Cloud 代码库的工作区 ID。

轮换旧的或过期的 Bitbucket Cloud 访问令牌

如果您的 Bitbucket Cloud 访问令牌过期,Cloud Build 主机连接会与 Bitbucket Cloud 代码库断开连接。因此,在以下情况下,您会看到错误:

  • 当您尝试关联 Bitbucket Cloud 代码库 Cloud Build 连接时,系统会显示 Failed to fetch repositories to link. Check that Cloud Build is still authorized to access data from the selected connection 消息。

  • 触发器页面上,当您点击运行时,系统会打开运行触发器页面并显示 Failed to list branches. You can still enter one manually 消息。

如需为连接轮换旧令牌或过期令牌,请执行以下操作:

  1. 查找与主机连接关联的密钥:

    1. 运行以下命令:

      gcloud builds connections describe CONNECTION_PATH --region=REGION
      

      其中:

      • CONNECTION_PATH 是 Cloud Build 中 Bitbucket Cloud 主机连接的路径,格式为 projects/PROJECT_ID/locations/REGION/connections/CONNECTION_NAME
      • REGION 是连接的区域
    2. 在命令的输出中,查找用户令牌字段的值。readAuthorizerCredential.userTokenSecretVersion 显示 Read 令牌的 Secret Manager 名称,authorizerCredential.userTokenSecretVersion 显示 Admin 令牌的 Secret Manager 名称。这些名称以 Secret 形式存储在 Secret Manager 中。

  2. 在 Bitbucket Cloud 中轮换每个访问令牌:

    1. 前往与 Cloud Build 主机连接关联的 Bitbucket Cloud 代码库。

    2. 按照 Bitbucket 文档中的说明轮换访问令牌。 轮替令牌时,Bitbucket Cloud 会创建具有新凭据的新令牌,并使该令牌的先前版本失效。轮换后的令牌与原始令牌具有相同的权限和范围。

    3. 复制轮换后的令牌的 ID。

  3. 为每个令牌创建新的 Secret 版本:

    1. 在 Google Cloud 控制台中打开 Secret Manager 页面:

      打开 Secret Manager 页面

    2. 对于您轮换的每个令牌,找到您在第 1 步中确定的 Secret 名称,然后依次点击 Actions(操作)和 Add new version(添加新版本)。

    3. 添加新版本窗口中,输入轮换后的令牌的 ID,然后点击添加新版本

如需了解详情,请参阅 Bitbucket Cloud 文档中的访问令牌增强 Bitbucket 中的安全性:为访问令牌引入过期时间

后续步骤