多容器 Azure 应用程序服务无法使用托管身份访问 Cosmos NoSql

问题描述 投票:0回答:1

我正在构建一个多容器应用程序,使用“docker compose”部署在 Azure 应用程序服务上,分配一个身份(用户分配的托管身份)并向主体 ID 提供 RBAC,以使用以下命令访问 cosmos 容器

az cosmosdb sql role assignment create -a cosmos-nosql-db -g rish90-rg-westus -s "/" -p actual_principal_id -d 00000000-0000-0000-0000-000000000002

多容器应用程序由三个容器 nginx 代理、nginx http web 服务器和基于 .NET 的后端服务器组成。它是使用 DefaultAzureCredential 与 CosmosDB 进行通信的后端服务器。

但是对于多容器应用程序,cosmos db 无法访问。我收到错误

Azure.Identity.CredentialUnavailableException: DefaultAzureCredential failed to retrieve a token from the included credentials.

但是如果我将后端部署为单个容器天蓝色应用程序服务;并启用托管身份和各自的RBAC,后端能够访问cosmos;

这里是相同的 Github 存储库的链接

我无法理解这里的问题是什么以及如何解决?

这是系统的设计

rough design of system

azure azure-web-app-service azure-managed-identity
1个回答
0
投票

我认为使用

docker compose
文件的多容器应用程序当前不支持托管身份连接,因为它当前处于预览状态。我建议使用
connection string
进行连接以解决问题。

使用连接字符串对我有用。

我为客户端使用了连接字符串。

docker-compose.yml
:

version: '3.3'

services:
  proxy:
    image: vivek.azurecr.io/proxy
    ports:
      - "80:80"
    container_name: proxy


  frontend:
    image: vivek.azurecr.io/frontend
    ports:
      - "80"
    depends_on:
      - backend
    container_name: frontend


  backend:
    image: vivek.azurecr.io/backend
    ports:
      - "3000"
    container_name: backend

TodoListDbClient.cs
:

using System.Net.Http.Headers;
using Azure.Identity;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Linq;
using TodoApi;

public class TodoListDbClient : IDbClient
{
    private readonly Container _todoListContainer;

    public TodoListDbClient()
    {   
        var cosmosClientOptions = new CosmosClientOptions {
            
        };
        var cosmosClient = new CosmosClient("AccountEndpoint=https://multicontainer-web-app-db.documents.azure.com:443/;AccountKey=xxxxxxxxxxxxxxxxxxxxx;");
        _todoListContainer = cosmosClient.GetDatabase("ToDoList").GetContainer("Items");
    }

    public async Task<ItemResponse<Todo>> AddAsync(Todo todoItem)
    {    
        return await _todoListContainer.CreateItemAsync<Todo>(todoItem);
    }

    public async Task<List<Todo>> GetAllAsync()
    {
        var queryable = _todoListContainer.GetItemLinqQueryable<Todo>();
        var feed = queryable.Where(p => p.id != null).ToFeedIterator();

        List<Todo> todos = [];

        while (feed.HasMoreResults)
        {   //pagination response
            var response = await feed.ReadNextAsync();
            foreach (var item in response)
            {
                todos.Add(item);
            }
        }

        return todos;
    }
}

OUTPUT

© www.soinside.com 2019 - 2024. All rights reserved.