连接到 Blob Storage

作为 BigQuery 管理员,您可以创建一个连接,使数据分析师能够访问存储在 Blob Storage 中的数据。

BigQuery Omni 通过连接访问 Blob Storage 数据。BigQuery Omni 支持 Azure 工作负载身份联合。借助 BigQuery Omni 对 Azure 工作负载身份联合的支持,您可以为租户中的 Azure 应用授予对 Google 服务账号的访问权限。没有任何应用客户端密钥需要由您或 Google 管理。

创建 BigQuery Azure 连接后,您可以查询 Blob Storage 数据将查询结果导出到 Blob Storage

准备工作

所需的角色

配额

如需详细了解配额,请参阅 BigQuery Connection API

创建 Azure 连接

如需创建 Azure 连接,请按以下步骤操作:

  1. 在 Azure 租户中创建应用
  2. 创建 BigQuery Azure 连接
  3. 添加联合凭据
  4. 为 BigQuery Azure AD 应用分配角色

如需详细了解如何使用联合身份凭据访问 Azure 中的数据,请参阅工作负载身份联合

在 Azure 租户中创建应用

如需在 Azure 租户中创建应用,请按照以下步骤操作:

Azure 门户

  1. 在 Azure 门户中,转到应用注册,然后点击新注册

  2. 对于名称,请输入应用的名称。

  3. 对于 Supported account types(支持的账号类型),选择 Accounts in this organizational directory only(仅此组织目录中的账号)。

  4. 如需注册新应用,请点击注册

  5. 记下 Application (client) ID(应用(客户端)ID)。创建连接时,您需要提供此 ID。

    用于创建应用的 Azure 门户

Terraform

将以下内容添加到 Terraform 配置文件中:

  resource "azuread_application" "example" {
    display_name = "bigquery-omni-connector"
  }

  resource "azuread_service_principal" "example" {
    application_id               = azuread_application.example.application_id
    app_role_assignment_required = false
  }

如需了解详情,请参阅如何在 Azure 中注册应用

创建连接

控制台

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. Add(添加)菜单中,选择 External data source(外部数据源)。

  3. 外部数据源窗格中,输入以下信息:

    • 对于连接类型,选择 Azure 上的 BigLake(通过 BigQuery Omni)
    • 对于连接 ID,输入连接资源的标识符。可使用字母、数字、短划线和下划线。
    • 选择您要创建连接的位置。
    • 可选:对于易记名称,输入方便用户使用的连接名称,例如 My connection resource。易记名称可以是任何容易辨识的值,让您以后在需要修改连接资源时能够轻松识别。
    • 可选:对于说明,输入此连接资源的说明。
    • 对于 Azure 租户 ID,输入 Azure 租户 ID,也称为目录(租户)ID。
    • 选中使用联合身份复选框,然后输入 Azure 联合应用(客户端)ID。

      如需了解如何获取 Azure ID,请参阅在 Azure 租户中创建应用

  4. 点击创建连接

  5. 点击转到连接

  6. 连接信息部分中,记下 BigQuery Google 身份的值,即服务账号 ID。此 ID 适用于您授权其访问应用的 Google Cloud 服务账号。

Terraform

  resource "google_bigquery_connection" "connection" {
    connection_id = "omni-azure-connection"
    location      = "azure-eastus2"
    description   = "created by terraform"

    azure {
      customer_tenant_id              = "TENANT_ID"
      federated_application_client_id = azuread_application.example.application_id
    }
  }

TENANT_ID 替换为包含 Blob Storage 账号的 Azure 目录的租户 ID。

bq

使用 bq mk 命令。 如需获取采用 JSON 格式的输出,请使用 --format=json 参数。

bq mk --connection --connection_type='Azure' \
  --tenant_id=TENANT_ID \
  --location=AZURE_LOCATION \
  --federated_azure=true \
  --federated_app_client_id=APP_ID \
  CONNECTION_ID

替换以下内容:

  • TENANT_ID:包含 Azure Storage 账号的 Active Directory 的租户 ID。
  • AZURE_LOCATION:Azure Storage 数据所在的 Azure 区域。BigQuery Omni 支持 azure-eastus2 区域。
  • APP_ID:Azure 应用(客户端)ID。如需了解如何获取此 ID,请参阅在 Azure 租户中创建应用
  • CONNECTION_ID:连接的名称。

输出类似于以下内容:

Connection CONNECTION_ID successfully created
Please add the following identity to your Azure application APP_ID
Identity: SUBJECT_ID

此输出包括以下值:

  • APP_ID:您创建的应用的 ID。

  • SUBJECT_ID:用户授权其访问应用的 Google Cloud 服务账号的 ID。在 Azure 中创建联合凭据时,此值是必需的。

请记下 APP_IDSUBJECT_ID 值,以便在后续步骤中使用。

接下来,为您的应用添加联合凭据。

添加联合凭据

如需创建联合凭据,请按照以下步骤操作:

Azure 门户

  1. 在 Azure 门户中,转到应用注册,然后点击您的应用。

  2. 选择“Certificates & secrets”(证书和密钥)>“Federated credentials”(联合凭据)> 添加凭据。之后,执行以下操作:

    1. Federated credential scenario(联合凭据场景)列表中,选择 Other issuer(其他颁发者)。

    2. 对于颁发者,输入 https://accounts.google.com

    3. 对于 Subject identifier(使用者标识符),输入您在创建连接时获得的 Google Cloud 服务账号的 BigQuery Google 身份

    4. 对于名称,输入凭据的名称。

    5. 点击添加

Terraform

将以下内容添加到 Terraform 配置文件中:

  resource "azuread_application" "example" {
    display_name = "bigquery-omni-connector"
  }

  resource "azuread_service_principal" "example" {
    application_id               = azuread_application.example.application_id
    app_role_assignment_required = false
  }

  resource "azuread_application_federated_identity_credential" "example" {
    application_object_id = azuread_application.example.object_id
    display_name          = "omni-federated-credential"
    description           = "BigQuery Omni federated credential"
    audiences             = ["api://AzureADTokenExchange"]
    issuer                = "https://accounts.google.com"
    subject               = google_bigquery_connection.connection.azure[0].identity
  }

如需了解详情,请参阅将应用配置为信任外部身份提供方

为 BigQuery 的 Azure 应用分配角色

如需为 BigQuery 的 Azure 应用分配角色,请使用 Azure 门户、Azure PowerShell 或 Microsoft Management REST API:

Azure 门户

您可以具有 Microsoft.Authorization/roleAssignments/write 权限的用户身份登录 Azure 门户,以在该门户中执行角色分配。通过角色分配,BigQuery Azure 连接可以访问角色政策中指定的 Azure Storage 数据。

如需使用 Azure 门户添加角色分配,请按照以下步骤操作:

  1. 从 Azure Storage 账号,在搜索栏中输入 IAM

  2. 点击 Access Control (IAM)(访问权限控制 (IAM))。

  3. 点击添加,然后选择添加角色分配

  4. 如需提供只读权限,请选择 Storage Blob Data Reader 角色。如需提供读写权限,请选择 Storage Blob Data Contributor 角色。

  5. 分配权限设置为用户、群组或服务主账号

  6. 点击选择成员

  7. 选择字段中,输入您在 Azure 租户中创建应用时提供的 Azure 应用名称。

  8. 点击保存

如需了解详情,请参阅使用 Azure 门户分配 Azure 角色

Terraform

将以下内容添加到 Terraform 配置文件中:

  resource "azurerm_role_assignment" "data-role" {
    scope                = data.azurerm_storage_account.example.id
    # Read permission for Omni on the storage account
    role_definition_name = "Storage Blob Data Reader"
    principal_id         = azuread_service_principal.example.id
  }

Azure PowerShell

如需在资源范围内为服务主账号添加角色分配,您可以使用 New-AzRoleAssignment 命令

  New-AzRoleAssignment`
   -SignInName APP_NAME`
   -RoleDefinitionName ROLE_NAME`
   -ResourceName RESOURCE_NAME`
   -ResourceType RESOURCE_TYPE`
   -ParentResource PARENT_RESOURCE`
   -ResourceGroupName RESOURCE_GROUP_NAME

请替换以下内容:

  • APP_NAME:应用名称。
  • ROLE_NAME:您要分配的角色名称。
  • RESOURCE_NAME:资源名称。
  • RESOURCE_TYPE:资源类型。
  • PARENT_RESOURCE:父级资源。
  • RESOURCE_GROUP_NAME:资源组名称。

如需详细了解如何使用 Azure PowerShell 添加新的服务主账号,请参阅使用 Azure PowerShell 分配 Azure 角色

Azure CLI

如需在资源范围内为服务主账号添加角色分配,您可以使用 Azure 命令行工具。您必须拥有存储账号的 Microsoft.Authorization/roleAssignments/write 权限才能授予角色。

如需向服务主账号分配角色(例如 Storage Blob Data Reader 角色),请运行 az role assignment create 命令

  az role assignment create --role "Storage Blob Data Reader" \
    --assignee-object-id ${SP_ID} \
    --assignee-principal-type ServicePrincipal \
    --scope   subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/STORAGE_ACCOUNT_NAME

替换以下内容:

  • SP_ID:服务主账号 ID。此服务主账号适用于您创建的应用。如需获取联合连接的服务主账号,请参阅服务主账号对象
  • STORAGE_ACCOUNT_NAME:存储账号名称。
  • RESOURCE_GROUP_NAME:资源组名称。
  • SUBSCRIPTION_ID:订阅 ID。

如需了解详情,请参阅使用 Azure CLI 分配 Azure 角色

Microsoft REST API

如需为服务主账号添加角色分配,您可以向 Microsoft Management 发送 HTTP 请求。

如需调用 Microsoft Graph REST API,请检索应用的 OAuth 令牌。如需了解详情,请参阅在没有用户的情况下获取访问权限。调用 Microsoft Graph REST API 的应用必须具有 Application.ReadWrite.All 应用权限。

如需生成 OAuth 令牌,请运行以下命令:

  export TOKEN=$(curl -X POST \
    https://login.microsoftonline.com/TENANT_ID/oauth2/token \
    -H 'cache-control: no-cache' \
    -H 'content-type: application/x-www-form-urlencoded' \
    --data-urlencode "grant_type=client_credentials" \
    --data-urlencode "resource=https://graph.microsoft.com/" \
    --data-urlencode "client_id=CLIENT_ID" \
    --data-urlencode "client_secret=CLIENT_SECRET" \
  | jq --raw-output '.access_token')

请替换以下内容:

  • TENANT_ID:与包含 Azure Storage 账号的 Azure 目录的 ID 匹配的租户 ID。
  • CLIENT_ID:Azure 客户端 ID。
  • CLIENT_SECRET:Azure 客户端密钥。

获取要为服务主账号分配的 Azure 内置角色的 ID。

以下是一些常见角色:

如需为服务主账号分配角色,请针对 Azure Resource Management REST API 调用 Microsoft Graph REST API:

  export ROLE_ASSIGNMENT_ID=$(uuidgen)
  curl -X PUT \
'https://management.azure.com/subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/STORAGE_ACCOUNT_NAME/providers/Microsoft.Authorization/roleAssignments/ROLE_ASSIGNMENT_ID?api-version=2018-01-01-preview' \
    -H "authorization: Bearer ${TOKEN?}" \
    -H 'cache-control: no-cache' \
    -H 'content-type: application/json' \
    -d '{
        "properties": {
            "roleDefinitionId": "subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/STORAGE_ACCOUNT_NAME/providers/Microsoft.Authorization/roleDefinitions/ROLE_ID",
            "principalId": "SP_ID"
        }
    }'

请替换以下内容:

  • ROLE_ASSIGNMENT_ID:角色 ID。
  • SP_ID:服务主账号 ID。此服务主账号适用于您创建的应用。如需获取联合连接的服务主账号,请参阅服务主对象
  • SUBSCRIPTION_ID:订阅 ID。
  • RESOURCE_GROUP_NAME:资源组名称。
  • STORAGE_ACCOUNT_NAME:存储账号名称。
  • SUBSCRIPTION_ID:订阅 ID。

连接现在可以使用了。但是,Azure 中的角色分配可能存在传播延迟。如果您由于权限问题而无法使用连接,请稍后重试。

与用户共享连接

您可以授予以下角色,以使用户可以查询数据并管理连接:

  • roles/bigquery.connectionUser:允许用户使用连接与外部数据源建立连接,并对其运行查询。

  • roles/bigquery.connectionAdmin:允许用户管理连接。

如需详细了解 BigQuery 中的 IAM 角色和权限,请参阅预定义的角色和权限

从下列选项中选择一项:

控制台

  1. 转到 BigQuery 页面。

    转到 BigQuery

    连接列在项目的外部连接组中。

  2. 探索器窗格中,点击您的项目名称 > 外部连接 > 连接

  3. 详细信息窗格中,点击共享以共享连接。之后,执行以下操作:

    1. 连接权限对话框中,通过添加或修改主账号与其他主账号共享连接。

    2. 点击保存

bq

您不能使用 bq 命令行工具共享连接。如需共享连接,请使用 Google Cloud 控制台或 BigQuery Connections API 方法共享连接。

API

使用 BigQuery Connections REST API 参考文档部分中的 projects.locations.connections.setIAM 方法,并提供一个 policy 资源实例。

Java

试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 BigQuery Java API 参考文档

如需向 BigQuery 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

import com.google.api.resourcenames.ResourceName;
import com.google.cloud.bigquery.connection.v1.ConnectionName;
import com.google.cloud.bigqueryconnection.v1.ConnectionServiceClient;
import com.google.iam.v1.Binding;
import com.google.iam.v1.Policy;
import com.google.iam.v1.SetIamPolicyRequest;
import java.io.IOException;

// Sample to share connections
public class ShareConnection {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "MY_PROJECT_ID";
    String location = "MY_LOCATION";
    String connectionId = "MY_CONNECTION_ID";
    shareConnection(projectId, location, connectionId);
  }

  static void shareConnection(String projectId, String location, String connectionId)
      throws IOException {
    try (ConnectionServiceClient client = ConnectionServiceClient.create()) {
      ResourceName resource = ConnectionName.of(projectId, location, connectionId);
      Binding binding =
          Binding.newBuilder()
              .addMembers("group:example-analyst-group@google.com")
              .setRole("roles/bigquery.connectionUser")
              .build();
      Policy policy = Policy.newBuilder().addBindings(binding).build();
      SetIamPolicyRequest request =
          SetIamPolicyRequest.newBuilder()
              .setResource(resource.toString())
              .setPolicy(policy)
              .build();
      client.setIamPolicy(request);
      System.out.println("Connection shared successfully");
    }
  }
}

后续步骤