Partilhar via


Usar uma entidade de serviço com o conector Spark 3 para o Azure Cosmos DB para NoSQL

Neste artigo, você aprenderá a criar um aplicativo e uma entidade de serviço do Microsoft Entra que podem ser usados com controle de acesso baseado em função. Em seguida, você pode usar essa entidade de serviço para se conectar a uma conta do Azure Cosmos DB para NoSQL a partir do Spark 3.

Pré-requisitos

Criar um segredo e registrar credenciais

Nesta seção, você cria um segredo do cliente e registra o valor para uso posterior.

  1. Abra o portal do Azure.

  2. Vá para o seu aplicativo Microsoft Entra existente.

  3. Vá para a página Certificados & segredos . Em seguida, crie um novo segredo. Salve o valor Segredo do Cliente para usar mais adiante neste artigo.

  4. Vá para a página Visão geral . Localize e registre os valores para ID do aplicativo (cliente), ID do objeto e ID do diretório (locatário). Você também usa esses valores mais adiante neste artigo.

  5. Vá para sua conta existente do Azure Cosmos DB para NoSQL.

  6. Registre o valor de URI na página Visão geral . Registe também os valores de ID de Subscrição e Grupo de Recursos. Você usa esses valores posteriormente neste artigo.

Criar uma definição e uma atribuição

Nesta seção, você cria uma definição de função de ID do Microsoft Entra. Em seguida, você atribui essa função com permissões para ler e gravar itens nos contêineres.

  1. Crie uma função usando o az role definition create comando. Passe o nome da conta do Azure Cosmos DB para NoSQL e o grupo de recursos, seguido por um corpo de JSON que define a função personalizada. A função também tem como escopo o nível da conta usando /. Certifique-se de fornecer um nome exclusivo para sua função usando a RoleName propriedade do corpo da solicitação.

    az cosmosdb sql role definition create \
        --resource-group "<resource-group-name>" \
        --account-name "<account-name>" \
        --body '{
            "RoleName": "<role-definition-name>",
            "Type": "CustomRole",
            "AssignableScopes": ["/"],
            "Permissions": [{
                "DataActions": [
                    "Microsoft.DocumentDB/databaseAccounts/readMetadata",
                    "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
                    "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
                ]
            }]
        }'
    
  2. Liste a definição de função que você criou para buscar seu identificador exclusivo na saída JSON. Registre o id valor da saída JSON.

    az cosmosdb sql role definition list \
        --resource-group "<resource-group-name>" \
        --account-name "<account-name>"
    
    [
      {
        ...,
        "id": "/subscriptions/<subscription-id>/resourceGroups/<resource-grou-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/sqlRoleDefinitions/<role-definition-id>",
        ...
        "permissions": [
          {
            "dataActions": [
              "Microsoft.DocumentDB/databaseAccounts/readMetadata",
              "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
              "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
            ],
            "notDataActions": []
          }
        ],
        ...
      }
    ]
    
  3. Use az cosmosdb sql role assignment create para criar uma atribuição de função. Substitua <aad-principal-id> pela ID do objeto que você registrou anteriormente neste artigo. Além disso, substitua <role-definition-id> id pelo valor obtido ao executar o az cosmosdb sql role definition list comando em uma etapa anterior.

    az cosmosdb sql role assignment create \
        --resource-group "<resource-group-name>" \
        --account-name "<account-name>" \
        --scope "/" \
        --principal-id "<account-name>" \
        --role-definition-id "<role-definition-id>"
    

Usar uma entidade de serviço

Agora que você criou um aplicativo e uma entidade de serviço do Microsoft Entra, criou uma função personalizada e atribuiu essas permissões de função à sua conta do Azure Cosmos DB para NoSQL, você deve ser capaz de executar um bloco de anotações.

  1. Abra seu espaço de trabalho do Azure Databricks.

  2. Na interface do espaço de trabalho, crie um novo cluster. Configure o cluster com estas configurações, no mínimo:

    Versão Value
    Versão em tempo de execução 13.3 LTS (Scala 2.12, Spark 3.4.1)
  3. Use a interface do espaço de trabalho para procurar pacotes Maven do Maven Central com uma ID de Grupo de com.azure.cosmos.spark. Instale o pacote especificamente para o Spark 3.4 com uma ID de artefato prefixada com azure-cosmos-spark_3-4 o cluster.

  4. Por fim, crie um novo bloco de anotações.

    Gorjeta

    Por padrão, o bloco de anotações é anexado ao cluster criado recentemente.

  5. No bloco de anotações, defina as definições de configuração do conector do Azure Cosmos DB Spark para o ponto de extremidade da conta NoSQL, o nome do banco de dados e o nome do contêiner. Use os valores ID de Assinatura, Grupo de Recursos, ID de Aplicativo (cliente), ID de Diretório (locatário) e Segredo do Cliente registrados anteriormente neste artigo.

    # Set configuration settings
    config = {
      "spark.cosmos.accountEndpoint": "<nosql-account-endpoint>",
      "spark.cosmos.auth.type": "ServicePrincipal",
      "spark.cosmos.account.subscriptionId": "<subscription-id>",
      "spark.cosmos.account.resourceGroupName": "<resource-group-name>",
      "spark.cosmos.account.tenantId": "<entra-tenant-id>",
      "spark.cosmos.auth.aad.clientId": "<entra-app-client-id>",
      "spark.cosmos.auth.aad.clientSecret": "<entra-app-client-secret>",
      "spark.cosmos.database": "<database-name>",
      "spark.cosmos.container": "<container-name>"        
    }    
    
    // Set configuration settings
    val config = Map(
      "spark.cosmos.accountEndpoint" -> "<nosql-account-endpoint>",
      "spark.cosmos.auth.type" -> "ServicePrincipal",
      "spark.cosmos.account.subscriptionId" -> "<subscription-id>",
      "spark.cosmos.account.resourceGroupName" -> "<resource-group-name>",
      "spark.cosmos.account.tenantId" -> "<entra-tenant-id>",
      "spark.cosmos.auth.aad.clientId" -> "<entra-app-client-id>",
      "spark.cosmos.auth.aad.clientSecret" -> "<entra-app-client-secret>",
      "spark.cosmos.database" -> "<database-name>",
      "spark.cosmos.container" -> "<container-name>" 
    )
    
  6. Configure a API de catálogo para gerenciar a API para recursos NoSQL usando o Spark.

    # Configure Catalog Api
    spark.conf.set("spark.sql.catalog.cosmosCatalog", "com.azure.cosmos.spark.CosmosCatalog")
    spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.accountEndpoint", "<nosql-account-endpoint>")
    spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.type", "ServicePrincipal")
    spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.account.subscriptionId", "<subscription-id>")
    spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.account.resourceGroupName", "<resource-group-name>")
    spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.account.tenantId", "<entra-tenant-id>")
    spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientId", "<entra-app-client-id>")
    spark.conf.set("spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientSecret", "<entra-app-client-secret>")
    
    // Configure Catalog Api
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog", "com.azure.cosmos.spark.CosmosCatalog")
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.accountEndpoint", "<nosql-account-endpoint>")
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.type", "ServicePrincipal")
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.account.subscriptionId", "<subscription-id>")
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.account.resourceGroupName", "<resource-group-name>")
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.account.tenantId", "<entra-tenant-id>")
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientId", "<entra-app-client-id>")
    spark.conf.set(s"spark.sql.catalog.cosmosCatalog.spark.cosmos.auth.aad.clientSecret", "<entra-app-client-secret>")
    
  7. Crie um novo banco de dados usando CREATE DATABASE IF NOT EXISTSo . Certifique-se de fornecer o nome do banco de dados.

    # Create a database using the Catalog API
    spark.sql("CREATE DATABASE IF NOT EXISTS cosmosCatalog.{};".format("<database-name>"))
    
    // Create a database using the Catalog API
    spark.sql(s"CREATE DATABASE IF NOT EXISTS cosmosCatalog.<database-name>;")
    
  8. Crie um novo contêiner usando o nome do banco de dados, o nome do contêiner, o caminho da chave de partição e os valores de taxa de transferência especificados.

    # Create a products container using the Catalog API
    spark.sql("CREATE TABLE IF NOT EXISTS cosmosCatalog.{}.{} USING cosmos.oltp TBLPROPERTIES(partitionKeyPath = '{}', manualThroughput = '{}')".format("<database-name>", "<container-name>", "<partition-key-path>", "<throughput>"))
    
    // Create a products container using the Catalog API
    spark.sql(s"CREATE TABLE IF NOT EXISTS cosmosCatalog.<database-name>.<container-name> using cosmos.oltp TBLPROPERTIES(partitionKeyPath = '<partition-key-path>', manualThroughput = '<throughput>')")
    
  9. Crie um conjunto de dados de exemplo.

    # Create sample data    
    products = (
      ("68719518391", "gear-surf-surfboards", "Yamba Surfboard", 12, 850.00, False),
      ("68719518371", "gear-surf-surfboards", "Kiama Classic Surfboard", 25, 790.00, True)
    )
    
    // Create sample data
    val products = Seq(
      ("68719518391", "gear-surf-surfboards", "Yamba Surfboard", 12, 850.00, false),
      ("68719518371", "gear-surf-surfboards", "Kiama Classic Surfboard", 25, 790.00, true)
    )
    
  10. Use spark.createDataFrame e a configuração OLTP (processamento de transações online) salvas anteriormente para adicionar dados de amostra ao contêiner de destino.

    # Ingest sample data    
    spark.createDataFrame(products) \
      .toDF("id", "category", "name", "quantity", "price", "clearance") \
      .write \
      .format("cosmos.oltp") \
      .options(config) \
      .mode("APPEND") \
      .save()
    
    // Ingest sample data
    spark.createDataFrame(products)
      .toDF("id", "category", "name", "quantity", "price", "clearance")
      .write
      .format("cosmos.oltp")
      .options(config)
      .mode("APPEND")
      .save()
    

    Gorjeta

    Neste exemplo de início rápido, as credenciais são atribuídas a variáveis em texto não criptografado. Por motivos de segurança, recomendamos que utilize segredos. Para obter mais informações sobre como configurar segredos, consulte Adicionar segredos à configuração do Spark.