fix(agents): restrict deploy RBAC pre-flight to roles with CogSvc data plane access#9205
Conversation
…role in deploy RBAC pre-flight
sufficientAIUserRoles previously included Owner, Contributor, and
Azure AI Developer, causing two classes of false positives:
- Owner/Contributor: management-plane-only roles with zero dataActions,
so a user with inherited Owner would satisfy the check but still lack
the Microsoft.CognitiveServices/* dataActions required for
POST /agents/{name}/versions, resulting in deploy 403.
- Azure AI Developer: dataActions cover only OpenAI/Speech/ContentSafety/MaaS,
NOT the AIServices.* namespace used by Foundry agents. Azure docs
explicitly state 'For Foundry project access, use the Foundry User
or Foundry Owner roles instead.'
Fix: restrict the list to roles that actually grant
Microsoft.CognitiveServices/* dataActions covering AIServices.*:
Foundry User (53ca6127-...): primary, CogSvc.* wildcard
Cognitive Services User (a97b65f3-...): backward-compat alias assigned
by older Bicep provisions
(AZURE_PRINCIPAL_ID flow)
Update TestSufficientRoleLists to assert the corrected membership and
add roleCognitiveServicesUser to TestDeveloperRBACRoleConstants.
|
Azure Pipelines: Successfully started running 1 pipeline(s). 6 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Narrows Foundry deploy RBAC checks to roles granting required Cognitive Services data-plane access.
Changes:
- Removes management-only and incompatible roles.
- Recognizes legacy Cognitive Services User assignments.
- Updates role-list tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
developer_rbac_check.go |
Revises sufficient AI role definitions. |
developer_rbac_check_test.go |
Validates updated role membership. |
…ane role list Addresses Copilot PR review comments on Azure#9205: 1. sufficientAIUserRoles was missing two built-in roles that carry Microsoft.CognitiveServices/* dataActions: - Foundry Project Manager (eadc314b-...) — constant already existed but was not included in the list. - Foundry Owner (c883944f-...) — new constant; the code comment already cited this role as recommended yet it was absent. Both omissions caused users with these roles to be falsely flagged, triggering a redundant Foundry User auto-assignment on every deploy. 2. DeveloperRBACResult.HasSufficientAIRole doc comment in developer_rbac_query.go named the old role set (Owner, Contributor, Foundry User, Azure AI Developer). Updated to reflect the actual accepted set.
Foundry Owner (c883944f-...) grants Microsoft.Authorization/roleAssignments/write, which the postdeploy hook needs to assign Foundry User to agent service principals. Without this, a user whose only role is Foundry Owner passes the AI-access check (sufficientAIUserRoles) but immediately receives the 'role assignment write not available' warning from check 2, creating a confusing and incorrect diagnostic.
|
nit (non-blocking): The |
VS Code are aligned in these two PRs: |
jongio
left a comment
There was a problem hiding this comment.
Verified the four role IDs and their data-plane coverage against the current built-in role definitions. Foundry User, Cognitive Services User, Foundry Project Manager, and Foundry Owner each carry Microsoft.CognitiveServices/* dataActions that cover AIServices/agents/write (Project Manager's NotDataActions exclude only impersonation and fine-tune deployment, not agents/write). Owner and Contributor are correctly dropped since they have zero dataActions. Foundry Owner's conditional roleAssignments/write allows assigning Foundry User (53ca6127), which is what the postdeploy path assigns, so adding it to sufficientRoleAssignWriteRoles is right. Role-list tests pass.
|
/check-enforcer override |
Fixes: #9169
Description
Problem
developer_rbac_check.go—sufficientAIUserRoles— contained three incorrect entries that caused a false-positive "sufficient" result, silently blocking the Foundry User auto-assignment and ultimately producing a deploy 403:actions: ["*"]). ZerodataActions. A user with inherited subscription-level Owner satisfies the check but still cannot callPOST /agents/{name}/versions(needsMicrosoft.CognitiveServices/accounts/AIServices/agents/writedataAction).dataActions. Additionally, itsnotActionsexplicitly blockMicrosoft.Authorization/*/Write, so it cannot even perform the Foundry User auto-assignment.dataActionscover onlyOpenAI/*,SpeechServices/*,ContentSafety/*,MaaS/*— not theAIServices.*namespace used by Foundry agents. Azure docs explicitly state: "For Foundry project access, use the Foundry User or Foundry Owner roles instead."When any of these roles was present (e.g. Owner inherited from the subscription), the check returned
hasAIAccess = true, skipping the Foundry User auto-assignment. The user ended up with no Cognitive Services dataActions on the project scope, causing deploy to fail with HTTP 403:Fix
Restrict
sufficientAIUserRolesto only roles that includeMicrosoft.CognitiveServices/*dataActions covering theAIServices.*namespace, and add the two previously missing roles:A new constant
roleCognitiveServicesUser(a97b65f3-...) is added for the Cognitive Services User role, which carries identicaldataActionsto Foundry User and is assigned by olderazd provisionBicep templates (theAZURE_PRINCIPAL_IDflow). Recognising it avoids a redundant auto-assignment on re-deploy.A new constant
roleFoundryOwner(c883944f-...) is added. The code comment already recommended Foundry Owner ("use the Foundry User or Foundry Owner roles instead"), but the role was missing from the list.roleAzureAIProjectManager(eadc314b-...) was already defined as a constant but was not included in the list.The stale doc comment on
DeveloperRBACResult.HasSufficientAIRoleindeveloper_rbac_query.gois updated to name the actual role set.Behavior after fix
hasAIAccess = true→ skip assignment → deploy 403hasAIAccess = false→ auto-assign Foundry User → deploy succeedshasAIAccess = false→ redundant re-assignment every deployhasAIAccess = true→ skip ✅hasAIAccess = true→ skip ✅hasAIAccess = true→ skip → deploy 403hasAIAccess = false→ auto-assign Foundry User → deploy succeedshasAIAccess = false→ redundant re-assignmenthasAIAccess = true→ skip ✅hasAIAccess = false→ redundant re-assignmenthasAIAccess = true→ skip ✅Files changed
internal/project/developer_rbac_check.goroleCognitiveServicesUserandroleFoundryOwnerconstants; rewritesufficientAIUserRolesto include all four valid rolesinternal/project/developer_rbac_check_test.goTestSufficientRoleLists(assert new members + NotContains for removed roles); addroleCognitiveServicesUserandroleFoundryOwnertoTestDeveloperRBACRoleConstantsinternal/project/developer_rbac_query.goHasSufficientAIRoleto reflect the actual role set