Authentifier et autoriser App Service à une base de données vectorielle

Cet article explique comment gérer la connexion entre votre application .NET App Service et une solution de base de données vectorielle. Il couvre l’utilisation des identités managées Microsoft Entra pour les services pris en charge et le stockage sécurisé de chaînes de connexion pour d’autres utilisateurs.

En ajoutant une base de données vectorielle à votre application, vous pouvez activer des [mémoires sémantiques ou magasins de vecteurs] (magasins de vecteurs) pour votre IA. Le kit de développement logiciel (SDK) de noyau sémantique pour .NET vous permet d’implémenter facilement le stockage de mémoire et le rappel à l’aide de votre solution de base de données vectorielle préférée.

Prérequis

Utiliser l’identité managée Microsoft Entra pour l’authentification

Si un service de base de données vectorielle prend en charge l’authentification Microsoft Entra, vous pouvez utiliser une identité managée avec votre App Service pour accéder en toute sécurité à votre base de données vectorielle sans avoir à provisionner ou à faire pivoter manuellement les secrets. Pour obtenir la liste des services Azure qui prennent en charge l’authentification Microsoft Entra, consultez services Azure qui prennent en charge l’authentification Microsoft Entra.

Ajouter une identité managée à App Service

Deux types d’identité peuvent être accordés à votre application :

  • Une identité attribuée par le système est liée à votre application et est supprimée si votre application est supprimée. Une application ne peut avoir qu’une seule identité affectée par le système.
  • Une identité attribuée par l’utilisateur est une ressource Azure autonome qui peut être assignée à votre application. Une application peut avoir plusieurs identités attribuées par l’utilisateur.

Ajouter une identité affectée par le système

  1. Accédez à la page de votre application dans le portail Azure, puis faites défiler jusqu’au groupe Paramètres.
  2. Sélectionnez Identité.
  3. Sous l’onglet Système affecté, basculez État sur Activé, puis sélectionnez Enregistrer.

Exécutez la commande az webapp identity assign pour créer une identité affectée par le système :

az webapp identity assign --name <appName> --resource-group <groupName>

Ajouter une identité attribuée par l’utilisateur

Pour ajouter une identité affectée par l’utilisateur à votre application, créez l’identité, puis ajoutez son identificateur de ressource à la configuration de votre application.

  1. Créez une ressource d’identité managée affectée par l’utilisateur en suivant ces instructions.

  2. Dans le volet de navigation gauche de la page de votre application, faites défiler vers le bas jusqu’au groupe Paramètres.

  3. Sélectionnez Identité.

  4. Sélectionnez Attribuée par l’utilisateur>Ajouter.

  5. Recherchez l’identité que vous avez créée précédemment, sélectionnez-la, puis sélectionnez Ajouter.

    Important

    Après avoir sélectionné Ajouter, l’application redémarre.

  1. Créez une identité affectée par l’utilisateur :

    az identity create --resource-group <groupName> --name <identityName>
    
  2. Affectez l’identité à votre application :

    az webapp identity assign --resource-group <groupName> --name <appName> --identities <identityId>
    

Ajouter un rôle Azure à votre identité managée

  1. Dans le Portail Azure, accédez à l’étendue à laquelle vous souhaitez accorder l’accès à la base de données vectorielle. L’étendue peut être un Groupe d’administration, Abonnement, Groupe de ressourcesou une ressource Azure spécifique.
  2. Dans le volet de navigation gauche, sélectionnez Contrôle d’accès (IAM).
  3. Sélectionnez Ajouter, puis Ajouter une attribution de rôle.
  4. Sous l’onglet Rôle, sélectionnez le rôle approprié qui accorde l’accès en lecture à votre base de données vectorielle.
  5. Sous l’onglet Membres, sélectionnez l’identité managée.
  6. Dans l’onglet Passer en revue + affecter, sélectionnez Passer en revue + affecter pour affecter le rôle.

Étendue des ressources

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/subscriptions/<subscriptionId>/resourcegroups/<resourceGroupName>/providers/<providerName>/<resourceType>/<resourceSubType>/<resourceName>"

Étendue du groupe de ressources

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/subscriptions/<subscriptionId>/resourcegroups/<resourceGroupName>"

Étendue de l’abonnement

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/subscriptions/<subscriptionId>"

Étendue d’un groupe d’administration

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/providers/Microsoft.Management/managementGroups/<managementGroupName>"

Implémenter l’authentification basée sur des jetons avec la base de données vectorielle

Les exemples de code suivants nécessitent ces bibliothèques supplémentaires :

  1. Initialisez un objet DefaultAzureCredential pour récupérer l’identité managée de votre application :

    // Initialize a DefaultAzureCredential.
    // This credential type will try several authentication flows in order until one is available.
    // Will pickup Visual Studio or Azure CLI credentials in local environments.
    // Will pickup managed identity credentials in production deployments.
    TokenCredential credentials = new DefaultAzureCredential(
        new DefaultAzureCredentialOptions
        {
            // If using a user-assigned identity specify either:
            // ManagedIdentityClientId or ManagedIdentityResourceId.
            // e.g.: ManagedIdentityClientId = "myIdentityClientId".
        }
    );
    
  2. Initialisez un objet IMemoryStore pour votre base de données vectorielle, puis utilisez-le pour générer un ISemanticTextMemory:

    // Retrieve the endpoint obtained from the Azure AI Search deployment.
    // Retrieve the endpoint and deployments obtained from the Azure OpenAI deployment.
    // Must use the deployment name not the underlying model name.
    IConfigurationRoot config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
    string searchEndpoint = config["AZURE_AISEARCH_ENDPOINT"]!;
    string openAiEndpoint = config["AZURE_OPENAI_ENDPOINT"]!;
    string embeddingModel = config["AZURE_OPENAI_EMBEDDING_NAME"]!;
    
    // The Semantic Kernel SDK provides a connector extension for Azure AI Search.
    // Initialize an AzureAISearchMemoryStore using your managed identity credentials.
    IMemoryStore memoryStore = new AzureAISearchMemoryStore(searchEndpoint, credentials);
    
    // Build a SemanticMemoryStore with Azure AI Search as the store.
    // Must also include a text embedding generation service.
    ISemanticTextMemory memory = new MemoryBuilder()
        .WithOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint)
        .WithMemoryStore(memoryStore)
        .Build();
    
  3. Générez un objet Kernel, puis importez l’objet ISemanticTextMemory à l’aide de TextMemoryPlugin:

    // Build a Kernel, include a chat completion service.
    string chatModel = config["AZURE_OPENAI_GPT_NAME"]!;
    Kernel kernel = Kernel
        .CreateBuilder()
        .AddAzureOpenAIChatCompletion(chatModel, openAiEndpoint, credentials)
        .Build();
    
    // Import the semantic memory store as a TextMemoryPlugin.
    // The TextMemoryPlugin enable recall via prompt expressions.
    kernel.ImportPluginFromObject(new TextMemoryPlugin(memory));
    
  4. Utilisez l’objet Kernel pour appeler une invite qui inclut le rappel de mémoire :

    // Must configure the memory collection, number of memories to recall, and relevance score.
    // The {{...}} syntax represents an expression to Semantic Kernel.
    // For more information on this syntax see:
    // https://video2.skills-academy.com/semantic-kernel/prompts/prompt-template-syntax
    string memoryCollection = config["AZURE_OPENAI_MEMORY_NAME"]!;
    string? result = await kernel.InvokePromptAsync<string>(
        "{{recall 'where did I grow up?'}}",
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollection,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    Console.WriteLine($"Output: {result}");
    

Utiliser Key Vault pour stocker les secrets de connexion

Si une base de données vectorielle ne prend pas en charge l’authentification Microsoft Entra, vous pouvez utiliser un coffre de clés pour stocker vos secrets de connexion et les récupérer avec votre application App Service. En utilisant Key Vault pour stocker vos secrets de connexion, vous pouvez les partager avec plusieurs applications et contrôler l’accès à des secrets individuels par application.

Avant de suivre ces étapes, récupérez une chaîne de connexion pour votre base de données vectorielle. Par exemple, consultez Utiliser Azure Cache pour Redis avec une application web ASP.NET Core.

Ajouter une chaîne de connexion à Key Vault

Important

Avant de suivre ces étapes, vérifiez que vous avez créé un Key Vault à l’aide du portail Azure.

  1. Accédez à votre coffre de clés dans le portail Azure.
  2. Dans le volet de navigation gauche de Key Vault, sélectionnez Objets, puis Secrets.
  3. Sélectionnez + Générer/importer.
  4. Dans l’écran Create a secret (Créer un secret), choisissez les valeurs suivantes :
    • Options de chargement: Manual.
    • Nom : Entrez un nom pour le secret. Le nom du secret doit être unique dans le coffre de clés.
    • Valeur: chaîne de connexion pour votre base de données vectorielle.
    • Conservez les valeurs par défaut des autres options. Sélectionnez Créer.
  5. Lorsque vous recevez le message indiquant que le secret a été créé avec succès, il est prêt à être utilisé dans votre application.

Important

Avant de suivre ces étapes, vérifiez que vous avez créé un Key Vault à l’aide de l’interface de ligne de commande Azure.

  1. Accordez à votre compte d’utilisateur des autorisations pour votre coffre de clés via le contrôle d’accès en fonction du rôle (RBAC), attribuez un rôle à l’aide de la commande Azure CLI az role assignment create:

    az role assignment create \
    --role "Key Vault Secrets User" \
    --assignee "<yourEmailAddress>" \
    --scope "/subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName>/providers/Microsoft.KeyVault/vaults/<keyVaultName>"
    
  2. Ajoutez la chaîne de connexion à Key Vault à l’aide de la commande Azure CLI az keyvault secret set:

    az keyvault secret set \
    --vault-name "<keyVaultName>" \
    --name "<secretName>" \
    --value "<connectionString>"
    

Accorder à votre App Service l’accès à Key Vault

  1. Attribuer une identité managée à votre App Service.
  2. Ajouter les rôles Key Vault Secrets User et Key Vault Reader à votre identité managée.

Implémenter la récupération de chaîne de connexion à partir de Key Vault

Pour utiliser les exemples de code suivants, vous avez besoin de ces bibliothèques supplémentaires :

Ces exemples de code utilisent une base de données Redis, mais vous pouvez les appliquer à n’importe quelle base de données vectorielle qui prend en charge les chaînes de connexion.

  1. Initialisez un objet DefaultAzureCredential pour récupérer l’identité managée de votre application :

    // Initialize a DefaultAzureCredential.
    // This credential type will try several authentication flows in order until one is available.
    // Will pickup Visual Studio or Azure CLI credentials in local environments.
    // Will pickup managed identity credentials in production deployments.
    TokenCredential credentials = new DefaultAzureCredential(
        new DefaultAzureCredentialOptions
        {
            // If using a user-assigned identity specify either:
            // ManagedIdentityClientId or ManagedIdentityResourceId.
            // e.g.: ManagedIdentityClientId = "myIdentityClientId".
        }
    );
    
  2. Ajoutez Key Vault lors de la création de votre configuration, cela mappe vos secrets Key Vault à l’objet IConfigurationRoot :

    // User secrets let you provide connection strings when testing locally
    // For more info see: https://video2.skills-academy.com/aspnet/core/security/app-secrets
    IConfigurationRoot config = new ConfigurationBuilder()
        .AddUserSecrets<Program>()
        .AddAzureKeyVault(new Uri("{vaultURI}"), credentials)
        .Build();
    
    // Retrieve the Redis connection string obtained from the Key Vault.
    string redisConnectionString = config["AZURE_REDIS_CONNECT_STRING"]!;
    
  3. Utilisez votre chaîne de connexion de base de données vectorielle à partir de Key Vault pour initialiser un objet IMemoryStore, puis utilisez-la pour générer un ISemanticTextMemory:

    // Use the connection string to connect to the database
    IDatabase database = (
        await ConnectionMultiplexer.ConnectAsync(redisConnectionString)
    ).GetDatabase();
    
    // The Semantic Kernel SDK provides a connector extension for Redis.
    // Initialize an RedisMemoryStore using your managed identity credentials.
    IMemoryStore memoryStore = new RedisMemoryStore(database);
    
    // Retrieve the endpoint and deployments obtained from the Azure OpenAI deployment.
    // Must use the deployment name not the underlying model name.
    string openAiEndpoint = config["AZURE_OPENAI_ENDPOINT"]!;
    string embeddingModel = config["AZURE_OPENAI_EMBEDDING_NAME"]!;
    
    // Build a SemanticMemoryStore with Azure AI Search as the store.
    // Must also include a text embedding generation service.
    ISemanticTextMemory memory = new MemoryBuilder()
        .WithOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint)
        .WithMemoryStore(memoryStore)
        .Build();
    
  4. Générez un objet Kernel, puis importez l’objet ISemanticTextMemory à l’aide de TextMemoryPlugin:

    // Build a Kernel, include a chat completion service.
    string chatModel = config["AZURE_OPENAI_GPT_NAME"]!;
    Kernel kernel = Kernel
        .CreateBuilder()
        .AddAzureOpenAIChatCompletion(chatModel, openAiEndpoint, credentials)
        .Build();
    
    // Import the semantic memory store as a TextMemoryPlugin.
    // The TextMemoryPlugin enable recall via prompt expressions.
    kernel.ImportPluginFromObject(new TextMemoryPlugin(memory));
    
  5. Utilisez l’objet Kernel pour appeler une invite qui inclut le rappel de mémoire :

    // Must configure the memory collection, number of memories to recall, and relevance score.
    // The {{...}} syntax represents an expression to Semantic Kernel.
    // For more information on this syntax see:
    // https://video2.skills-academy.com/semantic-kernel/prompts/prompt-template-syntax
    string memoryCollection = config["AZURE_OPENAI_MEMORY_NAME"]!;
    string? result = await kernel.InvokePromptAsync<string>(
        "{{recall 'where did I grow up?'}}",
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollection,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    Console.WriteLine($"Output: {result}");
    

Utiliser les paramètres d’application pour stocker les secrets de connexion

Si une base de données vectorielle ne prend pas en charge l’authentification Microsoft Entra, vous pouvez utiliser les paramètres de l’application App Service pour stocker vos secrets de connexion. En utilisant les paramètres d’application, vous pouvez stocker vos secrets de connexion sans approvisionner d’autres ressources Azure.

Avant de suivre ces étapes, récupérez une chaîne de connexion pour votre base de données vectorielle. Par exemple, consultez Utiliser Azure Cache pour Redis dans .NET Framework.

Ajouter une chaîne de connexion aux paramètres d’application

  1. Accédez à la page de votre application sur le portail Azure.
  2. Dans le menu de gauche de l'application, sélectionnez Configuration>Paramètres de l'application.
    • Par défaut, les valeurs des paramètres d’application sont masquées dans le portail pour la sécurité.
    • Pour afficher une valeur masquée d’un paramètre d’application, sélectionnez son champ Valeur.
  3. Sélectionnez Nouveau paramètre de connexion.
  4. Dans l’écran Ajouter/modifier la chaîne de connexion, choisissez les valeurs suivantes :
    • Nom: tapez un nom pour le paramètre. Le nom du paramètre doit être unique.
    • Valeur: chaîne de connexion pour votre base de données vectorielle.
    • Type: type de connexion, Custom si aucun autre ne s’applique.
    • Conservez les valeurs par défaut des autres options. Cliquez sur OK.
  5. Sélectionnez Enregistrer dans la page Configuration.

Ajoutez ou modifiez un paramètre d’application avec la commande Azure CLI az webapp config connection-string set:

az webapp config connection-string set \
--name "<appName>" \
--resource-group "<groupName>" \
--connection-string-type "<connectionType>" \
--settings <connectionName>='<connectionString>'

Implémenter la récupération de chaîne de connexion à partir des paramètres de l’application

Pour utiliser les exemples de code suivants, vous avez besoin de ces bibliothèques supplémentaires :

Ces exemples de code utilisent une base de données Redis, mais vous pouvez les appliquer à n’importe quelle base de données vectorielle qui prend en charge les chaînes de connexion.

  1. Ajoutez des variables d’environnement lors de la création de votre configuration, cela mappe vos chaînes de connexion à l’objet IConfigurationRoot :

    // User secrets let you provide connection strings when testing locally
    // For more info see: https://video2.skills-academy.com/en-us/aspnet/core/security/app-secrets
    IConfigurationRoot config = new ConfigurationBuilder()
        .AddUserSecrets<Program>()
        .AddEnvironmentVariables()
        .Build();
    
    // Retrieve the Redis connection string obtained from the app settings.
    // The connection string name should match the entry in application settings
    string redisConnectionString = config.GetConnectionString("AZURE_REDIS")!;
    
  2. Utilisez votre chaîne de connexion de base de données vectorielle à partir des paramètres d’application pour initialiser un objet IMemoryStore, puis utilisez-la pour générer un ISemanticTextMemory:

    // Use the connection string to connect to the database
    IDatabase database = (
        await ConnectionMultiplexer.ConnectAsync(redisConnectionString)
    ).GetDatabase();
    
    // The Semantic Kernel SDK provides a connector extension for Redis.
    // Initialize an RedisMemoryStore using your managed identity credentials.
    IMemoryStore memoryStore = new RedisMemoryStore(database);
    
    // Retrieve the endpoint and deployments obtained from the Azure OpenAI deployment.
    // Must use the deployment name not the underlying model name.
    string openAiEndpoint = config["AZURE_OPENAI_ENDPOINT"]!;
    string embeddingModel = config["AZURE_OPENAI_EMBEDDING_NAME"]!;
    
    // Build a SemanticMemoryStore with Azure AI Search as the store.
    // Must also include a text embedding generation service.
    ISemanticTextMemory memory = new MemoryBuilder()
        .WithOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint)
        .WithMemoryStore(memoryStore)
        .Build();
    
  3. Générez un objet Kernel, puis importez l’objet ISemanticTextMemory à l’aide de TextMemoryPlugin:

    // Build a Kernel, include a chat completion service.
    string chatModel = config["AZURE_OPENAI_GPT_NAME"]!;
    Kernel kernel = Kernel
        .CreateBuilder()
        .AddAzureOpenAIChatCompletion(chatModel, openAiEndpoint, credentials)
        .Build();
    
    // Import the semantic memory store as a TextMemoryPlugin.
    // The TextMemoryPlugin enable recall via prompt expressions.
    kernel.ImportPluginFromObject(new TextMemoryPlugin(memory));
    
  4. Utilisez l’objet Kernel pour appeler une invite qui inclut le rappel de mémoire :

    // Must configure the memory collection, number of memories to recall, and relevance score.
    // The {{...}} syntax represents an expression to Semantic Kernel.
    // For more information on this syntax see:
    // https://video2.skills-academy.com/semantic-kernel/prompts/prompt-template-syntax
    string memoryCollection = config["AZURE_OPENAI_MEMORY_NAME"]!;
    string? result = await kernel.InvokePromptAsync<string>(
        "{{recall 'where did I grow up?'}}",
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollection,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    Console.WriteLine($"Output: {result}");