Skip to content

[ACR] Fallback ACR token challenge handling for 403 responses without WWW-Authenticate#33460

Draft
Copilot wants to merge 3 commits into
devfrom
copilot/fix-az-acr-workflow-issue
Draft

[ACR] Fallback ACR token challenge handling for 403 responses without WWW-Authenticate#33460
Copilot wants to merge 3 commits into
devfrom
copilot/fix-az-acr-workflow-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 28, 2026

Related command
az acr supply-chain workflow create --run-immediately true

Description
Cloud Shell can return 403 (without WWW-Authenticate) on initial registry challenge, which breaks auth negotiation for OCI artifact push flows that assume a 401 challenge header. This change adds a targeted AAD-only fallback so token exchange can proceed when that header is absent.

  • Challenge handling hardening (acr/_docker_utils.py)

    • Keep strict challenge validation (401/403 only).
    • When is_aad_token=True and response is 403 with no WWW-Authenticate, synthesize token params using standard ACR endpoints (/oauth2/token, service=<login_server>).
    • Preserve existing failure behavior for non-AAD paths and unsupported responses.
  • Behavioral coverage (test_acr_commands_mock.py)

    • Added unit test for get_access_credentials fallback path on 403 without challenge header.
    • Added unit test for 403 with WWW-Authenticate (normal parse path).
    • Added unit test verifying non-AAD auth still rejects 403 without challenge header.
# New fallback path in _handle_challenge_phase(...)
if is_aad_token and challenge.status_code == 403 and not challenge.headers.get("WWW-Authenticate"):
    return {
        "realm": f"https://{login_server}/oauth2/token",
        "service": login_server
    }

Testing Guide

  • Repro path: run az acr supply-chain workflow create ... --run-immediately true from Cloud Shell against a registry that returns 403 without WWW-Authenticate on initial challenge.
  • Validation expectation: auth token exchange proceeds via fallback instead of failing at challenge parsing.

History Notes
[ACR] az acr supply-chain workflow create: add AAD token-challenge fallback when registry returns 403 without WWW-Authenticate during OCI push auth negotiation.


This checklist is used to make sure that common guidelines for a pull request are followed.

@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd Bot commented May 28, 2026

️✔️AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
️✔️acs
️✔️latest
️✔️3.12
️✔️3.13
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.13
️✔️ams
️✔️latest
️✔️3.12
️✔️3.13
️✔️apim
️✔️latest
️✔️3.12
️✔️3.13
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.13
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️aro
️✔️latest
️✔️3.12
️✔️3.13
️✔️backup
️✔️latest
️✔️3.12
️✔️3.13
️✔️batch
️✔️latest
️✔️3.12
️✔️3.13
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.13
️✔️billing
️✔️latest
️✔️3.12
️✔️3.13
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.13
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.13
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.13
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.13
️✔️config
️✔️latest
️✔️3.12
️✔️3.13
️✔️configure
️✔️latest
️✔️3.12
️✔️3.13
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.13
️✔️container
️✔️latest
️✔️3.12
️✔️3.13
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.13
️✔️core
️✔️latest
️✔️3.12
️✔️3.13
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.13
️✔️databoxedge
️✔️latest
️✔️3.12
️✔️3.13
️✔️dls
️✔️latest
️✔️3.12
️✔️3.13
️✔️dms
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.13
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.13
️✔️find
️✔️latest
️✔️3.12
️✔️3.13
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.13
️✔️identity
️✔️latest
️✔️3.12
️✔️3.13
️✔️iot
️✔️latest
️✔️3.12
️✔️3.13
️✔️keyvault
️✔️latest
️✔️3.12
️✔️3.13
️✔️lab
️✔️latest
️✔️3.12
️✔️3.13
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️maps
️✔️latest
️✔️3.12
️✔️3.13
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.13
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.13
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.13
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.13
️✔️network
️✔️latest
️✔️3.12
️✔️3.13
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.13
️✔️postgresql
️✔️latest
️✔️3.12
️✔️3.13
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.13
️✔️profile
️✔️latest
️✔️3.12
️✔️3.13
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.13
️✔️redis
️✔️latest
️✔️3.12
️✔️3.13
️✔️relay
️✔️latest
️✔️3.12
️✔️3.13
️✔️resource
️✔️latest
️✔️3.12
️✔️3.13
️✔️role
️✔️latest
️✔️3.12
️✔️3.13
️✔️search
️✔️latest
️✔️3.12
️✔️3.13
️✔️security
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.13
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.13
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.13
️✔️sql
️✔️latest
️✔️3.12
️✔️3.13
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.13
️✔️storage
️✔️latest
️✔️3.12
️✔️3.13
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.13
️✔️telemetry
️✔️latest
️✔️3.12
️✔️3.13
️✔️util
️✔️latest
️✔️3.12
️✔️3.13
️✔️vm
️✔️latest
️✔️3.12
️✔️3.13

@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd Bot commented May 28, 2026

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

Copilot AI changed the title [WIP] Fix az acr supply-chain workflow create command failure in Cloud Shell [ACR] Fallback ACR token challenge handling for 403 responses without WWW-Authenticate May 28, 2026
Copilot finished work on behalf of a0x1ab May 28, 2026 09:34
Copilot AI requested a review from a0x1ab May 28, 2026 09:34
@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented May 28, 2026

ACR

@a0x1ab
Copy link
Copy Markdown
Member

a0x1ab commented May 28, 2026

Live test results — azdev test acr --live --series

FAIL (exit 1)

Module: acr
PR head ref: copilot/fix-az-acr-workflow-issue
PR head sha: 4ca684a7ed5b5180f5469d81502b4332252aaaad
PR base ref: dev
New test files in PR: false

Workflow run: https://github.com/Azure/issue-sentinel/actions/runs/26572258516

Last 80 lines of azdev output
                         self.check('provisioningState', 'Succeeded'),
                         self.check('os', 'Linux'),
                         self.check('location', '{rg_loc}'),
                         self.check('resourceGroup', '{rg}')])
    
        # Create a S2 tier agentpool in a VNET.
>       self.cmd('acr agentpool create -n {agents2_name} -r {registry_name} --tier s2 --subnet-id {subnet_id}',
                 checks=[self.check('name', '{agents2_name}'),
                         self.check('count', 1),
                         self.check('tier', 'S2'),
                         self.check('virtualNetworkSubnetResourceId', '{subnet_id}'),
                         self.check('provisioningState', 'Succeeded'),
                         self.check('os', 'Linux'),
                         self.check('location', '{rg_loc}'),
                         self.check('resourceGroup', '{rg}')])

src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_agentpool_commands.py:52: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
src/azure-cli-testsdk/azure/cli/testsdk/base.py:177: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/base.py:252: in __init__
    self._in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:315: in _in_process_execute
    raise ex.exception
.venv/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/__init__.py:677: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/__init__.py:820: in _run_jobs_serially
    results.append(self._run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/__init__.py:800: in _run_job
    result = LongRunningOperation(cmd_copy.cli_ctx, 'Starting {}'.format(cmd_copy.name))(result)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/__init__.py:1181: in __call__
    raise exception
src/azure-cli-core/azure/cli/core/commands/__init__.py:1168: in __call__
    result = poller.result()
             ^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/azure/core/polling/_poller.py:323: in result
    self.wait(timeout)
.venv/lib/python3.12/site-packages/azure/core/tracing/decorator.py:119: in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/azure/core/polling/_poller.py:342: in wait
    raise self._exception  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/azure/core/polling/_poller.py:247: in _start
    self._polling_method.run()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <azure.mgmt.core.polling.arm_polling.ARMPolling object at 0x7f53385978f0>

    def run(self) -> None:
        try:
            self._poll()
    
        except BadStatus as err:
            self._status = "Failed"
            raise HttpResponseError(response=self._pipeline_response.http_response, error=err) from err
    
        except BadResponse as err:
            self._status = "Failed"
            raise HttpResponseError(
                response=self._pipeline_response.http_response,
                message=str(err),
                error=err,
            ) from err
    
        except OperationFailed as err:
>           raise HttpResponseError(response=self._pipeline_response.http_response, error=err) from err
E           azure.core.exceptions.HttpResponseError: (Runtime failure) The status for Agent Pool agents2 is Failed. Error Message: [05/28/2026 12:33:03 +00:00] Deployment failed: Deployment with id '/subscriptions/e8444a11-ad4e-4d79-8f48-22c96fc0d932/resourceGroups/ap-clireggrun4wb3ybcadc-agents2-3c6/providers/Microsoft.Resources/deployments/74ae449e-f0d1-4271-ae70-43d9fb682ad8' failed. CorrelationId: '0c94ae13-4934-4784-a6fb-87ec8ef574cb'. Registry Resource Id: /subscriptions/0c302431-1ad0-4187-87c9-d4cebcf7edc2/resourceGroups/clitest.rgosbr5nc3xnj3mpu2copgmztwl7elrrbfvrs42mnnax5vgvq2ov6vcn7eezczw5sg3/providers/Microsoft.ContainerRegistry/registries/clireggrun4wb3ybcadc. 
E           Code: Runtime failure
E           Message: The status for Agent Pool agents2 is Failed. Error Message: [05/28/2026 12:33:03 +00:00] Deployment failed: Deployment with id '/subscriptions/e8444a11-ad4e-4d79-8f48-22c96fc0d932/resourceGroups/ap-clireggrun4wb3ybcadc-agents2-3c6/providers/Microsoft.Resources/deployments/74ae449e-f0d1-4271-ae70-43d9fb682ad8' failed. CorrelationId: '0c94ae13-4934-4784-a6fb-87ec8ef574cb'. Registry Resource Id: /subscriptions/0c302431-1ad0-4187-87c9-d4cebcf7edc2/resourceGroups/clitest.rgosbr5nc3xnj3mpu2copgmztwl7elrrbfvrs42mnnax5vgvq2ov6vcn7eezczw5sg3/providers/Microsoft.ContainerRegistry/registries/clireggrun4wb3ybcadc.

.venv/lib/python3.12/site-packages/azure/core/polling/base_polling.py:965: HttpResponseError
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
=================== 1 failed, 3 passed in 3236.10s (0:53:56) ===================

Posted by agent-assist live-test workflow.

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

Labels

None yet

Projects

None yet

3 participants