Utilisez un principal de service avec le connecteur Spark 3 pour Azure Cosmos DB for NoSQL
Cet article explique comment créer une application et un principal de service Microsoft Entra pouvant être utilisés avec le contrôle d’accès en fonction du rôle. Vous pouvez ensuite utiliser ce principal de service pour vous connecter à un compte Azure Cosmos DB for NoSQL à partir de Spark 3.
Prérequis
- Un compte Azure Cosmos DB for NoSQL déjà créé :
- Si vous disposez d’un abonnement Azure, créez un compte.
- Vous ne possédez pas d’abonnement Azure ? Vous pouvez essayer Azure Cosmos DB gratuitement sans carte de crédit.
- Un espace de travail Azure Databricks existant.
- Application Microsoft Entra et principal de service enregistrés.
- Si vous n’avez pas de principal de service et d’application, enregistrez une application à l’aide du Portail Azure.
Créer une clé secrète et enregistrer des informations d’identification
Dans cette section, vous pouvez créer une clé secrète client et enregistrer la valeur à utiliser ultérieurement.
Ouvrez le portail Azure.
Rendez-vous sur votre application Microsoft Entra existante.
Rendez-vous sur la page Certificats et clés secrètes. Ensuite, créez un secret. Enregistrez la valeur de clé secrète client à utiliser plus loin dans cet article.
Allez à la page Vue d’ensemble. Recherchez et enregistrez les valeurs de l’ID d’application (client), de l’ID d’objet et de l’ID de répertoire (locataire). Vous utilisez également ces valeurs plus loin dans cet article.
Rendez-vous sur votre compte Azure Cosmos DB for NoSQL existant.
Enregistrez la valeur d’URI sur la page Vue d’ensemble. Enregistrez également les valeurs d’ID d’abonnement et de Groupe de ressources. Vous utilisez ces valeurs plus tard dans cet article.
Créer une définition et une affectation
Dans cette section, vous créerez une définition de rôle Microsoft Entra ID. Ensuite, vous attribuerez ce rôle avec des autorisations pour lire et écrire des éléments dans les conteneurs.
Créez un rôle en utilisant la commande
az role definition create
. Transmettez le nom et le groupe de ressources du compte Azure Cosmos DB for NoSQL, suivis d’un corps de JSON qui définit le rôle personnalisé. Le rôle est également étendu au niveau du compte en utilisant/
. Vérifiez que vous fournissez un nom unique pour votre rôle en utilisant laRoleName
propriété du corps de la demande.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/*" ] }] }'
Répertoriez la définition de rôle que vous avez créée pour récupérer son identificateur unique dans la sortie JSON. Enregistrez la valeur
id
de la sortie 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": [] } ], ... } ]
Utilisez
az cosmosdb sql role assignment create
pour créer une attribution de rôle. Remplacez<aad-principal-id>
par l’ID d’objet que vous avez enregistré précédemment dans cet article. Remplacez également<role-definition-id>
par la valeurid
extraite de l’exécution de la commandeaz cosmosdb sql role definition list
à l’étape précédente.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>"
Utiliser un principal de service
Maintenant que vous avez créé une application et un principal de service Microsoft Entra, généré un rôle personnalisé et attribué ces autorisations de rôle à votre compte Azure Cosmos DB for NoSQL, vous devriez être en mesure d’exécuter un notebook.
Ouvrez votre espace de travail Azure Databricks.
Dans l’interface de l’espace de travail, créez un cluster. Configurez le cluster avec ces paramètres, au minimum :
Version Valeur Version du runtime 13.3 LTS (Scala 2.12, Spark 3.4.1)
Utilisez l’interface de l’espace de travail pour rechercher les packages Maven à partir de Maven Central avec l’ID de groupe
com.azure.cosmos.spark
. Installez sur le cluster le package prévu spécifiquement pour Spark 3.4 dont l’ID d’artefact est précédé du préfixeazure-cosmos-spark_3-4
.Pour finir, créez un notebook.
Conseil
Par défaut, le notebook est attaché au cluster récemment créé.
Dans le notebook, définissez les paramètres de configuration du connecteur Spark Azure Cosmos DB pour le point de terminaison de compte NoSQL, le nom de la base de données et le nom du conteneur. Utilisez l’ID d’abonnement, le Groupe de ressources, l’ID d’application (client), l’ID de répertoire (locataire) et les valeurs de clé secrète client enregistrées précédemment dans cet article.
# 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>" )
Configurez l’API Catalogue afin de gérer les ressources d’API pour NoSQL en utilisant 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>")
Créez une base de données à l’aide de
CREATE DATABASE IF NOT EXISTS
. Vérifiez que vous fournissez le nom de votre base de données.# 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>;")
Créez un conteneur à l’aide du nom de la base de données, du nom du conteneur, du chemin d’accès à la clé de partition et des valeurs de débit que vous spécifiez.
# 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>')")
Créer un exemple de jeu de données.
# 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) )
Utilisez
spark.createDataFrame
et la configuration de traitements transactionnels en ligne (OLTP) précédemment enregistrée pour ajouter des exemples de données au conteneur cible.# 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()
Conseil
Dans cet exemple de démarrage rapide, les informations d’identification sont affectées à des variables en texte clair. Pour des raisons de sécurité, nous vous recommandons d’utiliser des clés secrètes. Pour plus d’informations sur la manière de configurer des clés secrètes, consultez Ajouter des secrets à votre configuration Spark.