From 25026c78d8886a88a8ca3e8e334dc50c13720bf9 Mon Sep 17 00:00:00 2001 From: Daniel Jurek Date: Wed, 12 Aug 2026 07:43:56 -0700 Subject: [PATCH] [CFS] Fix cargo feed auth for fork builds "cmake build All" fails in public PR validation for fork PRs with: token rejected for `azure-sdk-for-rust` failed to get successful HTTP response from .../_packaging/azure-sdk-for-rust/Cargo/index/config.json, got 401 TF400813: The user 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' is not authorized Two problems, both already solved in azure-sdk-for-rust (eng/templates/config.toml.template and eng/pipelines/templates/steps/use-rust.yml): 1. The feed was the org-scoped azure-sdk-for-rust index with no ~force-auth suffix, so Azure DevOps answered the index anonymously. Point at the project-scoped public feed with ~force-auth, which reports auth-required and is the same crates.io upstream azure-sdk-for-rust consumes. 2. CargoAuthenticate@0 authenticates with SYSTEM_ACCESSTOKEN, which Azure DevOps does not deliver to fork builds. The task still reports success but writes the anonymous identity, so the failure only surfaces later when cargo fetches the index. NuGetAuthenticate@1 authenticates with the build's service connection, whose token fork builds do get, and publishes it as VSS_NUGET_ACCESSTOKEN; feed that to CargoAuthenticate@0 as SYSTEM_ACCESSTOKEN. NuGetAuthenticate@1 is declared in cmake-build.yml rather than taken from nuget-config.yml because archetype-sdk-client.yml includes cmake-build.yml without it. Validated on build 6688949: "cmake build All" 27/27 (was 22 failing), 39/40 jobs green, and CFSClean compliant on every job with crates.io traffic gone. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f3a428db-e276-4363-afd9-a944e8533203 --- eng/pipelines/templates/steps/cmake-build.yml | 23 +++++++++++++++++++ eng/templates/config.toml.template | 14 +++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/eng/pipelines/templates/steps/cmake-build.yml b/eng/pipelines/templates/steps/cmake-build.yml index 38f1dac72c..14598ee105 100644 --- a/eng/pipelines/templates/steps/cmake-build.yml +++ b/eng/pipelines/templates/steps/cmake-build.yml @@ -30,10 +30,33 @@ steps: Write-Host "##vso[task.setvariable variable=CargoConfigPath]$configPath" displayName: Configure cargo to use the azure-sdk-for-rust feed + # Workaround issue in public pipelines. Revert when root cause issue is fixed: + # https://github.com/microsoft/azure-pipelines-tasks/issues/22421 + # CargoAuthenticate@0 authenticates with SYSTEM_ACCESSTOKEN, which Azure DevOps does + # not deliver to fork builds. The task still "succeeds", but writes the anonymous + # identity, and cargo then fails the index fetch with 401 / TF400813 for user + # aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa. NuGetAuthenticate@1 authenticates with the + # build's service connection, whose token Azure DevOps does deliver to fork builds, and + # publishes it as VSS_NUGET_ACCESSTOKEN for later steps. It runs as + # `public Build Service (azure-sdk)`, which holds Feed and Upstream Reader on the cargo + # feed. + # + # This is declared here rather than relying on nuget-config.yml because + # archetype-sdk-client.yml includes this template without it. + - task: NuGetAuthenticate@1 + displayName: Acquire an Azure Artifacts token that fork builds can use + - task: CargoAuthenticate@0 displayName: Authenticate cargo to the azure-sdk-for-rust feed inputs: configFile: $(CargoConfigPath) + # Workaround issue in public pipelines. Revert when root cause is fixed: + # https://github.com/microsoft/azure-pipelines-tasks/issues/22421 + # + # NuGetAuthenticate@1 above publishes the endpoint token as VSS_NUGET_ACCESSTOKEN, + # which is populated in fork builds and useful as SYSTEM_ACCESSTOKEN here. + env: + SYSTEM_ACCESSTOKEN: $(VSS_NUGET_ACCESSTOKEN) - script: cmake --version workingDirectory: build diff --git a/eng/templates/config.toml.template b/eng/templates/config.toml.template index 3d77616cd4..3299314b3d 100644 --- a/eng/templates/config.toml.template +++ b/eng/templates/config.toml.template @@ -6,15 +6,21 @@ # CMake/Corrosion invokes cargo for the azure-core-amqp rust_wrapper crate. # # CargoAuthenticate@0 parses the [registries] table below and exports the -# CARGO_REGISTRIES_AZURE_SDK_FOR_RUST_TOKEN / _CREDENTIAL_PROVIDER variables that cargo -# needs to authenticate against the feed. +# CARGO_REGISTRIES_AZURE_SDK_FOR_RUST_PUBLIC_TOKEN / _CREDENTIAL_PROVIDER variables that +# cargo needs to authenticate against the feed. +# +# The feed is the project-scoped `public` one shared with azure-sdk-for-rust, and the +# `~force-auth` suffix on the feed name is required. Without it Azure DevOps answers the +# index anonymously, and cargo fails with "token rejected ... got 401" for the anonymous +# identity aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa. See +# https://learn.microsoft.com/azure/devops/artifacts/cargo/cargo-upstream-source. # # The [source] replacement is what actually redirects index.crates.io and # static.crates.io to the feed. Cargo does not honor environment variables for the # [source] table, so an on-disk config file is required. [registries] -azure-sdk-for-rust = { index = "sparse+https://pkgs.dev.azure.com/azure-sdk/_packaging/azure-sdk-for-rust/Cargo/index/" } +azure-sdk-for-rust-public = { index = "sparse+https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-rust-public~force-auth/Cargo/index/" } [source.crates-io] -replace-with = "azure-sdk-for-rust" +replace-with = "azure-sdk-for-rust-public"