Skip to content

fix(agents): restrict deploy RBAC pre-flight to roles with CogSvc data plane access#9205

Merged
huimiu merged 3 commits into
Azure:mainfrom
jayzhang:huajie/agentdeploy_rbac
Jul 21, 2026
Merged

fix(agents): restrict deploy RBAC pre-flight to roles with CogSvc data plane access#9205
huimiu merged 3 commits into
Azure:mainfrom
jayzhang:huajie/agentdeploy_rbac

Conversation

@jayzhang

@jayzhang jayzhang commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Fixes: #9169

Description

Problem

developer_rbac_check.gosufficientAIUserRoles — contained three incorrect entries that caused a false-positive "sufficient" result, silently blocking the Foundry User auto-assignment and ultimately producing a deploy 403:

Role Why it was wrong
Owner Management-plane only (actions: ["*"]). Zero dataActions. A user with inherited subscription-level Owner satisfies the check but still cannot call POST /agents/{name}/versions (needs Microsoft.CognitiveServices/accounts/AIServices/agents/write dataAction).
Contributor Same — no dataActions. Additionally, its notActions explicitly block Microsoft.Authorization/*/Write, so it cannot even perform the Foundry User auto-assignment.
Azure AI Developer Its dataActions cover only OpenAI/*, SpeechServices/*, 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."

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:

Identity does not have permissions for
Microsoft.CognitiveServices/accounts/AIServices/agents/write actions

Fix

Restrict sufficientAIUserRoles to only roles that include Microsoft.CognitiveServices/* dataActions covering the AIServices.* namespace, and add the two previously missing roles:

// Before
var sufficientAIUserRoles = []string{
    roleOwner,            // ❌ no dataActions
    roleContributor,      // ❌ no dataActions
    roleAzureAIUser,      // ✅ Foundry User — CogSvc.*
    roleAzureAIDeveloper, // ❌ only OpenAI/Speech/ContentSafety/MaaS
}

// After
var sufficientAIUserRoles = []string{
    roleAzureAIUser,           // ✅ Foundry User: Microsoft.CognitiveServices/*
    roleCognitiveServicesUser, // ✅ backward compat: same dataActions, assigned by older Bicep
    roleAzureAIProjectManager, // ✅ Foundry Project Manager: Microsoft.CognitiveServices/*
    roleFoundryOwner,          // ✅ Foundry Owner: Microsoft.CognitiveServices/*
}

A new constant roleCognitiveServicesUser (a97b65f3-...) is added for the Cognitive Services User role, which carries identical dataActions to Foundry User and is assigned by older azd provision Bicep templates (the AZURE_PRINCIPAL_ID flow). 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.HasSufficientAIRole in developer_rbac_query.go is updated to name the actual role set.

Behavior after fix

Scenario Before After
User has Owner only (subscription-inherited) hasAIAccess = true → skip assignment → deploy 403 hasAIAccess = false → auto-assign Foundry User → deploy succeeds
User has Cognitive Services User (from Bicep provision) hasAIAccess = false → redundant re-assignment every deploy hasAIAccess = true → skip ✅
User has Foundry User hasAIAccess = true → skip ✅ unchanged ✅
User has Azure AI Developer only hasAIAccess = true → skip → deploy 403 hasAIAccess = false → auto-assign Foundry User → deploy succeeds
User has Foundry Project Manager hasAIAccess = false → redundant re-assignment hasAIAccess = true → skip ✅
User has Foundry Owner hasAIAccess = false → redundant re-assignment hasAIAccess = true → skip ✅

Files changed

File Change
internal/project/developer_rbac_check.go Add roleCognitiveServicesUser and roleFoundryOwner constants; rewrite sufficientAIUserRoles to include all four valid roles
internal/project/developer_rbac_check_test.go Update TestSufficientRoleLists (assert new members + NotContains for removed roles); add roleCognitiveServicesUser and roleFoundryOwner to TestDeveloperRBACRoleConstants
internal/project/developer_rbac_query.go Fix stale doc comment on HasSufficientAIRole to reflect the actual role set

…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.
Copilot AI review requested due to automatic review settings July 20, 2026 07:10
@azure-pipelines

Copy link
Copy Markdown
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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copilot AI review requested due to automatic review settings July 20, 2026 07:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

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.
Copilot AI review requested due to automatic review settings July 20, 2026 07:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@v1212

v1212 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

nit (non-blocking): The sufficientAIUserRoles set here diverges from the VS Code Foundry extension, which checks only Foundry User (53ca6127). This PR additionally accepts Cognitive Services User, Foundry Project Manager, and Foundry Owner — all valid (each carries Microsoft.CognitiveServices/* data-plane actions covering agents/write). Both are correct, just not aligned. Consider aligning the two implementations (or noting the intentional divergence) to keep them in sync.

@jayzhang

Copy link
Copy Markdown
Contributor Author

nit (non-blocking): The sufficientAIUserRoles set here diverges from the VS Code Foundry extension, which checks only Foundry User (53ca6127). This PR additionally accepts Cognitive Services User, Foundry Project Manager, and Foundry Owner — all valid (each carries Microsoft.CognitiveServices/* data-plane actions covering agents/write). Both are correct, just not aligned. Consider aligning the two implementations (or noting the intentional divergence) to keep them in sync.

VS Code are aligned in these two PRs:
https://github.com/microsoft/Skylight/pull/5413
https://github.com/microsoft/Skylight/pull/5422

@huimiu huimiu linked an issue Jul 20, 2026 that may be closed by this pull request
1 task
@huimiu huimiu added area/extensions Extensions (general) ext-agents azure.ai.agents extension labels Jul 20, 2026

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@huimiu

huimiu commented Jul 21, 2026

Copy link
Copy Markdown
Member

/check-enforcer override

@huimiu
huimiu enabled auto-merge (squash) July 21, 2026 01:59
@huimiu
huimiu merged commit 8826eed into Azure:main Jul 21, 2026
32 of 35 checks passed
@jayzhang
jayzhang deleted the huajie/agentdeploy_rbac branch July 21, 2026 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/extensions Extensions (general) customer-reported identify a customer issue ext-agents azure.ai.agents extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Issue] Role assignment is not automatically done in agent provision stage

6 participants