在部署期间读取 Azure ServiceBus 命名空间连接字符串

Read Azure ServiceBus Namespace connection string during deployment

我正在尝试从 Azure Function (C#) 向 Azure ServiceBus 队列发送消息。为此,我需要服务总线命名空间的 ConnectionString(或者可能传递 Azure.Core.TokenCredential)。

我在将 ConnectionString 传递给 ServiceBusClient 构造函数时确实起作用了。

string connectionString = "Endpoint=sb://<servicebus-name>.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=<access-key>";
var client = new ServiceBusClient(connectionString);
var sender = client.CreateSender(queueName);
...
sender.SendMessagesAsync()

问题是部署应该是自动化的,Function 和 ServiceBus 是使用资源模板部署的。因此,SharedAccessKey 是在部署时创建的。如果我可以读取资源模板中的 AccessKey,我可以设置一个应用程序设置,然后可以由函数读取。但是,我找不到在资源模板中获取 AccessKey 的方法。可能吗?

我尝试过的另一件事是使用这样的 TokenCredential 创建 ServiceBusClient

var credentials = new DefaultAzureCredential();
string[] ss = queueUrl.Split('/', StringSplitOptions.RemoveEmptyEntries);
var fullyQualifiedName = ss[^2];
var queueName = ss[^1];

var client = new ServiceBusClient(fullyQualifiedName, credentials);
var sender = client.CreateSender(queueName);
using ServiceBusMessageBatch messageBatch = sender.CreateMessageBatchAsync().Result; 

这样做时我得到:

Unauthorized access. 'Send' claim(s) are required to perform this operation. Resource: 'sb://<servicebus-name>.servicebus.windows.net/<queuename>'. 

我不完全理解 DefaultAzureCredential 应该如何工作。是否有可能以某种方式解决此权限问题(这是在 Azure 函数中)?

我的解决方法

我有一个解决方法,它需要在部署资源模板后执行额外的步骤。使用 Azure CLI 读取 ServiceBus 命名空间 ConnectionString,然后使用该值更新应用程序设置。该函数然后从应用程序设置中读取连接字符串。

$ cs=$(az servicebus namespace authorization-rule keys list --namespace-name <Namespace> -n RootManageSharedAccessKey -g <resource-group> -o json | jq -r '.primaryConnectionString')
$ az functionapp config appsettings set --settings ServiceBusNamespaceConnectionStringCLI=$cs -g <resource-group> -n <function-name>
...
- name: ServiceBusNamespaceConnectionStringCLI
  slotSetting: false
  value: Endpoint=sb://<servicebus-name>.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=<access-key>

我不想使用这个额外的步骤,而是尽可能在模板或代码中完成。有什么想法吗?

感谢这个答案 我找到了如何在资源模板中获取 connectionString。这就是我使用应用程序设置将连接字符串传递给函数的方式。

"appSettings": [
  {
    "name": "ServiceBusConnectionString",
    "value": "[listKeys(resourceId('Microsoft.ServiceBus/namespaces/AuthorizationRules', variables('serviceBusName'), '    RootManageSharedAccessKey'), '2021-06-01-preview').primaryConnectionString]"
  }