Skip to content

ci: replace Azure DevOps Marketplace PAT with Microsoft Entra OIDC publishing #489

Description

Summary

Migrate VS Code Marketplace publishing for AgentOpsAccelerator.agentops-accelerator from the Azure DevOps VSCE_PAT to Microsoft Entra authentication using GitHub Actions OIDC and a dedicated user-assigned managed identity.

Keep RELEASE_PAT unchanged. It is a GitHub credential used by cut-release.yml, not the Azure DevOps Marketplace credential being retired. PyPI and TestPyPI already use Trusted Publishing and should remain unchanged.

Why

The maintainer's organization now restricts Azure DevOps PAT creation to Packaging scopes. Packaging does not grant Marketplace publishing permissions, so creating or renewing the required Marketplace: Manage PAT is no longer a sustainable release mechanism.

Both .github/workflows/staging.yml and .github/workflows/release.yml currently publish with secrets.VSCE_PAT and vsce publish -p. The local staging/release scripts also reference this credential.

Feasibility evidence

An isolated test on 2026-09-06 succeeded:

https://github.com/Azure/agentops/actions/runs/34046045685/attempts/3

  • Created a temporary managed identity in the maintainer's mcaps-paulolacerda subscription in the Microsoft Non-Production tenant.
  • Authenticated that identity from a temporary GitHub Actions branch using OIDC, without a PAT or client secret.
  • Used the maintainer's corporate identity, which is an Owner of the publisher, to grant the temporary identity Contributor access.
  • Confirmed that the managed identity could access the publisher's role-assignment API using both Bearer authentication and the Basic OAuth authentication format used by vsce.
  • Confirmed its explicit Contributor role, whose returned description permits publishing and managing extensions.

Scope of evidence: this tested authentication and publishing-role authorization, not an extension upload or the vsce publish operation. It does not certify internal policy approval for production use of a Non-Production tenant identity.

The temporary publisher membership, managed identity, federated credential, resource group, and remote branch were removed. Production workflows and existing secrets were not changed. The successful run remains as evidence; its temporary identity must not be reused.

Implementation scope

  • Confirm the approved subscription/tenant and operational owner for a permanent publishing identity. Use a dedicated identity rather than repurposing the existing shared E2E Azure credentials.
  • Configure workload identity federation with trust restricted to the intended repository and staging/release execution contexts. Grant Contributor on the Marketplace publisher, not Owner. Do not add broad Azure RBAC grants solely for Marketplace access; the probe worked without an Azure role assignment.
  • Respect the repository's custom OIDC subject. It uses repository_owner_id, repository_id, and context, rather than the default repo:owner/repo:... subject. The probe initially failed until its federated credential matched the actual emitted subject. Inspect repos/Azure/agentops/actions/oidc/customization/sub and match the production jobs' actual branch/tag/environment context; do not copy the temporary branch subject or change the repository-wide OIDC configuration.
  • Update the Marketplace jobs in staging.yml and release.yml to request id-token: write, authenticate with Entra, and publish using a compatible vsce version and --azure-credential. Remove their VSCE_PAT environment wiring and -p usage. Use an explicit identity configuration so shared repository Azure variables cannot accidentally select the E2E identity.
  • Update scripts/staging.sh, scripts/staging.ps1, scripts/release.sh, and scripts/release.ps1 so maintained local publishing paths support Entra authentication without requiring an Azure DevOps PAT. Document the correct tenant/account selection for interactive publishing.
  • Update docs/release-process.md, .github/skills/release-management/SKILL.md, and related workflow/script comments with identity setup, custom OIDC subjects, publisher membership, troubleshooting, and the distinction between VSCE_PAT and RELEASE_PAT.
  • Preserve existing packaging, publisher/extension identity, versioning, and PyPI/TestPyPI behavior. Authentication failures must remain explicit; do not silently skip Marketplace publication or introduce a PAT fallback.
  • After the replacement is configured and verified, remove the obsolete VSCE_PAT GitHub secret and have its owner revoke the underlying Azure DevOps token, after confirming it has no other consumers. Do not retrieve or log secret values.

Acceptance criteria

  • Permanent identity placement and ownership are approved for the intended use.
  • Staging and stable publishing jobs authenticate with the intended identity via GitHub OIDC, with no Azure DevOps PAT or client secret.
  • The identity has the required Marketplace Contributor membership and federation is restricted to the intended execution contexts.
  • A permission preflight confirms the identity's explicit publishing role; a generic successful read alone is not treated as proof of upload capability.
  • An explicitly authorized release validates actual vsce publishing for the supported pre-release/stable flows. Do not publish dummy or unexpected versions of the production extension as a test.
  • Authentication and publisher-permission failures are surfaced clearly, without leaking tokens.
  • Local publishing scripts and maintainer documentation no longer require VSCE_PAT.
  • RELEASE_PAT, GitHub release preparation, and PyPI/TestPyPI Trusted Publishing remain functional and unchanged in purpose.
  • The obsolete Marketplace secret/token is retired only after successful migration.

Reference

Official VS Code guidance: secure automated Marketplace publishing with Entra authentication

Implementation should start from develop and target develop in the PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions