使用Bicep模板部署带托管标识的Logic Apps发Service Bus主题报401错误
问题概述
使用Bicep部署带系统托管标识的Logic Apps,用于向Service Bus主题发送消息。部署流程按顺序执行四个模块,门户显示部署成功,但发送消息时返回401未授权错误。手动通过Logic Apps设计器创建API连接则可正常发送,说明Bicep配置存在问题。
部署流程
- 配置带系统分配标识的Service Bus并创建目标主题
- 创建到Service Bus命名空间端点的API连接
- 创建带系统分配标识的Logic Apps,引用上述API连接并指定托管标识认证
- 为Service Bus主题分配
Service Bus Data SenderRBAC角色给Logic Apps的标识
错误信息
"status": 401,
"message": "40100: Unauthorized : Unauthorized access for 'Send' operation on endpoint 'sb://[sb-name-redacted].servicebus.windows.net/[topic-name-redacted]'"
各模块Bicep代码
Service Bus模块
//service bus resource resource_servicebus 'Microsoft.ServiceBus/namespaces@2022-01-01-preview' = { name: servicebus location: location sku: { [removed for brevity] } identity: { type: 'SystemAssigned' } properties: { [removed for brevity] } } //topics resource resource_topic_recurlywebhook 'Microsoft.ServiceBus/namespaces/topics@2022-01-01-preview' = { parent: resource_servicebus name: topic_[redacted] location: location properties: { [removed for brevity] } }
API连接模块
resource resource_connections_servicebus 'Microsoft.Web/connections@2018-07-01-preview' = { name: connections_servicebus location: location kind: 'V1' properties: { api: { id: connections_id_servicebus } displayName: connections_servicebus parameterValueSet: { name: 'managedIdentityAuth' values: { namespaceEndpoint:{ value: 'sb://${servicebus}.servicebus.windows.net' } } } } }
Logic Apps模块
//api connections resource resource_connections_servicebus 'Microsoft.Web/connections@2018-07-01-preview' existing = { name: connections_servicebus } //logic apps resource resource_lapp_ae_[redacted] 'Microsoft.Logic/workflows@2019-05-01' = { name: lapp_ae_[redacted] location: location identity: { type: 'SystemAssigned' } properties: { state: 'Enabled' definition: { '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#' contentVersion: '1.0.0.0' parameters: { '$connections': { defaultValue: { } type: 'Object' } } triggers: [removed for brevity] actions: { Response_200: [removed for brevity] Response_500: [removed for brevity] Send_message_to_[redacted]_topic: { runAfter: { } type: 'ApiConnection' inputs: { body: { ContentData: '@{base64(triggerBody())}' CorrelationId: '@{guid()}' Properties: '@triggerBody()' } host: { connection: { name: '@parameters(\'$connections\')[\'servicebus\'][\'connectionId\']' } } method: 'post' path: '/@{encodeURIComponent(encodeURIComponent(\'[redacted]\'))}/messages' } } } outputs: { } } parameters: { '$connections': { value: { servicebus: { connectionId: resource_connections_servicebus.id connectionName: resource_connections_servicebus.name connectionProperties: { authentication: { type: 'ManagedServiceIdentity' } } id: connections_id_servicebus } } } } } } ///////////////////////////////// outputs /////////////////////////////////////////////// output principalid_lapp_ae_rc_to_sb_connector string = resource_lapp_ae_rc_to_sb_connector.identity.principalId
Service Bus角色分配模块
//define roles to assign var rbac_service_bus_data_sender = '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' //define apps to send to topics param topic_[redacted]_access_list array = [ principalid_lapp_ae_[redacted] ] //////////////////////////// call resources to grant access to //////////////////////////////// resource resource_servicebus 'Microsoft.ServiceBus/namespaces@2022-01-01-preview' existing = { name: servicebus } resource resource_topic_[redacted] 'Microsoft.ServiceBus/namespaces/topics@2022-01-01-preview' existing = { parent: resource_servicebus name: topic_[redacted] } //////////////////////////// make role assignments //////////////////////////////// resource resource_topic_[redacted]_access_list 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalID in topic_[redacted]_access_list: { scope: resource_topic_[redacted] name: guid(resource_topic_[redacted].id, principalID, rbac_service_bus_data_sender) properties: { roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', rbac_service_bus_data_sender) principalId: principalID principalType: 'ServicePrincipal' } }]
问题排查与修复方案
1. API连接未配置使用调用者(Logic Apps)的托管标识
手动创建API连接时,默认会选择使用Logic Apps的系统标识作为认证主体,但Bicep中创建的API连接未指定这一配置,导致API连接尝试使用自身未启用的标识进行认证,最终触发401错误。
修复:修改API连接模块,添加useCallerIdentity参数
在parameterValueSet.values中添加以下配置,指定API连接使用调用它的Logic Apps标识:
parameterValueSet: { name: 'managedIdentityAuth' values: { namespaceEndpoint:{ value: 'sb://${servicebus}.servicebus.windows.net' } // 添加以下配置 useCallerIdentity: { value: true } } }
2. 缺少Logic Apps对API连接的访问权限
即使配置了使用调用者标识,Logic Apps的系统标识仍需要被授予使用该API连接的权限。
修复:在API连接模块中添加角色分配
为Logic Apps的系统标识授予Microsoft.Web/connections/use/action权限,允许其使用API连接:
// 假设Logic Apps的principalId通过参数传入API连接模块 param logicAppPrincipalId string resource apiConnRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: resource_connections_servicebus name: guid(resource_connections_servicebus.id, logicAppPrincipalId, '7f951dda-4ed3-4680-a7ca-43fe172d538d') properties: { roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') principalId: logicAppPrincipalId principalType: 'ServicePrincipal' } }
注意:需要在main.bicep中先部署Logic Apps模块,获取其principalId后,再传递给API连接模块进行角色分配,确保依赖顺序正确。
3. 验证角色分配的生效时机
RBAC角色分配可能存在延迟,确保在Logic Apps启动前角色分配已完成。可以在main.bicep中明确设置依赖关系,让角色分配模块依赖于Logic Apps模块,确保principalId已生成且角色分配完成后再启用Logic Apps。
验证修复
部署修改后的Bicep模板,等待所有资源部署完成后,触发Logic Apps的消息发送动作,确认401错误消失,消息成功发送到Service Bus主题。
内容的提问来源于stack exchange,提问作者dootdoot

