Udostępnij za pośrednictwem


Uwierzytelnianie i autoryzacja usługi App Service do wektorowej bazy danych

W tym artykule pokazano, jak zarządzać połączeniem między aplikacją .NET usługi App Service i rozwiązaniem wektorowej bazy danych. Obejmuje ona korzystanie z tożsamości zarządzanych firmy Microsoft w celu obsługi obsługiwanych usług i bezpiecznego przechowywania parametry połączenia dla innych osób.

Dodając bazę danych wektorów do aplikacji, można włączyć semantyczne wspomnienia dla sztucznej inteligencji. Zestaw SDK jądra semantycznego dla platformy .NET umożliwia łatwe implementowanie magazynu pamięci i kompletność przy użyciu preferowanego rozwiązania bazy danych wektorów.

Wymagania wstępne

Używanie tożsamości zarządzanej firmy Microsoft Entra do uwierzytelniania

Jeśli usługa wektorowej bazy danych obsługuje uwierzytelnianie firmy Microsoft Entra, możesz użyć tożsamości zarządzanej z usługą App Service, aby bezpiecznie uzyskać dostęp do wektorowej bazy danych bez konieczności ręcznego aprowizowania ani rotacji wpisów tajnych. Aby uzyskać listę usług platformy Azure, które obsługują uwierzytelnianie firmy Microsoft Entra, zobacz Usługi platformy Azure, które obsługują uwierzytelnianie firmy Microsoft Entra.

Dodawanie tożsamości zarządzanej do usługi App Service

Aplikacja może mieć korzystać z dwóch typów tożsamości:

  • Tożsamość przypisana przez system jest powiązana z aplikacją i jest usuwana, gdy aplikacja zostanie usunięta. Aplikacja może mieć tylko jedną tożsamość przypisaną przez system.
  • Tożsamość przypisana przez użytkownika to autonomiczny zasób platformy Azure, który można przypisać do aplikacji. Aplikacja może mieć wiele tożsamości przypisanych przez użytkownika.

Dodawanie tożsamości przypisanej przez system

  1. Przejdź do strony aplikacji w witrynie Azure Portal, a następnie przewiń w dół do grupy Ustawienia.
  2. Wybierz Tożsamość.
  3. Na karcie Przypisane przez system przełącz pozycję Stan na ., a następnie wybierz pozycję Zapisz.

Uruchom polecenie , az webapp identity assign aby utworzyć tożsamość przypisaną przez system:

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

Dodawanie tożsamości przypisanej przez użytkownika

Aby dodać tożsamość przypisaną przez użytkownika do aplikacji, utwórz tożsamość, a następnie dodaj jej identyfikator zasobu do konfiguracji aplikacji.

  1. Utwórz zasób tożsamości zarządzanej przypisanej przez użytkownika, postępując zgodnie z tymi instrukcjami.

  2. W okienku nawigacji po lewej stronie aplikacji przewiń w dół do grupy Ustawienia.

  3. Wybierz Tożsamość.

  4. Wybierz pozycję Dodaj przypisane przez> użytkownika.

  5. Znajdź utworzoną wcześniej tożsamość, wybierz ją, a następnie wybierz pozycję Dodaj.

    Ważne

    Po wybraniu pozycji Dodaj aplikacja zostanie ponownie uruchomiona.

  1. Utwórz tożsamość przypisaną przez użytkownika:

    az identity create --resource-group <groupName> --name <identityName>
    
  2. Przypisz tożsamość do aplikacji:

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

Dodawanie roli platformy Azure do tożsamości zarządzanej

  1. W witrynie Azure Portal przejdź do zakresu, do którego chcesz udzielić wektorowej bazy danych dostępu. Zakres może być grupą zarządzania, subskrypcją, grupą zasobów lub określonym zasobem platformy Azure.
  2. W okienku nawigacji po lewej stronie wybierz pozycję Kontrola dostępu (Zarządzanie dostępem i tożsamościami).
  3. Wybierz pozycję Dodaj, a następnie wybierz pozycję Dodaj przypisanie roli.
  4. Na karcie Rola wybierz odpowiednią rolę, która udziela dostępu do odczytu do bazy danych wektorów.
  5. Na karcie Członkowie wybierz tożsamość zarządzaną.
  6. Na karcie Przeglądanie i przypisywanie wybierz pozycję Przejrzyj i przypisz, aby przypisać rolę.

Zakres zasobów

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

Zakres grupy zasobów

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

Zakres subskrypcji

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

Zakres grupy zarządzania

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

Implementowanie uwierzytelniania opartego na tokenach przy użyciu wektorowej bazy danych

Następujące przykłady kodu wymagają następujących dodatkowych bibliotek:

  1. Zainicjuj DefaultAzureCredential obiekt w celu pobrania tożsamości zarządzanej aplikacji:

    // 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. Zainicjuj IMemoryStore obiekt dla bazy danych wektorów, a następnie użyj go do skompilowania obiektu 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()
        .WithAzureOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint, credentials)
        .WithMemoryStore(memoryStore)
        .Build();
    
  3. Skompiluj Kernel obiekt, a następnie zaimportuj ISemanticTextMemory obiekt przy użyciu polecenia 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. Użyj obiektu , Kernel aby wywołać monit zawierający przypomnienie pamięci:

    // 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://learn.microsoft.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}");
    

Przechowywanie wpisów tajnych połączenia przy użyciu usługi Key Vault

Jeśli wektorowa baza danych nie obsługuje uwierzytelniania firmy Microsoft Entra, możesz użyć usługi Key Vault do przechowywania wpisów tajnych połączenia i pobierania ich z aplikacją usługi App Service. Za pomocą usługi Key Vault do przechowywania wpisów tajnych połączenia można udostępniać je wielu aplikacjom i kontrolować dostęp do poszczególnych wpisów tajnych dla aplikacji.

Przed wykonaniem tych kroków pobierz parametry połączenia dla bazy danych wektorów. Na przykład zobacz Używanie usługi Azure Cache for Redis z aplikacją internetową platformy ASP.NET Core.

Dodawanie parametry połączenia do usługi Key Vault

Ważne

Przed wykonaniem tych kroków upewnij się, że utworzono usługę Key Vault przy użyciu witryny Azure Portal.

  1. Przejdź do magazynu kluczy w witrynie Azure Portal.
  2. W obszarze nawigacji po lewej stronie usługi Key Vault wybierz pozycję Obiekty , a następnie wybierz pozycję Wpisy tajne.
  3. Wybierz pozycję + Generuj/Importuj.
  4. Na ekranie Tworzenie wpisu tajnego wybierz następujące wartości:
    • Opcje przekazywania: Manual.
    • Nazwa: wpisz nazwę wpisu tajnego. Nazwa wpisu tajnego musi być unikatowa w usłudze Key Vault.
    • Wartość: parametry połączenia dla bazy danych wektorów.
    • Dla pozostałych opcji zostaw wartości domyślne. Wybierz pozycję Utwórz.
  5. Po wyświetleniu komunikatu o pomyślnym utworzeniu wpisu tajnego można go użyć w aplikacji.

Ważne

Przed wykonaniem tych kroków upewnij się, że utworzono usługę Key Vault przy użyciu interfejsu wiersza polecenia platformy Azure.

  1. Przyznaj swojemu kontu użytkownika uprawnienia do magazynu kluczy za pomocą kontroli dostępu opartej na rolach (RBAC), przypisz rolę przy użyciu polecenia interfejsu wiersza polecenia az role assignment createplatformy Azure:

    az role assignment create \
    --role "Key Vault Secrets User" \
    --assignee "<yourEmailAddress>" \
    --scope "/subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName>/providers/Microsoft.KeyVault/vaults/<keyVaultName>"
    
  2. Dodaj parametry połączenia do usługi Key Vault przy użyciu polecenia interfejsu wiersza polecenia az keyvault secret setplatformy Azure :

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

Udzielanie usłudze App Service dostępu do usługi Key Vault

  1. Przypisz tożsamość zarządzaną do usługi App Service.
  2. Key Vault Secrets User Dodaj role i Key Vault Reader do tożsamości zarządzanej.

Implementowanie pobierania parametry połączenia z usługi Key Vault

Aby użyć następujących przykładów kodu, potrzebne są następujące dodatkowe biblioteki:

Te przykłady kodu używają bazy danych Redis, ale można je zastosować do dowolnej wektorowej bazy danych obsługującej parametry połączenia.

  1. Zainicjuj DefaultAzureCredential obiekt w celu pobrania tożsamości zarządzanej aplikacji:

    // 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. Dodaj usługę Key Vault podczas kompilowania konfiguracji. Spowoduje to mapowanie wpisów tajnych usługi Key Vault na IConfigurationRoot obiekt:

    // User secrets let you provide connection strings when testing locally
    // For more info see: https://learn.microsoft.com/en-us/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. Użyj wektorowej bazy danych parametry połączenia z usługi Key Vault, aby zainicjować IMemoryStore obiekt, a następnie użyj jej do utworzenia ISemanticTextMemoryobiektu :

    // 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()
        .WithAzureOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint, credentials)
        .WithMemoryStore(memoryStore)
        .Build();
    
  4. Skompiluj Kernel obiekt, a następnie zaimportuj ISemanticTextMemory obiekt przy użyciu polecenia 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. Użyj obiektu , Kernel aby wywołać monit zawierający przypomnienie pamięci:

    // 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://learn.microsoft.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}");
    

Używanie ustawień aplikacji do przechowywania wpisów tajnych połączeń

Jeśli wektorowa baza danych nie obsługuje uwierzytelniania firmy Microsoft Entra, możesz użyć ustawień aplikacji usługi App Service do przechowywania wpisów tajnych połączenia. Za pomocą ustawień aplikacji można przechowywać wpisy tajne połączenia bez aprowizacji dodatkowych zasobów platformy Azure.

Przed wykonaniem tych kroków pobierz parametry połączenia dla bazy danych wektorów. Zobacz na przykład Use Azure Cache for Redis in .NET Framework (Używanie usługi Azure Cache for Redis na platformie .NET Framework).

Dodawanie parametry połączenia do ustawień aplikacji

  1. Przejdź do strony aplikacji w witrynie Azure Portal.
  2. W menu po lewej stronie aplikacji wybierz pozycję Ustawienia aplikacji konfiguracji>.
    • Domyślnie wartości ustawień aplikacji są ukryte w portalu pod kątem zabezpieczeń.
    • Aby wyświetlić ukrytą wartość ustawienia aplikacji, wybierz jego pole Wartość.
  3. Wybierz pozycję Nowe ustawienie połączenia.
  4. Na ekranie Dodawanie/edytowanie parametry połączenia wybierz następujące wartości:
    • Nazwa: wpisz nazwę ustawienia. Nazwa ustawienia musi być unikatowa.
    • Wartość: parametry połączenia dla bazy danych wektorów.
    • Typ: typ połączenia, Custom jeśli nie mają zastosowania żadne inne.
    • Dla pozostałych opcji zostaw wartości domyślne. Wybierz przycisk OK.
  5. Wybierz pozycję Zapisz z powrotem na stronie Konfiguracja.

Dodaj lub edytuj ustawienie aplikacji za pomocą polecenia interfejsu wiersza polecenia az webapp config connection-string setplatformy Azure:

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

Implementowanie pobierania parametry połączenia z ustawień aplikacji

Aby użyć następujących przykładów kodu, potrzebne są następujące dodatkowe biblioteki:

Te przykłady kodu używają bazy danych Redis, ale można je zastosować do dowolnej wektorowej bazy danych obsługującej parametry połączenia.

  1. Dodaj zmienne środowiskowe podczas kompilowania konfiguracji, spowoduje to mapowanie parametry połączenia na IConfigurationRoot obiekt :

    // User secrets let you provide connection strings when testing locally
    // For more info see: https://learn.microsoft.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. Użyj wektorowej bazy danych parametry połączenia z ustawień aplikacji, aby zainicjować IMemoryStore obiekt, a następnie użyj jej do utworzenia ISemanticTextMemoryelementu :

    // 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()
        .WithAzureOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint, credentials)
        .WithMemoryStore(memoryStore)
        .Build();
    
  3. Skompiluj Kernel obiekt, a następnie zaimportuj ISemanticTextMemory obiekt przy użyciu polecenia 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. Użyj obiektu , Kernel aby wywołać monit zawierający przypomnienie pamięci:

    // 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://learn.microsoft.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}");