From dc6a6d2d93f5415bc44b752f42cd8d5fdc5066eb Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Wed, 16 Sep 2026 15:42:49 +1000 Subject: [PATCH 01/16] fix(acr): restrict connected registry permissions to sync tokens Transplant the authentication discriminator, ManagedIdentity target guards, SyncToken-only help, and focused source unit tests. Source PR: https://github.com/Azure/azure-cli/pull/33910 Source SHA: e0b76941d9f5518bdd82529ef62eef89b43a3d45 --- .../cli/command_modules/acr/_constants.py | 6 + .../azure/cli/command_modules/acr/_help.py | 6 +- .../command_modules/acr/connected_registry.py | 31 ++++ .../test_acr_connected_registry_mi_unit.py | 152 ++++++++++++++++++ 4 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py diff --git a/src/azure-cli/azure/cli/command_modules/acr/_constants.py b/src/azure-cli/azure/cli/command_modules/acr/_constants.py index 5f87cda299c..1d1ea2cfe26 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_constants.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_constants.py @@ -15,6 +15,12 @@ USER_ASSIGNED_IDENTITY_RESOURCE_ID_TEMPLATE = '/subscriptions/{sub_id}/resourceGroups/{rg}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identity_name}' + +class ConnectedRegistryAuthType(Enum): + SYNC_TOKEN = 'SyncToken' + MANAGED_IDENTITY = 'ManagedIdentity' + + TASK_RESOURCE_TYPE = REGISTRY_RESOURCE_TYPE + '/tasks' TASK_VALID_VSTS_URLS = ['visualstudio.com', 'dev.azure.com'] TASK_RESOURCE_ID_TEMPLATE = '/subscriptions/{sub_id}/resourceGroups/{rg}/providers/Microsoft.ContainerRegistry/registries/{reg}/tasks/{name}' diff --git a/src/azure-cli/azure/cli/command_modules/acr/_help.py b/src/azure-cli/azure/cli/command_modules/acr/_help.py index 6a0eb168315..baecd50e3f8 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_help.py @@ -1727,12 +1727,12 @@ helps['acr connected-registry permissions'] = """ type: group -short-summary: Manage the repository permissions accross multiple connected registries. Please see https://aka.ms/acr/connected-registry for more information. +short-summary: Manage the repository permissions across multiple connected registries. Only supported for connected registries configured with SyncToken authentication (output is derived from the sync-token scope map). Please see https://aka.ms/acr/connected-registry for more information. """ helps['acr connected-registry permissions update'] = """ type: command -short-summary: Add and remove repository permissions accross all the necessary connected registry sync scope maps. +short-summary: Add and remove repository permissions across all the necessary connected registry sync scope maps. Only supported for connected registries configured with SyncToken authentication. examples: - name: Add permissions to synchronize images from 'repo1' and 'repo2' to the connected registry 'myconnectedregistry' and its ancestors. text: > @@ -1747,7 +1747,7 @@ helps['acr connected-registry permissions show'] = """ type: command -short-summary: Show the connected registry sync scope map information. +short-summary: Show the connected registry sync scope map information. Only supported for connected registries configured with SyncToken authentication. examples: - name: Show details and attributes of a sync scope map for a connected registry. text: > diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index 24cc66efa62..720324e981b 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -11,7 +11,9 @@ from azure.cli.core.commands import LongRunningOperation from azure.cli.core.commands.client_factory import get_subscription_id from azure.cli.core.util import user_confirmation +from azure.mgmt.containerregistry.models import ManagedServiceIdentityType from ._client_factory import cf_acr_tokens, cf_acr_scope_maps, cf_acr_registries +from ._constants import ConnectedRegistryAuthType from ._utils import ( build_token_id, create_default_scope_map, @@ -41,6 +43,23 @@ class ConnectedRegistryModes(Enum): REPOSITORY = "repositories/" GATEWAY = "gateway/" +AUTH_TYPE_SYNC_TOKEN = ConnectedRegistryAuthType.SYNC_TOKEN.value +AUTH_TYPE_MANAGED_IDENTITY = ConnectedRegistryAuthType.MANAGED_IDENTITY.value +MSI_TYPE_USER_ASSIGNED = ManagedServiceIdentityType.USER_ASSIGNED.value + + +def _get_current_auth_type(connected_registry): + """Return the current auth type ('SyncToken' or 'ManagedIdentity') of a connected registry. + + ``authType`` is the RP's canonical discriminator. Legacy resources predate the field and + deserialize as ``None`` — those are SyncToken by definition. + """ + auth_type = connected_registry.parent.sync_properties.auth_type + # SDK deserializes auth_type as an ``AuthType`` enum; use ``.value`` when available. + auth_type = getattr(auth_type, 'value', auth_type) + return auth_type or AUTH_TYPE_SYNC_TOKEN + + logger = get_logger(__name__) @@ -624,6 +643,12 @@ def acr_connected_registry_permissions_show(cmd, cmd, registry_name, resource_group_name) connected_registry = acr_connected_registry_show( cmd, client, connected_registry_name, registry_name, resource_group_name) + if _get_current_auth_type(connected_registry) == AUTH_TYPE_MANAGED_IDENTITY: + raise ArgumentUsageError( + "'az acr connected-registry permissions show' is not supported for a connected registry " + "using ManagedIdentity authentication. View the managed identity's Azure role assignments " + "and ABAC conditions to determine its repository permissions." + ) sync_token = get_token_from_id(cmd, connected_registry.parent.sync_properties.token_id) return get_scope_map_from_id(cmd, sync_token.scope_map_id) @@ -653,6 +678,12 @@ def acr_connected_registry_permissions_update(cmd, family_tree, target_connected_registry = _get_family_tree(connected_registry_list, connected_registry_name) if target_connected_registry is None: raise CLIError("Connected registry '{}' doesn't exist.".format(connected_registry_name)) + if _get_current_auth_type(target_connected_registry) == AUTH_TYPE_MANAGED_IDENTITY: + raise ArgumentUsageError( + "'az acr connected-registry permissions update' is not supported for a connected registry " + "using ManagedIdentity authentication. Update the ABAC conditions on the managed identity's " + "Azure role assignments to grant or revoke its repository permissions." + ) # remove repo permissions from connected registry descendants. remove_actions = REPO_SCOPES_BY_MODE[ConnectedRegistryModes.READWRITE.value] diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py new file mode 100644 index 00000000000..ed1134dcdd4 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -0,0 +1,152 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +"""Unit tests for managed-identity connected registry creation and permissions.""" + +import unittest +from unittest import mock + +from azure.cli.core.azclierror import ArgumentUsageError + +from azure.mgmt.containerregistry.models import ManagedServiceIdentityType + +from azure.cli.command_modules.acr._constants import ConnectedRegistryAuthType + +from azure.cli.command_modules.acr.connected_registry import ( + _get_current_auth_type, + acr_connected_registry_permissions_show, + acr_connected_registry_permissions_update, + AUTH_TYPE_MANAGED_IDENTITY, + AUTH_TYPE_SYNC_TOKEN, + MSI_TYPE_USER_ASSIGNED, +) + + +TEST_SUB = '00000000-0000-0000-0000-000000000001' +TEST_RG = 'rg' +TEST_REGISTRY = 'testreg' +TEST_CR = 'testcr123' +TEST_MSI_ID = ( + '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ManagedIdentity/' + 'userAssignedIdentities/msi1'.format(TEST_SUB, TEST_RG) +) + + +def _make_cmd(): + cmd = mock.MagicMock() + cmd.cli_ctx = mock.MagicMock() + return cmd + + +def _fake_cr(auth_type=None, has_identity=False, connection_state=None, + token_id=None, gateway_endpoint='parent.example.com', client_id='cid-1'): + """Build a fake connected-registry return object shaped like the SDK model.""" + cr = mock.MagicMock() + cr.name = TEST_CR + cr.mode = 'ReadOnly' + cr.connection_state = connection_state + cr.client_token_ids = None + cr.notifications_list = None + cr.parent = mock.MagicMock() + cr.parent.id = None + cr.parent.sync_properties = mock.MagicMock() + # Real MI-configured connected registries always have authType=ManagedIdentity set alongside + # the identity. Preserve that invariant when callers don't override auth_type explicitly. + if auth_type is None and has_identity: + auth_type = AUTH_TYPE_MANAGED_IDENTITY + cr.parent.sync_properties.auth_type = auth_type + cr.parent.sync_properties.token_id = token_id + cr.parent.sync_properties.gateway_endpoint = gateway_endpoint + if has_identity: + cr.identity = mock.MagicMock() + cr.identity.type = MSI_TYPE_USER_ASSIGNED + msi = mock.MagicMock() + msi.client_id = client_id + cr.identity.user_assigned_identities = {TEST_MSI_ID: msi} + else: + cr.identity = None + return cr + + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- + + +class TestConstantsSourcedFromEnum(unittest.TestCase): + """The module constants must match the ConnectedRegistryAuthType enum values verbatim.""" + + def test_auth_type_constants(self): + self.assertEqual(AUTH_TYPE_SYNC_TOKEN, ConnectedRegistryAuthType.SYNC_TOKEN.value) + self.assertEqual(AUTH_TYPE_MANAGED_IDENTITY, ConnectedRegistryAuthType.MANAGED_IDENTITY.value) + + def test_msi_type_constant(self): + self.assertEqual(MSI_TYPE_USER_ASSIGNED, ManagedServiceIdentityType.USER_ASSIGNED.value) + + +# --------------------------------------------------------------------------- +# Helper: _get_current_auth_type +# --------------------------------------------------------------------------- + + +class TestGetCurrentAuthType(unittest.TestCase): + + def test_managed_identity_auth_type(self): + cr = _fake_cr(auth_type=AUTH_TYPE_MANAGED_IDENTITY, has_identity=True) + self.assertEqual(_get_current_auth_type(cr), AUTH_TYPE_MANAGED_IDENTITY) + + def test_sync_token_auth_type_no_identity(self): + cr = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN, has_identity=False) + self.assertEqual(_get_current_auth_type(cr), AUTH_TYPE_SYNC_TOKEN) + + def test_missing_auth_type_defaults_to_sync_token(self): + cr = _fake_cr(auth_type=None, has_identity=False) + self.assertEqual(_get_current_auth_type(cr), AUTH_TYPE_SYNC_TOKEN) + + def test_enum_valued_auth_type_is_coerced_to_string(self): + cr = _fake_cr(auth_type=ConnectedRegistryAuthType.MANAGED_IDENTITY, has_identity=False) + result = _get_current_auth_type(cr) + self.assertEqual(result, AUTH_TYPE_MANAGED_IDENTITY) + self.assertIsInstance(result, str) + self.assertNotIn('ConnectedRegistryAuthType.', result) + + +UPDATE_MODULE = 'azure.cli.command_modules.acr.connected_registry' + + +# --------------------------------------------------------------------------- +# permissions show / update: blocked on MI +# --------------------------------------------------------------------------- + + +class TestConnectedRegistryPermissionsMI(unittest.TestCase): + + def test_permissions_show_blocked_on_mi(self): + cr = _fake_cr(has_identity=True) + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', + return_value=(None, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.acr_connected_registry_show', + return_value=cr): + with self.assertRaises(ArgumentUsageError): + acr_connected_registry_permissions_show( + cmd=_make_cmd(), client=mock.MagicMock(), + connected_registry_name=TEST_CR, registry_name=TEST_REGISTRY, + resource_group_name=TEST_RG) + + def test_permissions_update_blocked_on_mi(self): + cr = _fake_cr(has_identity=True) + client = mock.MagicMock() + client.list.return_value = [cr] + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', + return_value=(None, TEST_RG)): + with self.assertRaises(ArgumentUsageError): + acr_connected_registry_permissions_update( + cmd=_make_cmd(), client=client, + connected_registry_name=TEST_CR, registry_name=TEST_REGISTRY, + add_repos=['r1'], resource_group_name=TEST_RG) + + +if __name__ == '__main__': + unittest.main() From 19311da5e15777526303b306678ed9764f4b080d Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Wed, 16 Sep 2026 15:45:37 +1000 Subject: [PATCH 02/16] feat(acr): add managed identity connected registry creation Transplant CREATE options, inline authentication branches, identity shaping, request payload, example, and source validation tests. Retain cmd.get_models and legacy SyncToken validation. Require a nonblank identity and reject explicitly supplied incompatible options. Enforce top-level MI and immediate-parent leaf guards before mutations; defer data-endpoint enablement until parent validation. Cover the guards and real SDK payload/token paths. Source PR: https://github.com/Azure/azure-cli/pull/33910 Source SHA: e0b76941d9f5518bdd82529ef62eef89b43a3d45 --- .../azure/cli/command_modules/acr/_help.py | 9 + .../azure/cli/command_modules/acr/_params.py | 3 + .../command_modules/acr/connected_registry.py | 76 +++++-- .../test_acr_connected_registry_mi_unit.py | 202 +++++++++++++++++- 4 files changed, 272 insertions(+), 18 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/_help.py b/src/azure-cli/azure/cli/command_modules/acr/_help.py index baecd50e3f8..a9ae9443e8c 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_help.py @@ -1628,6 +1628,10 @@ helps['acr connected-registry create'] = """ type: command short-summary: Create a connected registry for an Azure Container Registry. +long-summary: | + ManagedIdentity authentication requires --identity and cannot be combined with --parent, --sync-token, or --repository. + ManagedIdentity connected registries must be top-level and cannot have children. + If --auth-type is omitted, SyncToken authentication is used. examples: - name: Create a connected registry in registry mode with access to repos app/hello-world and service/mycomponent. It'll create a sync token and scope-map with the right repo permissions. text: | @@ -1642,6 +1646,11 @@ az acr connected-registry create -r mycloudregistry -n myreadonlyacr -p myconnectedregistry \\ --repository "app/mycomponent" -m ReadOnly -s "0 12 * * *" -w PT4H \\ --client-tokens myTokenName1 myTokenName2 + - name: Create a connected registry that authenticates with its parent using a user-assigned managed identity. + text: | + az acr connected-registry create --registry mycloudregistry --name myconnectedregistry \\ + --auth-type ManagedIdentity \\ + --identity "/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/myUserAssignedIdentity" """ helps['acr connected-registry delete'] = """ diff --git a/src/azure-cli/azure/cli/command_modules/acr/_params.py b/src/azure-cli/azure/cli/command_modules/acr/_params.py index b21117b5ee5..5bce84a1487 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_params.py @@ -25,6 +25,7 @@ from ._constants import ( AbacRoleAssignmentMode, + ConnectedRegistryAuthType, REGISTRY_RESOURCE_TYPE, WEBHOOK_RESOURCE_TYPE, REPLICATION_RESOURCE_TYPE, @@ -583,6 +584,8 @@ def load_arguments(self, _): # pylint: disable=too-many-statements help='Indicate whether garbage collection is enabled. It is enabled by default.', arg_type=get_three_state_flag(), required=False, default="true") c.argument('garbage_collection_schedule', options_list=['--gc-schedule'], help='Used to determine garbage collection schedule. Uses cron expression to determine the schedule. If not specified, garbage collection is set to run once a day.', required=False, default="0 0 * * *") + c.argument('identity', help='Resource ID of a user-assigned managed identity to authenticate the connected registry with its parent. Required when --auth-type is ManagedIdentity.') + c.argument('auth_type', arg_type=get_enum_type([e.value for e in ConnectedRegistryAuthType]), options_list=['--auth-type'], help='Authentication type used by the connected registry to sync with its parent. Defaults to SyncToken.') with self.argument_context('acr connected-registry update') as c: c.argument('log_level', help='Set the log level for logging on the instance. Accepted log levels are Debug, Information, Warning, Error, and None.') diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index 720324e981b..410fdf0219e 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -60,10 +60,19 @@ def _get_current_auth_type(connected_registry): return auth_type or AUTH_TYPE_SYNC_TOKEN +def _build_user_assigned_identity(cmd, identity_resource_id): + """Wrap a single user-assigned identity resource ID in a ManagedServiceIdentity.""" + ManagedServiceIdentity, UserAssignedIdentity = cmd.get_models('ManagedServiceIdentity', 'UserAssignedIdentity') + return ManagedServiceIdentity( + type=MSI_TYPE_USER_ASSIGNED, + user_assigned_identities={identity_resource_id: UserAssignedIdentity()} + ) + + logger = get_logger(__name__) -def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-many-statements +def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-many-statements, too-many-branches client, registry_name, connected_registry_name, @@ -81,32 +90,50 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m notifications=None, garbage_collection_enabled=None, garbage_collection_schedule=None, + identity=None, + auth_type=None, yes=False): - if bool(sync_token_name) == bool(repositories): - raise CLIError("argument error: either --sync-token or --repository must be provided, but not both.") + is_managed_identity = auth_type == AUTH_TYPE_MANAGED_IDENTITY + if is_managed_identity: + if not identity or identity.isspace(): + raise ArgumentUsageError( + "argument error: --identity is required " + "when --auth-type ManagedIdentity." + ) + if sync_token_name is not None or repositories is not None: + raise ArgumentUsageError( + "argument error: --sync-token and --repository are not applicable when " + "--auth-type ManagedIdentity." + ) + if parent_name is not None: + raise ArgumentUsageError( + "argument error: --parent is not applicable when --auth-type ManagedIdentity." + ) + else: + if identity is not None: + raise ArgumentUsageError( + "argument error: --identity is only applicable with --auth-type ManagedIdentity." + ) + if bool(sync_token_name) == bool(repositories): + raise CLIError("argument error: either --sync-token or --repository must be provided, but not both.") # Check needed since the sync token gateway actions must be at least 5 characters long. if len(connected_registry_name) < 5: raise InvalidArgumentValueError("argument error: Connected registry name must be at least 5 characters long.") subscription_id = get_subscription_id(cmd.cli_ctx) registry, resource_group_name = get_registry_by_name(cmd.cli_ctx, registry_name, resource_group_name) - if not registry.data_endpoint_enabled: - user_confirmation("Dedicated data endpoints must be enabled to use connected-registry. Enabling might " + - "impact your firewall rules. Are you sure you want to enable it for '{}' registry?".format( - registry_name), yes) - acr_update_custom(cmd, registry, data_endpoint_enabled=True) - registry_client = cf_acr_registries(cmd.cli_ctx) - LongRunningOperation(cmd.cli_ctx)( - acr_update_set(cmd, registry_client, registry_name, resource_group_name, registry) - ) - from azure.core.exceptions import HttpResponseError as ErrorResponseException parent = None mode = mode.lower() if parent_name: try: parent = acr_connected_registry_show(cmd, client, parent_name, registry_name, resource_group_name) + if _get_current_auth_type(parent) == AUTH_TYPE_MANAGED_IDENTITY: + raise ArgumentUsageError( + "A connected registry using ManagedIdentity authentication cannot have children. " + "Choose a SyncToken parent with --parent or omit --parent." + ) connected_registry_list = list(client.list(resource_group_name, registry_name)) family_tree, _ = _get_family_tree(connected_registry_list, None) except ErrorResponseException as ex: @@ -119,10 +146,24 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m "when the connected registry parent '{}' mode is '{}'. ".format(parent_name, parent.mode) + "For more information on connected registries " + "please visit https://aka.ms/acr/connected-registry.") + + if not registry.data_endpoint_enabled: + user_confirmation("Dedicated data endpoints must be enabled to use connected-registry. Enabling might " + + "impact your firewall rules. Are you sure you want to enable it for '{}' registry?".format( + registry_name), yes) + acr_update_custom(cmd, registry, data_endpoint_enabled=True) + registry_client = cf_acr_registries(cmd.cli_ctx) + LongRunningOperation(cmd.cli_ctx)( + acr_update_set(cmd, registry_client, registry_name, resource_group_name, registry) + ) + + if parent_name: _update_ancestor_permissions(cmd, family_tree, resource_group_name, registry_name, parent.id, connected_registry_name, repositories, mode, False) - if sync_token_name: + if is_managed_identity: + sync_token_id = None + elif sync_token_name: sync_token_id = build_token_id(subscription_id, resource_group_name, registry_name, sync_token_name) else: sync_token_id = _create_sync_token(cmd, resource_group_name, registry_name, @@ -141,7 +182,6 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m 'ConnectedRegistry', 'LoggingProperties', 'SyncProperties', 'ParentProperties', 'GarbageCollectionProperties') connected_registry_create_parameters = ConnectedRegistry( - provisioning_state=None, mode=mode, parent=ParentProperties( id=parent.id if parent else None, @@ -149,7 +189,8 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m token_id=sync_token_id, schedule=sync_schedule, message_ttl=sync_message_ttl, - sync_window=sync_window + sync_window=sync_window, + auth_type=AUTH_TYPE_MANAGED_IDENTITY if is_managed_identity else AUTH_TYPE_SYNC_TOKEN, ) ), client_token_ids=client_token_list, @@ -161,7 +202,8 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m enabled=garbage_collection_enabled, schedule=garbage_collection_schedule ), - notifications_list=list(notifications_set) if notifications_set else None + notifications_list=list(notifications_set) if notifications_set else None, + identity=_build_user_assigned_identity(cmd, identity) if is_managed_identity else None, ) try: diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py index ed1134dcdd4..4ef9b75149b 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -9,13 +9,21 @@ from unittest import mock from azure.cli.core.azclierror import ArgumentUsageError +from knack.util import CLIError -from azure.mgmt.containerregistry.models import ManagedServiceIdentityType +from azure.mgmt.containerregistry import models +from azure.mgmt.containerregistry.models import ( + ManagedServiceIdentity, + ManagedServiceIdentityType, + UserAssignedIdentity, +) from azure.cli.command_modules.acr._constants import ConnectedRegistryAuthType from azure.cli.command_modules.acr.connected_registry import ( + _build_user_assigned_identity, _get_current_auth_type, + acr_connected_registry_create, acr_connected_registry_permissions_show, acr_connected_registry_permissions_update, AUTH_TYPE_MANAGED_IDENTITY, @@ -113,6 +121,198 @@ def test_enum_valued_auth_type_is_coerced_to_string(self): self.assertNotIn('ConnectedRegistryAuthType.', result) +# --------------------------------------------------------------------------- +# Helper: _build_user_assigned_identity +# --------------------------------------------------------------------------- + + +class TestBuildUserAssignedIdentity(unittest.TestCase): + + def test_shape(self): + cmd = _make_cmd() + cmd.get_models.return_value = (ManagedServiceIdentity, UserAssignedIdentity) + identity = _build_user_assigned_identity(cmd, TEST_MSI_ID) + self.assertIsInstance(identity, ManagedServiceIdentity) + self.assertEqual(identity.type, MSI_TYPE_USER_ASSIGNED) + self.assertIn(TEST_MSI_ID, identity.user_assigned_identities) + self.assertIsInstance( + identity.user_assigned_identities[TEST_MSI_ID], UserAssignedIdentity) + + +# --------------------------------------------------------------------------- +# create: client-side argument validation +# --------------------------------------------------------------------------- + + +class TestConnectedRegistryCreateValidation(unittest.TestCase): + + def _create(self, **overrides): + kwargs = dict( + cmd=_make_cmd(), + client=mock.MagicMock(), + registry_name=TEST_REGISTRY, + connected_registry_name=TEST_CR, + mode='ReadOnly', + ) + kwargs.update(overrides) + return acr_connected_registry_create(**kwargs) + + def test_mi_requires_identity(self): + with self.assertRaises(ArgumentUsageError): + self._create(auth_type=AUTH_TYPE_MANAGED_IDENTITY) + + def test_mi_rejects_sync_token(self): + with self.assertRaises(ArgumentUsageError): + self._create(auth_type=AUTH_TYPE_MANAGED_IDENTITY, + identity=TEST_MSI_ID, sync_token_name='tok') + + def test_mi_rejects_repository(self): + with self.assertRaises(ArgumentUsageError): + self._create(auth_type=AUTH_TYPE_MANAGED_IDENTITY, + identity=TEST_MSI_ID, repositories=['r1']) + + def test_sync_token_rejects_identity(self): + with self.assertRaises(ArgumentUsageError): + self._create(auth_type=AUTH_TYPE_SYNC_TOKEN, identity=TEST_MSI_ID, + sync_token_name='tok') + + def test_sync_token_requires_exactly_one_of_token_or_repos(self): + with self.assertRaises(CLIError): + # neither + self._create(auth_type=AUTH_TYPE_SYNC_TOKEN) + with self.assertRaises(CLIError): + # both + self._create(auth_type=AUTH_TYPE_SYNC_TOKEN, + sync_token_name='tok', repositories=['r1']) + + def test_short_name_rejected(self): + with self.assertRaises(Exception): # InvalidArgumentValueError + self._create(auth_type=AUTH_TYPE_MANAGED_IDENTITY, + identity=TEST_MSI_ID, + connected_registry_name='abc') # < 5 chars + + def test_mi_rejects_blank_identity(self): + for identity in ('', ' ', '\t'): + with self.subTest(identity=identity), self.assertRaises(ArgumentUsageError): + self._create(auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=identity) + + def test_mi_rejects_explicit_empty_token_or_repositories(self): + for options in ({'sync_token_name': ''}, {'repositories': []}, {'repositories': ['']}): + with self.subTest(options=options), self.assertRaises(ArgumentUsageError): + self._create(auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=TEST_MSI_ID, **options) + + def test_identity_requires_explicit_managed_identity_auth(self): + for auth_type in (None, AUTH_TYPE_SYNC_TOKEN): + for identity in ('', TEST_MSI_ID): + with self.subTest(auth_type=auth_type, identity=identity), \ + self.assertRaises(ArgumentUsageError): + self._create(auth_type=auth_type, identity=identity, sync_token_name='tok') + + def test_mi_rejects_parent_before_registry_lookup(self): + with mock.patch(UPDATE_MODULE + '.get_registry_by_name') as get_registry, \ + mock.patch(UPDATE_MODULE + '.get_subscription_id') as get_subscription: + for parent_name in ('parentcr', ''): + with self.subTest(parent_name=parent_name), self.assertRaisesRegex(ArgumentUsageError, '--parent'): + self._create(auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=TEST_MSI_ID, + parent_name=parent_name) + get_registry.assert_not_called() + get_subscription.assert_not_called() + + def test_mi_parent_rejected_before_mutations(self): + parent = _fake_cr(has_identity=True) + client = mock.MagicMock() + registry = mock.MagicMock(data_endpoint_enabled=False) + with mock.patch(UPDATE_MODULE + '.get_subscription_id', return_value=TEST_SUB), \ + mock.patch(UPDATE_MODULE + '.get_registry_by_name', return_value=(registry, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.acr_connected_registry_show', return_value=parent) as show, \ + mock.patch(UPDATE_MODULE + '.acr_update_custom') as update_registry, \ + mock.patch(UPDATE_MODULE + '.acr_update_set') as set_registry, \ + mock.patch(UPDATE_MODULE + '._create_sync_token') as create_token, \ + mock.patch(UPDATE_MODULE + '._update_ancestor_permissions') as update_permissions: + for auth_type in (None, AUTH_TYPE_SYNC_TOKEN, AUTH_TYPE_MANAGED_IDENTITY): + with self.subTest(auth_type=auth_type), self.assertRaises(ArgumentUsageError): + options = {'identity': TEST_MSI_ID} if auth_type == AUTH_TYPE_MANAGED_IDENTITY else { + 'repositories': ['r1']} + self._create(client=client, parent_name='parentcr', auth_type=auth_type, **options) + self.assertEqual(show.call_count, 2) + client.list.assert_not_called() + client.begin_create.assert_not_called() + update_registry.assert_not_called() + set_registry.assert_not_called() + create_token.assert_not_called() + update_permissions.assert_not_called() + + +class TestConnectedRegistryCreatePayload(unittest.TestCase): + + def test_root_auth_payload_and_token_paths(self): + for auth_type, options in ( + (AUTH_TYPE_MANAGED_IDENTITY, {'identity': TEST_MSI_ID}), + (None, {'sync_token_name': 'sync-token'}), + (AUTH_TYPE_SYNC_TOKEN, {'repositories': ['r1']})): + with self.subTest(auth_type=auth_type): + cmd = _make_cmd() + cmd.get_models.side_effect = lambda *names: tuple(getattr(models, name) for name in names) + client = mock.MagicMock() + registry = mock.MagicMock(data_endpoint_enabled=True) + token_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ContainerRegistry/registries/{}/tokens/sync-token'.format( + TEST_SUB, TEST_RG, TEST_REGISTRY) + client_token_id = token_id.replace('/tokens/sync-token', '/tokens/client-token') + with mock.patch(UPDATE_MODULE + '.get_subscription_id', return_value=TEST_SUB), \ + mock.patch(UPDATE_MODULE + '.get_registry_by_name', return_value=(registry, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '._create_sync_token', return_value=token_id) as create_token, \ + mock.patch(UPDATE_MODULE + '.cf_acr_tokens') as tokens, \ + mock.patch(UPDATE_MODULE + '.cf_acr_scope_maps') as scope_maps, \ + mock.patch(UPDATE_MODULE + '._update_ancestor_permissions') as update_permissions: + result = acr_connected_registry_create( + cmd, client, TEST_REGISTRY, TEST_CR, mode='ReadOnly', auth_type=auth_type, + client_token_list=['client-token'], sync_schedule='0 12 * * *', sync_window='PT4H', + sync_message_ttl='P2D', log_level='Information', sync_audit_logs_enabled=True, + garbage_collection_enabled=True, garbage_collection_schedule='0 0 * * *', + notifications=['hello:latest', 'hello:latest'], **options) + self.assertIs(result, client.begin_create.return_value) + client.begin_create.assert_called_once() + call = client.begin_create.call_args.kwargs + self.assertEqual(call['resource_group_name'], TEST_RG) + self.assertEqual(call['registry_name'], TEST_REGISTRY) + self.assertEqual(call['connected_registry_name'], TEST_CR) + parameters = call['connected_registry_create_parameters'] + self.assertIsInstance(parameters, models.ConnectedRegistry) + expected_sync = { + 'authType': auth_type or AUTH_TYPE_SYNC_TOKEN, + 'schedule': '0 12 * * *', + 'messageTtl': 'P2D', + 'syncWindow': 'PT4H', + } + if auth_type == AUTH_TYPE_MANAGED_IDENTITY: + self.assertEqual(parameters.identity.as_dict(), { + 'type': 'UserAssigned', 'userAssignedIdentities': {TEST_MSI_ID: {}}}) + self.assertIsNone(parameters.parent.sync_properties.token_id) + create_token.assert_not_called() + else: + self.assertIsNone(parameters.identity) + expected_sync['tokenId'] = token_id + if 'repositories' in options: + create_token.assert_called_once_with( + cmd, TEST_RG, TEST_REGISTRY, TEST_CR, ['r1'], 'readonly') + else: + create_token.assert_not_called() + self.assertIsNone(parameters.parent.id) + self.assertEqual(parameters.parent.sync_properties.as_dict(), expected_sync) + self.assertEqual(parameters.mode, 'readonly') + self.assertEqual(parameters.client_token_ids, [client_token_id]) + self.assertEqual(parameters.logging.as_dict(), { + 'logLevel': 'Information', 'auditLogStatus': 'Enabled'}) + self.assertEqual(parameters.garbage_collection.as_dict(), { + 'enabled': True, 'schedule': '0 0 * * *'}) + self.assertEqual(parameters.notifications_list, ['hello:latest']) + client.get.assert_not_called() + client.list.assert_not_called() + tokens.assert_not_called() + scope_maps.assert_not_called() + update_permissions.assert_not_called() + + UPDATE_MODULE = 'azure.cli.command_modules.acr.connected_registry' From f729787da4f0a9b866c13f98f248b2c1ea98bf78 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Wed, 16 Sep 2026 16:29:32 +1000 Subject: [PATCH 03/16] feat(acr): add connected registry managed identity migration Reuse the UPDATE arguments, inline input handling and PATCH shaping from https://github.com/Azure/azure-cli/pull/33910, source e0b76941d9f5518bdd82529ef62eef89b43a3d45, with the existing SDK model helper. Keep ManagedIdentity as the only migration target. Require explicit auth type and a nonblank identity, while deferring current-auth and Offline eligibility checks to the RP. Correct the migration example and cover empty inputs, RP-error propagation, migration combined with ordinary property changes, and preservation of auth during ordinary updates. --- .../azure/cli/command_modules/acr/_help.py | 9 + .../azure/cli/command_modules/acr/_params.py | 2 + .../command_modules/acr/connected_registry.py | 33 +++- .../test_acr_connected_registry_mi_unit.py | 165 +++++++++++++++++- 4 files changed, 204 insertions(+), 5 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/_help.py b/src/azure-cli/azure/cli/command_modules/acr/_help.py index a9ae9443e8c..4f85ffe3953 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_help.py @@ -1710,6 +1710,10 @@ helps['acr connected-registry update'] = """ type: command short-summary: Update a connected registry for an Azure Container Registry. +long-summary: | + Only one-way migration from SyncToken to ManagedIdentity authentication is supported. + The service validates migration eligibility, including the required Offline state. + Run `az acr connected-registry deactivate` before invoking the migration. examples: - name: Update the connected registry client Tokens. text: | @@ -1720,6 +1724,11 @@ text: | az acr connected-registry update --registry mycloudregistry --name myreadonlyacr \\ --sync-schedule "0 12 * * *" --sync-window PT4H + - name: Migrate an offline connected registry from SyncToken to ManagedIdentity authentication. + text: | + az acr connected-registry update --registry mycloudregistry --name myconnectedregistry \\ + --auth-type ManagedIdentity \\ + --identity "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myUserAssignedIdentity" """ helps['acr connected-registry get-settings'] = """ diff --git a/src/azure-cli/azure/cli/command_modules/acr/_params.py b/src/azure-cli/azure/cli/command_modules/acr/_params.py index 5bce84a1487..f1fe726518f 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_params.py @@ -603,6 +603,8 @@ def load_arguments(self, _): # pylint: disable=too-many-statements c.argument('garbage_collection_enabled', options_list=['--gc-enabled'], help='Indicate whether garbage collection is enabled. It is enabled by default.', arg_type=get_three_state_flag()) c.argument('garbage_collection_schedule', options_list=['--gc-schedule'], help='Used to determine garbage collection schedule. Uses cron expression to determine the schedule. If not specified, garbage collection is set to run once a day.') + c.argument('identity', help='Resource ID of a user-assigned managed identity. Requires --auth-type ManagedIdentity.') + c.argument('auth_type', arg_type=get_enum_type([ConnectedRegistryAuthType.MANAGED_IDENTITY.value]), options_list=['--auth-type'], help='Target authentication type. Only one-way migration from SyncToken to ManagedIdentity is supported. The service validates migration eligibility, including the required Offline state.') with self.argument_context('acr connected-registry permissions') as c: c.argument('add_repos', options_list=['--add'], nargs='*', help='repository permissions to be added to the targeted connected registry and it\'s ancestors sync scope maps. Use the format "--add [REPO1 REPO2 ...]" per flag. ' + repo_valid_actions) diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index 410fdf0219e..3c391ce85fc 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -215,7 +215,7 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m raise CLIError(e) -def acr_connected_registry_update(cmd, # pylint: disable=too-many-locals, too-many-statements +def acr_connected_registry_update(cmd, # pylint: disable=too-many-locals, too-many-statements, too-many-branches client, registry_name, connected_registry_name, @@ -230,13 +230,36 @@ def acr_connected_registry_update(cmd, # pylint: disable=too-many-locals, too-m add_notifications=None, remove_notifications=None, garbage_collection_enabled=None, - garbage_collection_schedule=None): + garbage_collection_schedule=None, + identity=None, + auth_type=None): _, resource_group_name = validate_managed_registry( cmd, registry_name, resource_group_name) subscription_id = get_subscription_id(cmd.cli_ctx) current_connected_registry = acr_connected_registry_show( cmd, client, connected_registry_name, registry_name, resource_group_name) + # Only SyncToken -> ManagedIdentity migration is supported. + identity_update = None + sync_auth_type_update = None + + if auth_type is not None or identity is not None: + if not auth_type: + raise ArgumentUsageError( + "argument error: --auth-type is required when --identity is provided during update." + ) + if auth_type != AUTH_TYPE_MANAGED_IDENTITY: + raise ArgumentUsageError( + "argument error: only migration to --auth-type ManagedIdentity is supported." + ) + if not identity or identity.isspace(): + raise ArgumentUsageError( + "argument error: a non-empty --identity is required " + "when migrating to --auth-type ManagedIdentity." + ) + identity_update = _build_user_assigned_identity(cmd, identity) + sync_auth_type_update = AUTH_TYPE_MANAGED_IDENTITY + # Add or remove from the current client token id list if add_client_token_list is not None: for i, client_token_name in enumerate(add_client_token_list): @@ -294,7 +317,8 @@ def acr_connected_registry_update(cmd, # pylint: disable=too-many-locals, too-m sync_properties=SyncUpdateProperties( schedule=sync_schedule, message_ttl=sync_message_ttl, - sync_window=sync_window + sync_window=sync_window, + auth_type=sync_auth_type_update, ), logging=LoggingProperties( log_level=log_level, @@ -305,7 +329,8 @@ def acr_connected_registry_update(cmd, # pylint: disable=too-many-locals, too-m schedule=garbage_collection_schedule ), client_token_ids=client_token_list, - notifications_list=notifications_list + notifications_list=notifications_list, + identity=identity_update, ) try: diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py index 4ef9b75149b..023d0258238 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -3,11 +3,12 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -"""Unit tests for managed-identity connected registry creation and permissions.""" +"""Unit tests for managed-identity connected registry creation, permissions, and update.""" import unittest from unittest import mock +from azure.core.exceptions import HttpResponseError from azure.cli.core.azclierror import ArgumentUsageError from knack.util import CLIError @@ -26,6 +27,7 @@ acr_connected_registry_create, acr_connected_registry_permissions_show, acr_connected_registry_permissions_update, + acr_connected_registry_update, AUTH_TYPE_MANAGED_IDENTITY, AUTH_TYPE_SYNC_TOKEN, MSI_TYPE_USER_ASSIGNED, @@ -40,6 +42,7 @@ '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ManagedIdentity/' 'userAssignedIdentities/msi1'.format(TEST_SUB, TEST_RG) ) +TEST_MSI_ID2 = TEST_MSI_ID.replace('msi1', 'msi2') def _make_cmd(): @@ -348,5 +351,165 @@ def test_permissions_update_blocked_on_mi(self): add_repos=['r1'], resource_group_name=TEST_RG) +# --------------------------------------------------------------------------- +# update: input validation and PATCH shape +# --------------------------------------------------------------------------- + + +class TestConnectedRegistryUpdateMigration(unittest.TestCase): + + def _patch_common(self): + p_validate = mock.patch(UPDATE_MODULE + '.validate_managed_registry', + return_value=(None, TEST_RG)) + p_subid = mock.patch(UPDATE_MODULE + '.get_subscription_id', + return_value=TEST_SUB) + return p_validate, p_subid + + def _run_update(self, current, **overrides): + client = mock.MagicMock() + cmd = _make_cmd() + cmd.get_models.side_effect = lambda *names: tuple(getattr(models, name) for name in names) + kwargs = dict( + cmd=cmd, + client=client, + registry_name=TEST_REGISTRY, + connected_registry_name=TEST_CR, + resource_group_name=TEST_RG, + ) + kwargs.update(overrides) + p_validate, p_subid = self._patch_common() + with p_validate, p_subid, \ + mock.patch(UPDATE_MODULE + '.acr_connected_registry_show', return_value=current): + acr_connected_registry_update(**kwargs) + return client + + # ---- error paths ------------------------------------------------------ + + def test_identity_without_auth_type_errors(self): + cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN) + for identity in (TEST_MSI_ID, '', ' ', '\t', '\n'): + with self.subTest(identity=identity): + client = mock.MagicMock() + with self.assertRaisesRegex(ArgumentUsageError, '--auth-type is required'): + self._run_update(cur, client=client, identity=identity) + client.begin_update.assert_not_called() + + def test_migration_eligibility_errors_are_deferred_to_rp(self): + for auth_type, state, identity in ( + (AUTH_TYPE_SYNC_TOKEN, 'Online', TEST_MSI_ID), + (AUTH_TYPE_MANAGED_IDENTITY, 'Offline', TEST_MSI_ID2), + (AUTH_TYPE_MANAGED_IDENTITY, 'Offline', TEST_MSI_ID)): + with self.subTest(auth_type=auth_type, state=state, identity=identity): + cur = _fake_cr(auth_type=auth_type, + has_identity=auth_type == AUTH_TYPE_MANAGED_IDENTITY, + connection_state=state) + client = mock.MagicMock() + error = HttpResponseError(message='The requested migration is not allowed.') + client.begin_update.side_effect = error + with self.assertRaises(HttpResponseError) as caught: + self._run_update(cur, client=client, auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=identity) + self.assertIs(caught.exception, error) + client.begin_update.assert_called_once() + client.list.assert_not_called() + + def test_migrate_to_mi_requires_identity(self): + cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN) + for identity in (None, '', ' ', '\t', '\n'): + with self.subTest(identity=identity): + client = mock.MagicMock() + with self.assertRaisesRegex(ArgumentUsageError, 'non-empty --identity'): + self._run_update(cur, client=client, auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=identity) + client.begin_update.assert_not_called() + + def test_migrate_to_sync_token_rejected(self): + cur = _fake_cr(has_identity=True, connection_state='Offline') + with self.assertRaises(ArgumentUsageError) as ctx: + self._run_update(cur, auth_type=AUTH_TYPE_SYNC_TOKEN) + self.assertIn('only migration to --auth-type ManagedIdentity is supported', + str(ctx.exception)) + + # ---- success paths: assert PATCH body shape --------------------------- + + def _extract_update_body(self, client): + # begin_update(resource_group_name=..., registry_name=..., + # connected_registry_name=..., connected_registry_update_parameters=...) + self.assertTrue(client.begin_update.called) + _, kwargs = client.begin_update.call_args + return kwargs['connected_registry_update_parameters'] + + def test_migrate_sync_token_to_mi_sends_identity(self): + cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN, connection_state='Offline') + client = self._run_update(cur, auth_type=AUTH_TYPE_MANAGED_IDENTITY, + identity=TEST_MSI_ID) + body = self._extract_update_body(client) + self.assertIsNotNone(body.identity) + self.assertEqual(body.identity.type, MSI_TYPE_USER_ASSIGNED) + self.assertIn(TEST_MSI_ID, body.identity.user_assigned_identities) + self.assertEqual(body.sync_properties.auth_type, AUTH_TYPE_MANAGED_IDENTITY) + serialized = body.as_dict() + self.assertEqual(serialized['identity'], { + 'type': 'UserAssigned', 'userAssignedIdentities': {TEST_MSI_ID: {}}}) + self.assertEqual(serialized['properties']['syncProperties'], { + 'authType': AUTH_TYPE_MANAGED_IDENTITY}) + self.assertNotIn('parent', serialized['properties']) + self.assertNotIn('tokenId', serialized['properties']['syncProperties']) + + def test_migration_combines_with_ordinary_property_updates(self): + cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN, connection_state='Offline') + client = self._run_update( + cur, auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=TEST_MSI_ID, + sync_window='PT4H', log_level='Debug', garbage_collection_enabled=False, + add_client_token_list=['client-token'], add_notifications=['image:latest']) + serialized = self._extract_update_body(client).as_dict() + token_id = ( + '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ContainerRegistry/' + 'registries/{}/tokens/client-token'.format(TEST_SUB, TEST_RG, TEST_REGISTRY) + ) + self.assertEqual(serialized, { + 'identity': {'type': 'UserAssigned', 'userAssignedIdentities': {TEST_MSI_ID: {}}}, + 'properties': { + 'syncProperties': {'authType': AUTH_TYPE_MANAGED_IDENTITY, 'syncWindow': 'PT4H'}, + 'logging': {'logLevel': 'Debug'}, + 'garbageCollection': {'enabled': False}, + 'clientTokenIds': [token_id], + 'notificationsList': ['image:latest'], + }, + }) + client.begin_update.assert_called_once() + client.list.assert_not_called() + + def test_ordinary_update_preserves_auth_on_either_mode(self): + token_prefix = ( + '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ContainerRegistry/' + 'registries/{}/tokens/'.format(TEST_SUB, TEST_RG, TEST_REGISTRY) + ) + for auth_type in (None, AUTH_TYPE_SYNC_TOKEN, AUTH_TYPE_MANAGED_IDENTITY): + with self.subTest(auth_type=auth_type): + cur = _fake_cr(auth_type=auth_type, + has_identity=auth_type == AUTH_TYPE_MANAGED_IDENTITY, + connection_state='Online') + cur.client_token_ids = [token_prefix + 'old-token'] + cur.notifications_list = ['old:latest'] + client = self._run_update( + cur, add_client_token_list=['new-token'], remove_client_token_list=['old-token'], + sync_schedule='0 12 * * *', sync_window='PT4H', sync_message_ttl='P2D', + log_level='Information', sync_audit_logs_enabled='Enabled', + garbage_collection_enabled=False, garbage_collection_schedule='0 0 * * *', + add_notifications=['new:latest'], remove_notifications=['old:latest']) + serialized = self._extract_update_body(client).as_dict() + self.assertEqual(serialized, {'properties': { + 'syncProperties': { + 'schedule': '0 12 * * *', 'syncWindow': 'PT4H', 'messageTtl': 'P2D'}, + 'logging': {'logLevel': 'Information', 'auditLogStatus': 'Enabled'}, + 'garbageCollection': {'enabled': False, 'schedule': '0 0 * * *'}, + 'clientTokenIds': [token_prefix + 'new-token'], + 'notificationsList': ['new:latest'], + }}) + self.assertNotIn('identity', serialized) + self.assertNotIn('authType', serialized['properties']['syncProperties']) + client.begin_update.assert_called_once() + client.list.assert_not_called() + + if __name__ == '__main__': unittest.main() From 2929e7ea071a285ec2a2c1a133cf3cc973783c7f Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Wed, 16 Sep 2026 16:47:49 +1000 Subject: [PATCH 04/16] feat(acr): add managed identity connected registry settings Transfer GET-SETTINGS helpers, ManagedIdentity early return, and the shared SyncToken settings tail from the pinned original implementation. Source: https://github.com/Azure/azure-cli/pull/33910 Source-commit: e0b76941d9f5518bdd82529ef62eef89b43a3d45 Preserve source response guards, request-name selection, endpoint/protocol resolution, output keys, errors, and MI --generate-password rejection. Keep accepted CREATE, permissions, UPDATE, fixtures, and tests unchanged. Deviations/integration: - Add a handler-level too-many-locals pylint annotation (26 vs limit 25) rather than restructuring the original source. - Reuse existing test fixtures/imports; copy the four MI tests and helper, adding one exact-output/no-token-or-credential-call test and one six-case SyncToken regression test. Update the test module description/import. - Clarify optional SyncToken generation and MI rejection in get-settings help/argument help, plus the deprecated renew-credentials restriction. Preserve examples and all parameter defaults/requirements. The source connection-string format is not independently verified against inaccessible specification section 3.3. Request-name vs GET-response-name and endpoint contract questions remain separately reported, not fixed. Validation: 34 mock-only unit tests pass; six SyncToken cases also pass against the accepted pre-transfer handler. Scoped flake8/pylint, help and command/parameter lint, in-memory compilation, and source-fidelity checks pass. No live Azure or recording validation performed. --- .../azure/cli/command_modules/acr/_help.py | 4 +- .../azure/cli/command_modules/acr/_params.py | 2 +- .../command_modules/acr/connected_registry.py | 105 +++++++++--- .../test_acr_connected_registry_mi_unit.py | 154 +++++++++++++++++- 4 files changed, 236 insertions(+), 29 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/_help.py b/src/azure-cli/azure/cli/command_modules/acr/_help.py index 4f85ffe3953..4188d41dde7 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_help.py @@ -1733,7 +1733,8 @@ helps['acr connected-registry get-settings'] = """ type: command -short-summary: Retrieve information required to activate a connected registry, and creates or rotates the sync token credentials. +short-summary: Retrieve information required to activate a connected registry, optionally generating SyncToken credentials. +long-summary: ManagedIdentity settings do not require a sync token password and do not support --generate-password. examples: - name: Get the settings information required to install a connected registry without the password. text: > @@ -1790,6 +1791,7 @@ helps['acr connected-registry install renew-credentials'] = """ type: command short-summary: Retrieve information required to activate a connected registry, and renews the sync token credentials. +long-summary: Only supported for connected registries configured with SyncToken authentication. examples: - name: Set http as the parent protocol, and prints the values in json format required to activate a connected registry and the newly generated sync token credentials. text: > diff --git a/src/azure-cli/azure/cli/command_modules/acr/_params.py b/src/azure-cli/azure/cli/command_modules/acr/_params.py index f1fe726518f..14d1365938a 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_params.py @@ -570,7 +570,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements c.argument('sync_audit_logs_enabled', options_list=['--audit-logs-enabled'], help='Indicate whether audit log synchronization is enabled. It is enabled by default.', required=False, arg_type=get_three_state_flag(), deprecate_info=c.deprecate(hide=True)) c.argument('parent_protocol', arg_type=get_enum_type(['http', 'https']), options_list=['--parent-protocol'], help='Specify the protocol used to communicate with its parent.', required=True) - c.argument('generate_password', arg_type=get_enum_type(['1', '2']), options_list=['--generate-password'], help='Select which password you want to generate, and it is required to retrieve the password from the sync token.') + c.argument('generate_password', arg_type=get_enum_type(['1', '2']), options_list=['--generate-password'], help='Select which password you want to generate, and it is required to retrieve the password from the sync token. Not supported with ManagedIdentity authentication.') with self.argument_context('acr connected-registry create') as c: c.argument('log_level', help='Set the log level for logging on the instance. Accepted log levels are Debug, Information, Warning, Error, and None.', required=False, default="Information") diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index 3c391ce85fc..7acdb2a66f2 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -558,7 +558,44 @@ def acr_connected_registry_install_renew_credentials(cmd, '1', yes, resource_group_name) -def acr_connected_registry_get_settings(cmd, +def _resolve_parent_endpoint(connected_registry, parent_protocol): + parent_gateway_endpoint = connected_registry.parent.sync_properties.gateway_endpoint \ + or "" + if connected_registry.parent.id: + parent_endpoint_protocol = parent_protocol + else: + if parent_protocol != "https": + logger.warning("Parent endpoint protocol must be 'https' when parent is a cloud registry.") + parent_endpoint_protocol = "https" + return parent_gateway_endpoint, parent_endpoint_protocol + + +def _build_connected_registry_settings(connected_registry_name, + parent_gateway_endpoint, + parent_endpoint_protocol, + auth_connection_fragment, + auth_env): + connection_string = ( + "ConnectedRegistryName={};".format(connected_registry_name) + + auth_connection_fragment + + "ParentGatewayEndpoint={};".format(parent_gateway_endpoint) + + "ParentEndpointProtocol={}".format(parent_endpoint_protocol) + ) + login_server_placeholder = ( + "" + ) + settings = dict(auth_env) + settings.update({ + "ACR_REGISTRY_CERTIFICATE_VOLUME": "/var/acr/certs", + "ACR_REGISTRY_DATA_VOLUME": "/var/acr/data", + "ACR_REGISTRY_CONNECTION_STRING": connection_string, + "ACR_REGISTRY_LOGIN_SERVER": login_server_placeholder, + }) + return settings + + +def acr_connected_registry_get_settings(cmd, # pylint: disable=too-many-locals client, connected_registry_name, registry_name, @@ -571,6 +608,35 @@ def acr_connected_registry_get_settings(cmd, connected_registry = acr_connected_registry_show( cmd, client, connected_registry_name, registry_name, resource_group_name) + if _get_current_auth_type(connected_registry) == AUTH_TYPE_MANAGED_IDENTITY: + if generate_password: + raise ArgumentUsageError( + "argument error: --generate-password is not applicable for a connected registry " + "configured with ManagedIdentity authentication." + ) + identity = getattr(connected_registry, 'identity', None) + user_assigned = identity.user_assigned_identities if identity else None + if not user_assigned: + raise CLIError( + "Connected registry '{}' is in ManagedIdentity mode but no user-assigned identity is " + "attached.".format(connected_registry_name)) + # Spec §3.3: exactly one user-assigned identity is expected. + msi_resource_id, msi = next(iter(user_assigned.items())) + client_id = getattr(msi, 'client_id', None) + if not client_id: + raise CLIError( + "Client ID for user-assigned identity '{}' is not populated by the service yet.".format( + msi_resource_id)) + parent_gateway_endpoint, parent_endpoint_protocol = _resolve_parent_endpoint( + connected_registry, parent_protocol) + return _build_connected_registry_settings( + connected_registry_name, + parent_gateway_endpoint, + parent_endpoint_protocol, + auth_connection_fragment="ManagedIdentityClientId={};".format(client_id), + auth_env={}, + ) + sync_token_name = connected_registry.parent.sync_properties.token_id.split('/tokens/')[1] if generate_password: user_confirmation("Are you sure you want to generate a new sync token '{}' password{}?".format( @@ -599,31 +665,18 @@ def acr_connected_registry_get_settings(cmd, sync_username = sync_token_name sync_password = "" - parent_gateway_endpoint = connected_registry.parent.sync_properties.gateway_endpoint - if parent_gateway_endpoint is None or parent_gateway_endpoint == '': - parent_gateway_endpoint = "" - parent_id = connected_registry.parent.id - # if parent_id is not none, parent is a connected registry - if parent_id: - parent_endpoint_protocol = parent_protocol - # if parent_id is none, parent is a cloud registry - else: - if parent_protocol != "https": - logger.warning("Parent endpoint protocol must be 'https' when parent is a cloud registry.") - parent_endpoint_protocol = "https" - connected_registry_login_server = "" - connection_string = "ConnectedRegistryName=%s;" % connected_registry_name + \ - "SyncTokenName=%s;SyncTokenPassword=%s;" % (sync_username, sync_password) + \ - "ParentGatewayEndpoint=%s;ParentEndpointProtocol=%s" % (parent_gateway_endpoint, parent_endpoint_protocol) - return { - "SYNC_TOKEN_USER": sync_username, - "SYNC_TOKEN_PASSWORD": sync_password, - "ACR_REGISTRY_CERTIFICATE_VOLUME": "/var/acr/certs", - "ACR_REGISTRY_DATA_VOLUME": "/var/acr/data", - "ACR_REGISTRY_CONNECTION_STRING": connection_string, - "ACR_REGISTRY_LOGIN_SERVER": connected_registry_login_server - } + parent_gateway_endpoint, parent_endpoint_protocol = _resolve_parent_endpoint( + connected_registry, parent_protocol) + return _build_connected_registry_settings( + connected_registry_name, + parent_gateway_endpoint, + parent_endpoint_protocol, + auth_connection_fragment="SyncTokenName={};SyncTokenPassword={};".format(sync_username, sync_password), + auth_env={ + "SYNC_TOKEN_USER": sync_username, + "SYNC_TOKEN_PASSWORD": sync_password, + }, + ) # endregion diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py index 023d0258238..ba90819046e 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -"""Unit tests for managed-identity connected registry creation, permissions, and update.""" +"""Unit tests for managed-identity connected registry creation, permissions, update, and settings.""" import unittest from unittest import mock @@ -25,6 +25,7 @@ _build_user_assigned_identity, _get_current_auth_type, acr_connected_registry_create, + acr_connected_registry_get_settings, acr_connected_registry_permissions_show, acr_connected_registry_permissions_update, acr_connected_registry_update, @@ -511,5 +512,156 @@ def test_ordinary_update_preserves_auth_on_either_mode(self): client.list.assert_not_called() +# --------------------------------------------------------------------------- +# get-settings: MI-flavored connection string +# --------------------------------------------------------------------------- + + +class TestConnectedRegistryGetSettingsMI(unittest.TestCase): + + def _invoke(self, cr, **kw): + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', + return_value=(None, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.acr_connected_registry_show', + return_value=cr): + return acr_connected_registry_get_settings( + cmd=_make_cmd(), client=mock.MagicMock(), + connected_registry_name=TEST_CR, registry_name=TEST_REGISTRY, + parent_protocol='https', resource_group_name=TEST_RG, **kw) + + def test_generate_password_rejected_on_mi(self): + cr = _fake_cr(has_identity=True) + with self.assertRaises(ArgumentUsageError): + self._invoke(cr, generate_password='1', yes=True) + + def test_missing_user_assigned_errors(self): + cr = _fake_cr(has_identity=True) + cr.identity.user_assigned_identities = None + with self.assertRaises(CLIError): + self._invoke(cr) + + def test_missing_client_id_errors(self): + cr = _fake_cr(has_identity=True, client_id=None) + with self.assertRaises(CLIError): + self._invoke(cr) + + def test_happy_path_returns_mi_connection_string(self): + cr = _fake_cr(has_identity=True, client_id='cid-happy') + result = self._invoke(cr) + self.assertIn('ManagedIdentityClientId=cid-happy', + result['ACR_REGISTRY_CONNECTION_STRING']) + self.assertNotIn('SyncTokenName', result['ACR_REGISTRY_CONNECTION_STRING']) + self.assertNotIn('SYNC_TOKEN_USER', result) + self.assertNotIn('SYNC_TOKEN_PASSWORD', result) + self.assertNotIn('ACR_MANAGED_IDENTITY_CLIENT_ID', result) + self.assertNotIn('ACR_MANAGED_IDENTITY_RESOURCE_ID', result) + + def test_source_settings_use_get_without_token_or_credential_calls(self): + cr = _fake_cr(has_identity=True, client_id='cid-happy') + cr.name = 'name-returned-by-get' + client = mock.MagicMock() + client.get.return_value = cr + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', return_value=(None, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.get_token_from_id') as token_lookup, \ + mock.patch(UPDATE_MODULE + '.cf_acr_tokens') as token_factory, \ + mock.patch('azure.cli.command_modules.acr._client_factory.cf_acr_token_credentials') as cred_factory, \ + mock.patch('azure.cli.command_modules.acr.token.acr_token_credential_generate') as generate, \ + mock.patch(UPDATE_MODULE + '.user_confirmation') as confirm: + result = acr_connected_registry_get_settings( + cmd=_make_cmd(), client=client, + connected_registry_name=TEST_CR, registry_name=TEST_REGISTRY, + parent_protocol='http', resource_group_name=TEST_RG) + client.get.assert_called_once_with(TEST_RG, TEST_REGISTRY, TEST_CR) + self.assertEqual(client.method_calls, [mock.call.get(TEST_RG, TEST_REGISTRY, TEST_CR)]) + token_lookup.assert_not_called() + token_factory.assert_not_called() + cred_factory.assert_not_called() + generate.assert_not_called() + confirm.assert_not_called() + # Preserve the pinned source format (including its request name), not a verified spec contract. + self.assertEqual(result, { + 'ACR_REGISTRY_CERTIFICATE_VOLUME': '/var/acr/certs', + 'ACR_REGISTRY_DATA_VOLUME': '/var/acr/data', + 'ACR_REGISTRY_CONNECTION_STRING': ( + 'ConnectedRegistryName={};ManagedIdentityClientId=cid-happy;' + 'ParentGatewayEndpoint=parent.example.com;ParentEndpointProtocol=https'.format(TEST_CR)), + 'ACR_REGISTRY_LOGIN_SERVER': ( + ''), + }) + + +class TestConnectedRegistryGetSettingsSyncToken(unittest.TestCase): + + def test_legacy_settings_passwords_endpoints_and_protocols(self): + token_id = ( + '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ContainerRegistry/' + 'registries/{}/tokens/sync'.format(TEST_SUB, TEST_RG, TEST_REGISTRY)) + parent_id = '/connectedRegistries/parent' + for auth_type, parent, gateway, protocol, password, expected_protocol in ( + (None, None, 'parent.example.com', 'http', None, 'https'), + (AUTH_TYPE_SYNC_TOKEN, None, None, 'https', None, 'https'), + (AUTH_TYPE_SYNC_TOKEN, parent_id, '', 'http', None, 'http'), + (AUTH_TYPE_SYNC_TOKEN, parent_id, 'parent.example.com', 'https', None, 'https'), + (AUTH_TYPE_SYNC_TOKEN, None, 'parent.example.com', 'http', '1', 'https'), + (AUTH_TYPE_SYNC_TOKEN, parent_id, 'parent.example.com', 'http', '2', 'http')): + with self.subTest(auth_type=auth_type, parent=parent, gateway=gateway, + protocol=protocol, password=password): + cr = _fake_cr(auth_type=auth_type, token_id=token_id, gateway_endpoint=gateway) + cr.parent.id = parent + cmd = _make_cmd() + credentials = mock.MagicMock() + credentials.username = 'generated-sync' + credentials.passwords = [ + mock.Mock(value='test-only-password-1'), + mock.Mock(value='test-only-password-2'), + ] + credentials.passwords[0].name = 'password1' + credentials.passwords[1].name = 'password2' + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', return_value=(None, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.acr_connected_registry_show', return_value=cr), \ + mock.patch(UPDATE_MODULE + '.user_confirmation') as confirm, \ + mock.patch('azure.cli.command_modules.acr._client_factory.cf_acr_token_credentials') as factory, \ + mock.patch('azure.cli.command_modules.acr.token.acr_token_credential_generate') as generate, \ + mock.patch(UPDATE_MODULE + '.LongRunningOperation') as lro: + lro.return_value.return_value = credentials + result = acr_connected_registry_get_settings( + cmd=cmd, client=mock.MagicMock(), + connected_registry_name=TEST_CR, registry_name=TEST_REGISTRY, + parent_protocol=protocol, generate_password=password, yes=True, + resource_group_name=TEST_RG) + username = credentials.username if password else 'sync' + expected_password = ('test-only-password-' + password if password else + '') + self.assertEqual(result, { + 'SYNC_TOKEN_USER': username, + 'SYNC_TOKEN_PASSWORD': expected_password, + 'ACR_REGISTRY_CERTIFICATE_VOLUME': '/var/acr/certs', + 'ACR_REGISTRY_DATA_VOLUME': '/var/acr/data', + 'ACR_REGISTRY_CONNECTION_STRING': ( + 'ConnectedRegistryName={};SyncTokenName={};SyncTokenPassword={};' + 'ParentGatewayEndpoint={};ParentEndpointProtocol={}'.format( + TEST_CR, username, expected_password, + gateway or '', expected_protocol)), + 'ACR_REGISTRY_LOGIN_SERVER': ( + ''), + }) + if password: + confirm.assert_called_once_with( + "Are you sure you want to generate a new sync token 'sync' password{}?".format(password), True) + factory.assert_called_once_with(cmd.cli_ctx) + generate.assert_called_once_with( + cmd, factory.return_value, TEST_REGISTRY, 'sync', + password1=password == '1', password2=password == '2', resource_group_name=TEST_RG) + lro.assert_called_once_with(cmd.cli_ctx) + lro.return_value.assert_called_once_with(generate.return_value) + else: + confirm.assert_not_called() + factory.assert_not_called() + generate.assert_not_called() + lro.assert_not_called() + + if __name__ == '__main__': unittest.main() From f9facc8d79407a280b56a5624a3b722c0687e494 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Fri, 18 Sep 2026 18:58:25 +1000 Subject: [PATCH 05/16] fix --- .../azure/cli/command_modules/acr/connected_registry.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index 7acdb2a66f2..a26f55f867b 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -620,7 +620,8 @@ def acr_connected_registry_get_settings(cmd, # pylint: disable=too-many-locals raise CLIError( "Connected registry '{}' is in ManagedIdentity mode but no user-assigned identity is " "attached.".format(connected_registry_name)) - # Spec §3.3: exactly one user-assigned identity is expected. + + # exactly one user-assigned identity is expected. msi_resource_id, msi = next(iter(user_assigned.items())) client_id = getattr(msi, 'client_id', None) if not client_id: From 112635b1f477226a33b55ef6ea8a1ecc0c01e157 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Mon, 21 Sep 2026 14:24:11 +1000 Subject: [PATCH 06/16] fix(acr): handle managed identity connected registry deletion --- .../azure/cli/command_modules/acr/_params.py | 2 +- .../command_modules/acr/connected_registry.py | 2 + .../test_acr_connected_registry_mi_unit.py | 127 +++++++++++++++++- 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/_params.py b/src/azure-cli/azure/cli/command_modules/acr/_params.py index 14d1365938a..439965e0871 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_params.py @@ -565,7 +565,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements c.argument('parent_name', options_list=['--parent', '-p'], help='The name of the parent connected registry.') c.argument('repositories', options_list=['--repository'], nargs='+', help='Specify the repositories that need to be sync to the connected registry. It can be in the format [REPO01] [REPO02]...') c.argument('sync_token_name', options_list=['--sync-token'], help='Specifies the sync token used to synchronize the connected registry with its parent. It most have only repo permissions and at least the actions required for its mode. It can include access for multiple repositories.') - c.argument('cleanup', help='It will aslo delete the sync token and the scope map resources.') + c.argument('cleanup', help='Delete the sync token and scope map resources for SyncToken authentication. No effect for ManagedIdentity authentication; the managed identity and role assignments are not deleted.') c.argument('no_children', help='Used to remove all children from the list.', action='store_true') c.argument('sync_audit_logs_enabled', options_list=['--audit-logs-enabled'], help='Indicate whether audit log synchronization is enabled. It is enabled by default.', required=False, arg_type=get_three_state_flag(), deprecate_info=c.deprecate(hide=True)) diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index a26f55f867b..e5aa629f1cf 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -360,6 +360,8 @@ def acr_connected_registry_delete(cmd, connected_registry = acr_connected_registry_show( cmd, client, connected_registry_name, registry_name, resource_group_name) result = client.begin_delete(resource_group_name, registry_name, connected_registry_name).result() + if _get_current_auth_type(connected_registry) == AUTH_TYPE_MANAGED_IDENTITY: + return result sync_token = get_token_from_id(cmd, connected_registry.parent.sync_properties.token_id) sync_token_name = sync_token.name sync_scope_map_name = sync_token.scope_map_id.split('/scopeMaps/')[1] diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py index ba90819046e..3e689ad2cf6 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -"""Unit tests for managed-identity connected registry creation, permissions, update, and settings.""" +"""Unit tests for managed-identity connected registry creation, deletion, permissions, update, and settings.""" import unittest from unittest import mock @@ -25,6 +25,7 @@ _build_user_assigned_identity, _get_current_auth_type, acr_connected_registry_create, + acr_connected_registry_delete, acr_connected_registry_get_settings, acr_connected_registry_permissions_show, acr_connected_registry_permissions_update, @@ -320,6 +321,130 @@ def test_root_auth_payload_and_token_paths(self): UPDATE_MODULE = 'azure.cli.command_modules.acr.connected_registry' +class TestConnectedRegistryDelete(unittest.TestCase): + + def test_mi_delete_skips_token_cleanup(self): + token_id = ( + '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ContainerRegistry/' + 'registries/{}/tokens/old-sync'.format(TEST_SUB, TEST_RG, TEST_REGISTRY)) + for cleanup in (False, True): + for auth_type in (AUTH_TYPE_MANAGED_IDENTITY, models.AuthType.MANAGED_IDENTITY): + for previous_token in (None, token_id): + with self.subTest(cleanup=cleanup, auth_type=auth_type, token_id=previous_token): + cr = _fake_cr(auth_type=auth_type, has_identity=True, token_id=previous_token) + cmd = _make_cmd() + client = mock.MagicMock() + client.get.return_value = cr + client.begin_delete.return_value.result.return_value = mock.sentinel.deleted + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', + return_value=(None, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.user_confirmation') as confirm, \ + mock.patch(UPDATE_MODULE + '.get_token_from_id') as token_lookup, \ + mock.patch(UPDATE_MODULE + '.get_scope_map_from_id') as scope_lookup, \ + mock.patch(UPDATE_MODULE + '.cf_acr_tokens') as tokens, \ + mock.patch(UPDATE_MODULE + '.cf_acr_scope_maps') as scope_maps, \ + mock.patch('azure.cli.command_modules.acr.token.acr_token_delete') as delete_token, \ + mock.patch('azure.cli.command_modules.acr.scope_map.acr_scope_map_delete') as delete_scope, \ + mock.patch(UPDATE_MODULE + '._get_family_tree') as family_tree, \ + mock.patch(UPDATE_MODULE + '._update_ancestor_permissions') as update_permissions, \ + mock.patch(UPDATE_MODULE + '.logger.warning') as warning: + result = acr_connected_registry_delete( + cmd, client, TEST_CR, TEST_REGISTRY, cleanup=cleanup, resource_group_name=TEST_RG) + self.assertIs(result, mock.sentinel.deleted) + client.get.assert_called_once_with(TEST_RG, TEST_REGISTRY, TEST_CR) + client.begin_delete.assert_called_once_with(TEST_RG, TEST_REGISTRY, TEST_CR) + client.begin_delete.return_value.result.assert_called_once_with() + self.assertEqual(client.mock_calls, [ + mock.call.get(TEST_RG, TEST_REGISTRY, TEST_CR), + mock.call.begin_delete(TEST_RG, TEST_REGISTRY, TEST_CR), + mock.call.begin_delete().result(), + ]) + confirm.assert_called_once_with( + "Are you sure you want to delete the connected registry '{}' in '{}'{}?".format( + TEST_CR, TEST_REGISTRY, '' if cleanup else ' without cleanup flag enabled'), False) + token_lookup.assert_not_called() + scope_lookup.assert_not_called() + tokens.assert_not_called() + scope_maps.assert_not_called() + delete_token.assert_not_called() + delete_scope.assert_not_called() + family_tree.assert_not_called() + update_permissions.assert_not_called() + warning.assert_not_called() + + def test_sync_token_delete_preserves_cleanup_and_warning(self): + token_id = ( + '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ContainerRegistry/' + 'registries/{}/tokens/sync'.format(TEST_SUB, TEST_RG, TEST_REGISTRY)) + for cleanup in (False, True): + for auth_type in (AUTH_TYPE_SYNC_TOKEN, models.AuthType.SYNC_TOKEN, None): + with self.subTest(cleanup=cleanup, auth_type=auth_type): + cr = _fake_cr(auth_type=auth_type, token_id=token_id) + cr.parent.id = '/connectedRegistries/parent' + cmd = _make_cmd() + client = mock.MagicMock() + client.get.return_value = cr + client.begin_delete.return_value.result.return_value = mock.sentinel.deleted + client.list.return_value = [mock.sentinel.parent] + token = mock.MagicMock() + token.name = 'sync' + token.scope_map_id = token_id.replace('/tokens/sync', '/scopeMaps/sync-scope') + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', + return_value=(None, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.user_confirmation') as confirm, \ + mock.patch(UPDATE_MODULE + '.get_token_from_id', return_value=token) as token_lookup, \ + mock.patch(UPDATE_MODULE + '.cf_acr_tokens') as tokens, \ + mock.patch(UPDATE_MODULE + '.cf_acr_scope_maps') as scope_maps, \ + mock.patch('azure.cli.command_modules.acr.token.acr_token_delete') as delete_token, \ + mock.patch('azure.cli.command_modules.acr.scope_map.acr_scope_map_delete') as delete_scope, \ + mock.patch(UPDATE_MODULE + '._get_family_tree', + return_value=(mock.sentinel.family_tree, None)) as family_tree, \ + mock.patch(UPDATE_MODULE + '._update_ancestor_permissions') as update_permissions, \ + mock.patch(UPDATE_MODULE + '.logger.warning') as warning: + result = acr_connected_registry_delete( + cmd, client, TEST_CR, TEST_REGISTRY, cleanup=cleanup, yes=True, resource_group_name=TEST_RG) + self.assertIs(result, mock.sentinel.deleted) + client.get.assert_called_once_with(TEST_RG, TEST_REGISTRY, TEST_CR) + client.begin_delete.assert_called_once_with(TEST_RG, TEST_REGISTRY, TEST_CR) + client.begin_delete.return_value.result.assert_called_once_with() + confirm.assert_called_once_with( + "Are you sure you want to delete the connected registry '{}' in '{}'{}?".format( + TEST_CR, TEST_REGISTRY, '' if cleanup else ' without cleanup flag enabled'), True) + token_lookup.assert_called_once_with(cmd, token_id) + if cleanup: + tokens.assert_called_once_with(cmd.cli_ctx) + scope_maps.assert_called_once_with(cmd.cli_ctx) + delete_token.assert_called_once_with( + cmd, tokens.return_value, TEST_REGISTRY, 'sync', True, TEST_RG) + delete_token.return_value.result.assert_called_once_with() + delete_scope.assert_called_once_with( + cmd, scope_maps.return_value, TEST_REGISTRY, 'sync-scope', True, TEST_RG) + delete_scope.return_value.result.assert_called_once_with() + client.list.assert_called_once_with(TEST_RG, TEST_REGISTRY) + family_tree.assert_called_once_with([mock.sentinel.parent], None) + update_permissions.assert_called_once_with( + cmd, mock.sentinel.family_tree, TEST_RG, TEST_REGISTRY, + cr.parent.id, TEST_CR, remove_access=True) + warning.assert_not_called() + else: + tokens.assert_not_called() + scope_maps.assert_not_called() + delete_token.assert_not_called() + delete_scope.assert_not_called() + client.list.assert_not_called() + family_tree.assert_not_called() + update_permissions.assert_not_called() + warning.assert_called_once_with( + "Connected registry successfully deleted. Please cleanup your sync tokens and scope maps. " + "Run the following commands for cleanup: \n\t" + "az acr token delete -n sync -r {registry} --yes\n\t" + "az acr scope-map delete -n sync-scope -r {registry} --yes\n" + "Run the following command on all ascendency to remove the deleted registry gateway access: " + "\n\taz acr scope-map update -n -r {registry} --remove-gateway " + "{connected_registry} config/read config/write message/read message/write".format( + registry=TEST_REGISTRY, connected_registry=TEST_CR)) + + # --------------------------------------------------------------------------- # permissions show / update: blocked on MI # --------------------------------------------------------------------------- From 6ba0c894171107f5c51fdf895e53bb23df184ef0 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Mon, 21 Sep 2026 14:30:28 +1000 Subject: [PATCH 07/16] tests(acr): record connected registry mi create + show + get-settings + delete --- ...cr_connectedregistry_managed_identity.yaml | 1028 +++++++++++++++++ .../test_acr_connectedregistry_commands.py | 67 ++ 2 files changed, 1095 insertions(+) create mode 100644 src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity.yaml diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity.yaml b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity.yaml new file mode 100644 index 00000000000..c99a83dd953 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity.yaml @@ -0,0 +1,1028 @@ +interactions: +- request: + body: '{"location": "eastus", "sku": {"name": "Premium"}, "properties": {"adminUserEnabled": + false, "roleAssignmentMode": "AbacRepositoryPermissions"}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr create + Connection: + - keep-alive + Content-Length: + - '144' + Content-Type: + - application/json + ParameterSetName: + - -n -g -l --sku --role-assignment-mode + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:22.6256643+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":false,"regionalEndpoints":"Disabled","dataEndpointHostNames":[],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1722' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:29 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/5c10bb92-7260-41ae-b356-7be602802f2f + x-ms-ratelimit-remaining-subscription-global-writes: + - '12000' + x-ms-ratelimit-remaining-subscription-writes: + - '800' + x-msedge-ref: + - 'Ref A: 87F98FDB20ED408C94A2121F24B75187 Ref B: SYD281080712062 Ref C: 2026-09-21T04:14:21Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr update + Connection: + - keep-alive + ParameterSetName: + - -n -g --data-endpoint-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:22.6256643+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":false,"regionalEndpoints":"Disabled","dataEndpointHostNames":[],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1722' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:31 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: A7426E28EC6249FCABF7A14E59B04334 Ref B: SYD281080711060 Ref C: 2026-09-21T04:14:31Z' + status: + code: 200 + message: OK +- request: + body: '{"properties": {"dataEndpointEnabled": true}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr update + Connection: + - keep-alive + Content-Length: + - '45' + Content-Type: + - application/json + ParameterSetName: + - -n -g --data-endpoint-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PATCH + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:32 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/westus/460e6290-5986-475a-ade5-334e498b661a + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: CD2FCDFAD327465BAFE82C0FB980197F Ref B: SYD281080706054 Ref C: 2026-09-21T04:14:32Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - identity create + Connection: + - keep-alive + ParameterSetName: + - --name -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001","name":"clitest.rg000001","type":"Microsoft.Resources/resourceGroups","location":"westus","tags":{"product":"azurecli","cause":"automation","test":"test_acr_connectedregistry_managed_identity","date":"2026-09-21T04:14:16Z","module":"acr"},"properties":{"provisioningState":"Succeeded"}}' + headers: + cache-control: + - no-cache + content-length: + - '378' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:33 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 048DF40B5CCD4612B39D2BEB3463A0D1 Ref B: SYD281080711062 Ref C: 2026-09-21T04:14:33Z' + status: + code: 200 + message: OK +- request: + body: '{"location": "westus"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - identity create + Connection: + - keep-alive + Content-Length: + - '22' + Content-Type: + - application/json + ParameterSetName: + - --name -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003?api-version=2025-05-31-preview + response: + body: + string: '{"location":"westus","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003","name":"cr-mi-id000003","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"isolationScope":"None","assignmentRestrictions":{"providers":[]},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","principalId":"0509fc30-f152-4292-8373-384dcd592828","clientId":"8106ddd1-7697-4a47-9f7f-d66c63d603c6"}}' + headers: + cache-control: + - no-cache + content-length: + - '512' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:37 GMT + expires: + - '-1' + location: + - /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003 + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/26e286d0-2119-40a3-b6ea-8ec0b498187d + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: 0E9DE3EF4F67415A9EE325A864F295B8 Ref B: SYD281080708025 Ref C: 2026-09-21T04:14:34Z' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + ParameterSetName: + - -n -r -g -m --auth-type --identity + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:38 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 6854B644B3E64C0CA97E641FEC52901A Ref B: SYD281080707025 Ref C: 2026-09-21T04:14:38Z' + status: + code: 200 + message: OK +- request: + body: '{"identity": {"type": "UserAssigned", "userAssignedIdentities": {"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003": + {}}}, "properties": {"garbageCollection": {"enabled": "true", "schedule": "0 + 0 * * *"}, "mode": "readonly", "parent": {"syncProperties": {"schedule": "* + * * * *", "messageTtl": "P2D", "authType": "ManagedIdentity"}}, "logging": {"logLevel": + "Information", "auditLogStatus": "Disabled"}}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + Content-Length: + - '513' + Content-Type: + - application/json + ParameterSetName: + - -n -r -g -m --auth-type --identity + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"0509fc30-f152-4292-8373-384dcd592828","clientId":"8106ddd1-7697-4a47-9f7f-d66c63d603c6"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen","name":"crmiscen","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:40.3062901+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:40.3062901+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"* + * * * *","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Information","auditLogStatus":"Disabled"},"garbageCollection":{"enabled":true,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1281' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:41 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/westus/da28f5de-40ff-4637-bef6-871d4603a53b + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: FF7B35CD1C20470C92D0F48675762BBE Ref B: SYD281080705062 Ref C: 2026-09-21T04:14:40Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry show + Connection: + - keep-alive + ParameterSetName: + - -n -r -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:41 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: B75C589C1A004E0C99DAD44790EB2747 Ref B: SYD281080708052 Ref C: 2026-09-21T04:14:41Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry show + Connection: + - keep-alive + ParameterSetName: + - -n -r -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"0509fc30-f152-4292-8373-384dcd592828","clientId":"8106ddd1-7697-4a47-9f7f-d66c63d603c6"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen","name":"crmiscen","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:40.3062901+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:40.3062901+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"* + * * * *","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Information","auditLogStatus":"Disabled"},"garbageCollection":{"enabled":true,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1281' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:42 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/3dd1376c-95e2-40cd-be9a-80563257692f + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 418A6970DDC049469D284F95EBF38833 Ref B: SYD281080711023 Ref C: 2026-09-21T04:14:42Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry get-settings + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --parent-protocol + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: AEA3137A142B425480285A240A2DAC00 Ref B: SYD281080705034 Ref C: 2026-09-21T04:14:43Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry get-settings + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --parent-protocol + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: F90DC6DF065F42A0B9882AA7B52000B4 Ref B: SYD281080708060 Ref C: 2026-09-21T04:14:44Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry get-settings + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --parent-protocol + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"0509fc30-f152-4292-8373-384dcd592828","clientId":"8106ddd1-7697-4a47-9f7f-d66c63d603c6"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen","name":"crmiscen","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:40.3062901+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:40.3062901+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"* + * * * *","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Information","auditLogStatus":"Disabled"},"garbageCollection":{"enabled":true,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1281' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/westus/b701581e-392a-4d28-a084-ff362698c121 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 966757DC54E1405B88EED49D10A4A25B Ref B: SYD281080711031 Ref C: 2026-09-21T04:14:45Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + ParameterSetName: + - -n -r -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:46 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 0C16240A62A54EB490A3B1A84EC266D1 Ref B: SYD281080709040 Ref C: 2026-09-21T04:14:46Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + ParameterSetName: + - -n -r -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:47 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: CBFA27AC49AD441D91C67250F02BF598 Ref B: SYD281080707029 Ref C: 2026-09-21T04:14:47Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + ParameterSetName: + - -n -r -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"0509fc30-f152-4292-8373-384dcd592828","clientId":"8106ddd1-7697-4a47-9f7f-d66c63d603c6"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen","name":"crmiscen","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:40.3062901+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:40.3062901+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"* + * * * *","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Information","auditLogStatus":"Disabled"},"garbageCollection":{"enabled":true,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1281' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:47 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/westus/95e8caa6-d44b-49de-8cf0-b873308969b2 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 39036F8360BB4D04ACE5B5B286EC4530 Ref B: SYD281080709060 Ref C: 2026-09-21T04:14:48Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -n -r -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmiscen?api-version=2026-09-01-preview + response: + body: + string: '' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:14:48 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/westus/eb200d07-acf4-4f6d-8222-9779354d936e + x-ms-ratelimit-remaining-subscription-deletes: + - '799' + x-ms-ratelimit-remaining-subscription-global-deletes: + - '11999' + x-msedge-ref: + - 'Ref A: AA2DEBBF0BCF4CFFB2851E215FE7E7AD Ref B: SYD281080705062 Ref C: 2026-09-21T04:14:48Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -n -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:14:22.6256643+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:14:32.6858052+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:14:22.6256643Z","provisioningState":"Deleting","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:14:29.9778722+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:14:29.9779109+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1757' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:14:49 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-fc616d77-b572-11f1-bdd4-3cefa50a58cc?api-version=2026-09-01-preview&t=639255608899252598&c=MIIHwzCCBqugAwIBAgIQO9vjerLJyzCAZGOG8qnuujANBgkqhkiG9w0BAQsFADA1MTMwMQYDVQQDEypDQ01FIEcxIFRMUyBSU0EgMjA0OCBTSEEyNTYgMjA0OSBDVVMgQ0EgMDEwHhcNMjYwOTE3MTkyNzU0WhcNMjYxMjEzMDEyNzU0WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOH7XcOFB9oBlttbwx8AirjT-trX0XvGg-qTsZnfCNKSBKRmEGUNPWfYKFgDpx0AZwfOinDzB58zssD8uZb2jeDqfJuiR1vqsOBWntnOkwx0IgWzw_pbET-L7lO_ZYW2-ec3c5ZewHiy0Jr51TL2zNtCadpjfB2g2RkKJY_5Zgyqgccwx0LvPgj81bdByhSFWtd49llL8NuFYWjo3Fk7HmsitrM-T8Z3xgac37X6nC2PTsQFiO6h917Etzgh-KBeYYfZiOTF9hHnetiX5px_9XecvBma56vHFyzqoF4VpkESo5tWkT_beymCu5gy2ngynn3SNDYyVgZXGrEn4V_OKM0CAwEAAaOCBMIwggS-MIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwIwDAYKKwYBBAGCN3sEAjAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYEFLXKU9erjRhgRqjwHfGKduIH8QgZMB8GA1UdIwQYMBaAFPzkWgovhQ7nRLkHc3jg1EQHohkRMIIBygYDVR0fBIIBwTCCAb0wb6BtoGuGaWh0dHA6Ly9wcmltYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZW50cmFsdXMvY3Jscy9jY21lY2VudHJhbHVzcGtpL2NjbWVjZW50cmFsdXNpY2EwMS84MS9jdXJyZW50LmNybDBxoG-gbYZraHR0cDovL3NlY29uZGFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvY2VudHJhbHVzL2NybHMvY2NtZWNlbnRyYWx1c3BraS9jY21lY2VudHJhbHVzaWNhMDEvODEvY3VycmVudC5jcmwwYKBeoFyGWmh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9jZW50cmFsdXMvY3Jscy9jY21lY2VudHJhbHVzcGtpL2NjbWVjZW50cmFsdXNpY2EwMS84MS9jdXJyZW50LmNybDB1oHOgcYZvaHR0cDovL2NjbWVjZW50cmFsdXNwa2kuY2VudHJhbHVzLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZWNlbnRyYWx1c2ljYTAxLzgxL2N1cnJlbnQuY3JsMIIBzwYIKwYBBQUHAQEEggHBMIIBvTByBggrBgEFBQcwAoZmaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2NlbnRyYWx1cy9jYWNlcnRzL2NjbWVjZW50cmFsdXNwa2kvY2NtZWNlbnRyYWx1c2ljYTAxL2NlcnQuY2VyMHQGCCsGAQUFBzAChmhodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZW50cmFsdXMvY2FjZXJ0cy9jY21lY2VudHJhbHVzcGtpL2NjbWVjZW50cmFsdXNpY2EwMS9jZXJ0LmNlcjBjBggrBgEFBQcwAoZXaHR0cDovL2NybC5taWNyb3NvZnQuY29tL2NlbnRyYWx1cy9jYWNlcnRzL2NjbWVjZW50cmFsdXNwa2kvY2NtZWNlbnRyYWx1c2ljYTAxL2NlcnQuY2VyMGwGCCsGAQUFBzAChmBodHRwOi8vY2NtZWNlbnRyYWx1c3BraS5jZW50cmFsdXMucGtpLmNvcmUud2luZG93cy5uZXQvY2VydGlmaWNhdGVBdXRob3JpdGllcy9jY21lY2VudHJhbHVzaWNhMDEwDQYJKoZIhvcNAQELBQADggEBAEdUznjVdYbUtxHD93flzOpv9itmdLU-P-i-amvvUBn1ESE_kJadN1MNgEM7wepiASPBur_kdjFJFZ5QdmL9EfoQmFlXLFS-v1qgMBh2uK-7Kx5nCPVe7MfrPZyaDtWWZoKQ1ku_7opeRh0t5mG0O3vQdmu-gxm9jX2bOhHTHW_uA9yYnskYrIv0kyqah1mv5zf85_XKMRSd592hVfIL4O9kUoKFjYKYWROv0MDSHRzOr2h9LjtoXGtDVpaGhgXaw6SQLRfR9piqIFxVYxpsgwP30Cdlvv9Vz-bZEpoPLRZc4_cpvPp6ZaWJSQgQNnoHo1QDfwAPoEEjmUxvRB06lrI&s=2UFdjQhrw7dbU_YbAPIlakEUWMpmD3ffH92PGMWi4HxnSRkWA_LE4AcQAL8RC1O9NwrkbHKz59s9ySWNf51cyproqW40Nuf38s3o_xOlFzE_qBl_iUxqkLGc3VigaujpaYiA-JJDWVrQZDKIieVBEYxkMjzLMnRfunVCn8ysfcFpfD9-A3vTWcYcWxg3ilgyVDrl0knPhesmTw0cEbnSvieMnb41W7oLsQIP7RB_uEqHj587nZbNeeI9FWI_RQBhEsuVbgP5fXMUbxm6TC1taFY2PRLASVJ6rAi2JsIdNYG22twYwVd0WxubEsFM0T06TzQmQn6kC9B63WoEVJAeWg&h=ioqda8ion8RijFe0JMrfWVlfO4fl_M4D-atK4t6SyIM + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/westus/f1a2ac6d-09a5-482f-8c15-869986b81fa1 + x-ms-ratelimit-remaining-subscription-deletes: + - '799' + x-ms-ratelimit-remaining-subscription-global-deletes: + - '11999' + x-msedge-ref: + - 'Ref A: 2F725A8717F54D2295B41C5D62980919 Ref B: SYD281080707052 Ref C: 2026-09-21T04:14:49Z' + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr delete + Connection: + - keep-alive + ParameterSetName: + - -n -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-fc616d77-b572-11f1-bdd4-3cefa50a58cc?api-version=2026-09-01-preview&t=639255608899252598&c=MIIHwzCCBqugAwIBAgIQO9vjerLJyzCAZGOG8qnuujANBgkqhkiG9w0BAQsFADA1MTMwMQYDVQQDEypDQ01FIEcxIFRMUyBSU0EgMjA0OCBTSEEyNTYgMjA0OSBDVVMgQ0EgMDEwHhcNMjYwOTE3MTkyNzU0WhcNMjYxMjEzMDEyNzU0WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOH7XcOFB9oBlttbwx8AirjT-trX0XvGg-qTsZnfCNKSBKRmEGUNPWfYKFgDpx0AZwfOinDzB58zssD8uZb2jeDqfJuiR1vqsOBWntnOkwx0IgWzw_pbET-L7lO_ZYW2-ec3c5ZewHiy0Jr51TL2zNtCadpjfB2g2RkKJY_5Zgyqgccwx0LvPgj81bdByhSFWtd49llL8NuFYWjo3Fk7HmsitrM-T8Z3xgac37X6nC2PTsQFiO6h917Etzgh-KBeYYfZiOTF9hHnetiX5px_9XecvBma56vHFyzqoF4VpkESo5tWkT_beymCu5gy2ngynn3SNDYyVgZXGrEn4V_OKM0CAwEAAaOCBMIwggS-MIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwIwDAYKKwYBBAGCN3sEAjAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYEFLXKU9erjRhgRqjwHfGKduIH8QgZMB8GA1UdIwQYMBaAFPzkWgovhQ7nRLkHc3jg1EQHohkRMIIBygYDVR0fBIIBwTCCAb0wb6BtoGuGaWh0dHA6Ly9wcmltYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZW50cmFsdXMvY3Jscy9jY21lY2VudHJhbHVzcGtpL2NjbWVjZW50cmFsdXNpY2EwMS84MS9jdXJyZW50LmNybDBxoG-gbYZraHR0cDovL3NlY29uZGFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvY2VudHJhbHVzL2NybHMvY2NtZWNlbnRyYWx1c3BraS9jY21lY2VudHJhbHVzaWNhMDEvODEvY3VycmVudC5jcmwwYKBeoFyGWmh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9jZW50cmFsdXMvY3Jscy9jY21lY2VudHJhbHVzcGtpL2NjbWVjZW50cmFsdXNpY2EwMS84MS9jdXJyZW50LmNybDB1oHOgcYZvaHR0cDovL2NjbWVjZW50cmFsdXNwa2kuY2VudHJhbHVzLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZWNlbnRyYWx1c2ljYTAxLzgxL2N1cnJlbnQuY3JsMIIBzwYIKwYBBQUHAQEEggHBMIIBvTByBggrBgEFBQcwAoZmaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2NlbnRyYWx1cy9jYWNlcnRzL2NjbWVjZW50cmFsdXNwa2kvY2NtZWNlbnRyYWx1c2ljYTAxL2NlcnQuY2VyMHQGCCsGAQUFBzAChmhodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZW50cmFsdXMvY2FjZXJ0cy9jY21lY2VudHJhbHVzcGtpL2NjbWVjZW50cmFsdXNpY2EwMS9jZXJ0LmNlcjBjBggrBgEFBQcwAoZXaHR0cDovL2NybC5taWNyb3NvZnQuY29tL2NlbnRyYWx1cy9jYWNlcnRzL2NjbWVjZW50cmFsdXNwa2kvY2NtZWNlbnRyYWx1c2ljYTAxL2NlcnQuY2VyMGwGCCsGAQUFBzAChmBodHRwOi8vY2NtZWNlbnRyYWx1c3BraS5jZW50cmFsdXMucGtpLmNvcmUud2luZG93cy5uZXQvY2VydGlmaWNhdGVBdXRob3JpdGllcy9jY21lY2VudHJhbHVzaWNhMDEwDQYJKoZIhvcNAQELBQADggEBAEdUznjVdYbUtxHD93flzOpv9itmdLU-P-i-amvvUBn1ESE_kJadN1MNgEM7wepiASPBur_kdjFJFZ5QdmL9EfoQmFlXLFS-v1qgMBh2uK-7Kx5nCPVe7MfrPZyaDtWWZoKQ1ku_7opeRh0t5mG0O3vQdmu-gxm9jX2bOhHTHW_uA9yYnskYrIv0kyqah1mv5zf85_XKMRSd592hVfIL4O9kUoKFjYKYWROv0MDSHRzOr2h9LjtoXGtDVpaGhgXaw6SQLRfR9piqIFxVYxpsgwP30Cdlvv9Vz-bZEpoPLRZc4_cpvPp6ZaWJSQgQNnoHo1QDfwAPoEEjmUxvRB06lrI&s=2UFdjQhrw7dbU_YbAPIlakEUWMpmD3ffH92PGMWi4HxnSRkWA_LE4AcQAL8RC1O9NwrkbHKz59s9ySWNf51cyproqW40Nuf38s3o_xOlFzE_qBl_iUxqkLGc3VigaujpaYiA-JJDWVrQZDKIieVBEYxkMjzLMnRfunVCn8ysfcFpfD9-A3vTWcYcWxg3ilgyVDrl0knPhesmTw0cEbnSvieMnb41W7oLsQIP7RB_uEqHj587nZbNeeI9FWI_RQBhEsuVbgP5fXMUbxm6TC1taFY2PRLASVJ6rAi2JsIdNYG22twYwVd0WxubEsFM0T06TzQmQn6kC9B63WoEVJAeWg&h=ioqda8ion8RijFe0JMrfWVlfO4fl_M4D-atK4t6SyIM + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:14:51 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-fc616d77-b572-11f1-bdd4-3cefa50a58cc?api-version=2026-09-01-preview&t=639255608915655641&c=MIIHlTCCBn2gAwIBAgIRAP3gA1NTVfsyY1OAzEH6ZxgwDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgV1VTMiBDQSAwMTAeFw0yNjA4MTcwMzUwMzRaFw0yNzAyMTIwOTUwMzRaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4QdyZCaJJyeTiLaFPtWJfrFjQBvFiPuzXEv1RYUnOVbG6CgM9-zAjE6VqzzH_ry3ylc1gfGz6trnOm36FC95XZN2cCXp9y49dBX5ARtbkqOb5BHj5WIXttGYC8azrRlvpPY-UgoTrxrODNYnd9zPdmWFTt8eiVOabmtu8YkeC5xQbAfStgY-cSF67cM163I2m0lUmMRhXAoURoP8LYqW8LPszEPUm35qa6W0XcEfar_boQxw4ZdhrhAO_JSNzOmKlvArod48lGW9Qo67YUrtSxaxhZLN-ToHXgM2BXkkOkxuLlfF-zewr3Hc0ZK_XonevTH-HqtYfak-VOdgLwwwQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQUMwWFFADYJuZjpCje-R5vqszDG70wHwYDVR0jBBgwFoAUrONy-gOyc549lcjvh1uu3Ruh7WgwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkzL2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC93ZXN0dXMyL2NybHMvY2NtZXdlc3R1czJwa2kvY2NtZXdlc3R1czJpY2EwMS85My9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkzL2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZXdlc3R1czJwa2kud2VzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWV3ZXN0dXMyaWNhMDEvOTMvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY2FjZXJ0cy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21ld2VzdHVzMnBraS53ZXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZXdlc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAfdst7PXa3ogyQLF7Jy4O_dGeSpqDceWxzIbo4NIpZfZMInuRZt6N1cZ17JzQwO9wpT3dbvQrW_9Chfhc9K26kB7skQlG9nV6CIaJ5LroI00qr85tOPRcMbzSa_LwIM_1WhqUAbC1vt42bKM4cgC_QniX7bfhwBKQ7zUjh4Fstu-6lYJzztVawXpnNMYNceUEljzwL2p7jhz2ReKQafSIStD7cREW2DUKEw0nW492Ro2Eb8rMaVqMGpcq__nFurDqDstzrSOzcc76ZsENCHFmj_X5HdtdrvHDESbNm8n4LAaZi15lQlMTGFLJdEx8Ck-obWaoY0XEIqJDE2uMyZfZ7Q&s=ZH4BzBW4H-xDNBzf01Tp6osFNLBWE_NYML80OMZ8mZA7KewSeBCC3G3dRE1030cIhuqqwH8iJi1guaXnnBGLmDzFYYM6L96sNlC9rOnMlvm0u5pfplSlnDnpLfh2ql9tsOanQJvgmJYd-A13C3m28wi9xS9VIsRZWPPCfntDqjDJbd-eF7c5qIAJ8eYab2XejJOaPjr1iNJUyF4wseKkNo0fif39ZqQNTEzwMhv99A1JWQURHBBeWn3ypSYolG00pDgTRJZDDYsXFdmeY7HQGflnLgv0yyT-3BxB_WkzefmNGf0esZcKJZnjlYbayGpQXXuwmyEFSOfmianyMddU_g&h=PNN87rltqhO5Jm3CUaRT8juK-4-zVvT1j14WHvQet0M + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiacentral/ccacbe81-a445-4182-aaf1-39089737e2fd + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 241FA77D1F024ECCB96023467A77FCFA Ref B: SYD281080712036 Ref C: 2026-09-21T04:14:50Z' + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr delete + Connection: + - keep-alive + ParameterSetName: + - -n -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-fc616d77-b572-11f1-bdd4-3cefa50a58cc?api-version=2026-09-01-preview&t=639255608915655641&c=MIIHlTCCBn2gAwIBAgIRAP3gA1NTVfsyY1OAzEH6ZxgwDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgV1VTMiBDQSAwMTAeFw0yNjA4MTcwMzUwMzRaFw0yNzAyMTIwOTUwMzRaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4QdyZCaJJyeTiLaFPtWJfrFjQBvFiPuzXEv1RYUnOVbG6CgM9-zAjE6VqzzH_ry3ylc1gfGz6trnOm36FC95XZN2cCXp9y49dBX5ARtbkqOb5BHj5WIXttGYC8azrRlvpPY-UgoTrxrODNYnd9zPdmWFTt8eiVOabmtu8YkeC5xQbAfStgY-cSF67cM163I2m0lUmMRhXAoURoP8LYqW8LPszEPUm35qa6W0XcEfar_boQxw4ZdhrhAO_JSNzOmKlvArod48lGW9Qo67YUrtSxaxhZLN-ToHXgM2BXkkOkxuLlfF-zewr3Hc0ZK_XonevTH-HqtYfak-VOdgLwwwQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQUMwWFFADYJuZjpCje-R5vqszDG70wHwYDVR0jBBgwFoAUrONy-gOyc549lcjvh1uu3Ruh7WgwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkzL2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC93ZXN0dXMyL2NybHMvY2NtZXdlc3R1czJwa2kvY2NtZXdlc3R1czJpY2EwMS85My9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkzL2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZXdlc3R1czJwa2kud2VzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWV3ZXN0dXMyaWNhMDEvOTMvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY2FjZXJ0cy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21ld2VzdHVzMnBraS53ZXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZXdlc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAfdst7PXa3ogyQLF7Jy4O_dGeSpqDceWxzIbo4NIpZfZMInuRZt6N1cZ17JzQwO9wpT3dbvQrW_9Chfhc9K26kB7skQlG9nV6CIaJ5LroI00qr85tOPRcMbzSa_LwIM_1WhqUAbC1vt42bKM4cgC_QniX7bfhwBKQ7zUjh4Fstu-6lYJzztVawXpnNMYNceUEljzwL2p7jhz2ReKQafSIStD7cREW2DUKEw0nW492Ro2Eb8rMaVqMGpcq__nFurDqDstzrSOzcc76ZsENCHFmj_X5HdtdrvHDESbNm8n4LAaZi15lQlMTGFLJdEx8Ck-obWaoY0XEIqJDE2uMyZfZ7Q&s=ZH4BzBW4H-xDNBzf01Tp6osFNLBWE_NYML80OMZ8mZA7KewSeBCC3G3dRE1030cIhuqqwH8iJi1guaXnnBGLmDzFYYM6L96sNlC9rOnMlvm0u5pfplSlnDnpLfh2ql9tsOanQJvgmJYd-A13C3m28wi9xS9VIsRZWPPCfntDqjDJbd-eF7c5qIAJ8eYab2XejJOaPjr1iNJUyF4wseKkNo0fif39ZqQNTEzwMhv99A1JWQURHBBeWn3ypSYolG00pDgTRJZDDYsXFdmeY7HQGflnLgv0yyT-3BxB_WkzefmNGf0esZcKJZnjlYbayGpQXXuwmyEFSOfmianyMddU_g&h=PNN87rltqhO5Jm3CUaRT8juK-4-zVvT1j14WHvQet0M + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:15:02 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/4ddfaf1a-a9ff-449c-8129-d4b44bf9b9be + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 76A4F0F94C8F40B0B90696D0E3AC3668 Ref B: SYD281080709029 Ref C: 2026-09-21T04:15:02Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - identity delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - --name -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003?api-version=2025-05-31-preview + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:15:07 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/westus/6f08f0ed-fac5-483e-bb81-5968abb564db + x-ms-ratelimit-remaining-subscription-deletes: + - '799' + x-ms-ratelimit-remaining-subscription-global-deletes: + - '11999' + x-msedge-ref: + - 'Ref A: BDBDA738ED194CDFBB390501ABF0EAC9 Ref B: SYD281080706029 Ref C: 2026-09-21T04:15:03Z' + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py index 67bdaaf8f30..22071aa5453 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py @@ -234,3 +234,70 @@ def test_acr_connectedregistry_dedicated_endpoint_not_enabled(self, resource_gro # Delete registry self.cmd('acr delete -n {registry_name} -g {rg} -y') + + @ResourceGroupPreparer() + @AllowLargeResponse(size_kb=99999) + def test_acr_connectedregistry_managed_identity(self): + # Managed-identity auth mode for connected registries. Recorded scenario is + # intentionally minimal (create + show + get-settings + delete) so the cassette + # does not depend on the SyncToken->ManagedIdentity migration. + # Client-side validation, the migration state machine, and MI-mode delete cleanup + # are covered by mock-based unit tests in test_acr_connected_registry_mi_unit.py. + # Note: This test does NOT import from azure.mgmt.containerregistry so the + # recording remains valid across future SDK model-namespace changes. + + self.kwargs.update({ + 'registry_name': self.create_random_name('clireg', 20), + 'cr_mi_name': 'crmiscen', + 'rg_loc': 'eastus', + 'sku': 'Premium', + 'identity_name': self.create_random_name('cr-mi-id', 20), + }) + + # Registry + data endpoint + abac (required for connected-registry). + self.cmd('acr create -n {registry_name} -g {rg} -l {rg_loc} --sku {sku} ' + '--role-assignment-mode rbac-abac', + checks=[self.check('name', '{registry_name}'), + self.check('sku.name', '{sku}'), + self.check('provisioningState', 'Succeeded'), + self.check('roleAssignmentMode', 'AbacRepositoryPermissions')]) + self.cmd('acr update -n {registry_name} -g {rg} --data-endpoint-enabled true', + checks=[self.check('dataEndpointEnabled', True), + self.check('roleAssignmentMode', 'AbacRepositoryPermissions')]) + + # User-assigned identity. + result = self.cmd('identity create --name {identity_name} -g {rg}').get_output_in_json() + self.kwargs['identity_id'] = result['id'] + self.kwargs['identity_client_id'] = result['clientId'] + + # --- Create with ManagedIdentity --- + self.cmd('acr connected-registry create -n {cr_mi_name} -r {registry_name} -g {rg} ' + '-m ReadOnly --auth-type ManagedIdentity --identity {identity_id}', + checks=[self.check('name', '{cr_mi_name}'), + self.check('mode', 'ReadOnly'), + self.check('provisioningState', 'Succeeded'), + self.check('parent.syncProperties.authType', 'ManagedIdentity'), + self.check('identity.type', 'userAssigned')]) + + # --- Show reflects MI --- + self.cmd('acr connected-registry show -n {cr_mi_name} -r {registry_name} -g {rg}', + checks=[self.check('parent.syncProperties.authType', 'ManagedIdentity'), + self.check('identity.type', 'userAssigned')]) + + # --- get-settings returns MI-flavored connection string --- + settings = self.cmd('acr connected-registry get-settings -n {cr_mi_name} -r {registry_name} ' + '-g {rg} --parent-protocol https').get_output_in_json() + connection_string = settings['ACR_REGISTRY_CONNECTION_STRING'] + self.assertIn( + 'ManagedIdentityClientId={};'.format(self.kwargs['identity_client_id']), + connection_string) + self.assertNotIn('SyncTokenName=', connection_string) + self.assertNotIn('SyncTokenPassword=', connection_string) + self.assertNotIn('SYNC_TOKEN_USER', settings) + self.assertNotIn('SYNC_TOKEN_PASSWORD', settings) + + # --- MI-mode delete (no sync token / scope map cleanup path) --- + self.cmd('acr connected-registry delete -n {cr_mi_name} -r {registry_name} -g {rg} -y') + self.cmd('acr delete -n {registry_name} -g {rg} -y') + # Shared RG: clean up the user-assigned identity too. + self.cmd('identity delete --name {identity_name} -g {rg}') From cb3e0292b08a9647c08a5a84de3acad1829b342a Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Mon, 21 Sep 2026 14:46:30 +1000 Subject: [PATCH 08/16] tests(acr): add connected-registry mi migration recording --- ...edregistry_managed_identity_migration.yaml | 1643 +++++++++++++++++ .../test_acr_connectedregistry_commands.py | 85 + 2 files changed, 1728 insertions(+) create mode 100644 src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity_migration.yaml diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity_migration.yaml b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity_migration.yaml new file mode 100644 index 00000000000..fa31649f39e --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_connectedregistry_managed_identity_migration.yaml @@ -0,0 +1,1643 @@ +interactions: +- request: + body: '{"location": "eastus", "sku": {"name": "Premium"}, "properties": {"adminUserEnabled": + false, "roleAssignmentMode": "AbacRepositoryPermissions"}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr create + Connection: + - keep-alive + Content-Length: + - '144' + Content-Type: + - application/json + ParameterSetName: + - -n -g -l --sku --role-assignment-mode + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:39.2175714+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":false,"regionalEndpoints":"Disabled","dataEndpointHostNames":[],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1722' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:46 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/289d5df1-afbe-426b-bc3c-ea492d4c09a3 + x-ms-ratelimit-remaining-subscription-global-writes: + - '12000' + x-ms-ratelimit-remaining-subscription-writes: + - '800' + x-msedge-ref: + - 'Ref A: 100EA8BECD79493F9081120BCEAC5FAC Ref B: SYD281080705029 Ref C: 2026-09-21T04:40:37Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr update + Connection: + - keep-alive + ParameterSetName: + - -n -g --data-endpoint-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:39.2175714+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":false,"regionalEndpoints":"Disabled","dataEndpointHostNames":[],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1722' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:47 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: AE95ACD4CB1E4E2E9E17F2E1DE4E5D1C Ref B: SYD281080710025 Ref C: 2026-09-21T04:40:47Z' + status: + code: 200 + message: OK +- request: + body: '{"properties": {"dataEndpointEnabled": true}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr update + Connection: + - keep-alive + Content-Length: + - '45' + Content-Type: + - application/json + ParameterSetName: + - -n -g --data-endpoint-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PATCH + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:50 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiasoutheast/88f7a069-737f-46fd-9c60-a500c8363d96 + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: BF2E1CEA16CA494B916209D29FCA3563 Ref B: SYD281080708036 Ref C: 2026-09-21T04:40:48Z' + status: + code: 200 + message: OK +- request: + body: '{"location": "eastus"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - identity create + Connection: + - keep-alive + Content-Length: + - '22' + Content-Type: + - application/json + ParameterSetName: + - -n -g -l + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003?api-version=2025-05-31-preview + response: + body: + string: '{"location":"eastus","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003","name":"cr-mi-id000003","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"isolationScope":"None","assignmentRestrictions":{"providers":[]},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","principalId":"eb1bd128-216b-4383-b86e-11cc2b90e7c9","clientId":"ecc4d608-39bc-45e8-a83b-10e52b43567c"}}' + headers: + cache-control: + - no-cache + content-length: + - '512' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:54 GMT + expires: + - '-1' + location: + - /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003 + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/e2e8fc7c-0a6e-4e4a-b1c2-4d8e14e30b1d + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: 87D08F9630494F8BA5749EADB190126D Ref B: SYD281080708034 Ref C: 2026-09-21T04:40:52Z' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --mode --auth-type --repository --log-level --sync-schedule --sync-window + --notifications --gc-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:56 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: A76ADA3D9AF849B39F232E86E6783D50 Ref B: SYD281080712036 Ref C: 2026-09-21T04:40:56Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --mode --auth-type --repository --log-level --sync-schedule --sync-window + --notifications --gc-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/scopeMaps/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"error":{"code":"ResourceNotFound","message":"The resource crmigration + could not be found."},"status":"Failed"}' + headers: + api-supported-versions: + - 2019-05-01-preview, 2020-11-01-preview, 2021-06-01-preview, 2021-08-01-preview, + 2021-12-01-preview, 2022-02-01-preview, 2022-12-01, 2023-01-01-preview, 2023-06-01-preview, + 2023-07-01, 2023-08-01-preview, 2023-11-01-preview, 2024-01-01-preview, 2024-11-01-preview, + 2025-03-01-preview, 2025-04-01, 2025-05-01-preview, 2025-06-01-preview, 2025-09-01-preview, + 2025-11-01, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, 2026-09-01-preview, + 2026-11-01 + cache-control: + - no-cache + content-length: + - '112' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:57 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/482b32ff-dd6d-42c1-b326-7a194090b1f3 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 4F71C46ED37E49A8ACF11AC3BFB75429 Ref B: SYD281080705034 Ref C: 2026-09-21T04:40:57Z' + status: + code: 404 + message: Not Found +- request: + body: '{"properties": {"actions": ["repositories/hello-world/content/read", "repositories/hello-world/metadata/read", + "gateway/crmigration/config/read", "gateway/crmigration/config/write", "gateway/crmigration/message/read", + "gateway/crmigration/message/write"], "description": "Created by connected registry + sync token: crmigration"}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + Content-Length: + - '328' + Content-Type: + - application/json + ParameterSetName: + - -n -r -g --mode --auth-type --repository --log-level --sync-schedule --sync-window + --notifications --gc-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/scopeMaps/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/scopeMaps","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/scopeMaps/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:58.9997153+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:58.9997153+00:00"},"properties":{"description":"Created + by connected registry sync token: crmigration","type":"UserDefined","creationDate":"2026-09-21T04:40:59.0223319+00:00","provisioningState":"Succeeded","actions":["repositories/hello-world/content/read","repositories/hello-world/metadata/read","gateway/crmigration/config/read","gateway/crmigration/config/write","gateway/crmigration/message/read","gateway/crmigration/message/write"]}}' + headers: + api-supported-versions: + - 2019-05-01-preview, 2020-11-01-preview, 2021-06-01-preview, 2021-08-01-preview, + 2021-12-01-preview, 2022-02-01-preview, 2022-12-01, 2023-01-01-preview, 2023-06-01-preview, + 2023-07-01, 2023-08-01-preview, 2023-11-01-preview, 2024-01-01-preview, 2024-11-01-preview, + 2025-03-01-preview, 2025-04-01, 2025-05-01-preview, 2025-06-01-preview, 2025-09-01-preview, + 2025-11-01, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, 2026-09-01-preview, + 2026-11-01 + cache-control: + - no-cache + content-length: + - '911' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:58 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/fb5f8ec9-d918-4820-b927-e55271510d51 + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: 7935BC7EC4674E138957717A7F1F962C Ref B: SYD281080712036 Ref C: 2026-09-21T04:40:58Z' + status: + code: 200 + message: OK +- request: + body: '{"properties": {"scopeMapId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/scopeMaps/crmigration", + "status": "enabled"}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + Content-Length: + - '222' + Content-Type: + - application/json + ParameterSetName: + - -n -r -g --mode --auth-type --repository --log-level --sync-schedule --sync-window + --notifications --gc-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/tokens","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:59.7573903+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:59.7573903+00:00"},"properties":{"creationDate":"2026-09-21T04:40:59.7950047+00:00","provisioningState":"Creating","scopeMapId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/scopeMaps/crmigration","credentials":{"passwords":[]},"status":"enabled"}}' + headers: + api-supported-versions: + - 2019-05-01-preview, 2020-11-01-preview, 2021-06-01-preview, 2021-08-01-preview, + 2021-12-01-preview, 2022-02-01-preview, 2022-12-01, 2023-01-01-preview, 2023-06-01-preview, + 2023-07-01, 2023-08-01-preview, 2023-11-01-preview, 2024-01-01-preview, 2024-11-01-preview, + 2025-03-01-preview, 2025-04-01, 2025-05-01-preview, 2025-06-01-preview, 2025-09-01-preview, + 2025-11-01, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, 2026-09-01-preview, + 2026-11-01 + azure-asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration/operationStatuses/token-a247ff8e-b576-11f1-b229-3cefa50a58cc?api-version=2026-09-01-preview&t=639255624599136421&c=MIIHlTCCBn2gAwIBAgIRAN0yZzL8aR42UZysboj3ciowDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgRVVTMiBDQSAwMTAeFw0yNjA4MTQwMDQwMTRaFw0yNzAyMDkwNjQwMTRaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzoSOkVR7MNj87TdZrq2tsL7eEWBZ1UxYUjlHs2t1x6Xn31o-6e5yM1I79Xw17HpG_ZRC01sH0DmLucuBF6EGQR50aTJ6mx22HrEe4YQhQiTieYabApNFEW7C1Z3sqhwTVaWGvV9-nw9anTx1HztS5s2jjMeJoebstq-wBIvYIOyM7hj12vYY5vdXTn9Sask3V8S3KBxdPpOFhQ5pKF6CgT-fQ9-scbzgeKeWuPXZTO0EeH02xAsj1c-lki5VGv0RewzD2beJxGO1-CxJFOfH9H3UnlZMKLg6kT-aBTn6RuYVuLJoMYYC-eHbYtahA3x5r3yutNG8gegIMlLlcdTGAQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQU7naFfTwmNksX70OjHOYQPsR55KIwHwYDVR0jBBgwFoAU_Ow-26p8H4IeBbihBvlD5wKzCrkwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9lYXN0dXMyL2NybHMvY2NtZWVhc3R1czJwa2kvY2NtZWVhc3R1czJpY2EwMS8zOS9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZWVhc3R1czJwa2kuZWFzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWVlYXN0dXMyaWNhMDEvMzkvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY2FjZXJ0cy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21lZWFzdHVzMnBraS5lYXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZWVhc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAJrRoJWjIzsymA0Vpio4e2hRDOWlG5PpWmWos3Gflt8XcQwRsU-vvdeWk-uT-wHYn52846N5Ue5cbvM8NV-labOA852VL2mtuHnz7bkkRfWTlP-tB-JYDS8l0yGcTENq-UNlakbleLgtfD-Qr09l853jhegiUP3vJKLXMCFF1C2maSNhwZg1MlrEswNSPzRH0Xj9q0-487lH42RncuRXCIqd8ljf1_8v-IXMl6WtDdQDYjQE_s-OHN0BNXt0t4wTd5ikeG6NCH2SHC2wB-PchAiE5P4oHK6Vx3M0q3TEexP11Up6I9ksnpNBw256ZKPa0pX3urxLa215fDhtScA9RzA&s=OcFQKnISu4MoxtO9I1iGTNbT2srXy2EVSM1ULPFlzodZ82AfSZWqAhVoV4pzyEe4DibUPbBl1Q9u-3Hv2xKGIQhXND8pd-tpXknmRTjLinzTge15V4xQbP8Ct20wrf8KEFv3Dj8Mlhuiu10TJGskbuvrAg3DfmnDMUtoYnrT4yk8VEI44Y-aQMT4u_QYk65kQBnnSq3ZODwTV3Wq1RV7mtKCkGsqucV-1NhpF0-NI6MEdJWTiY-rhgKFbl8xl66_8OUjQezfdC6a0hLmqGGOxCEGEHAGRsA5bqzXfr2zcDwpGw9UaEoLLYdFoklQstSBVCn5HBrI1yZc5ikSHAKbNg&h=iabC062MiIDAEIu0nnddLgasL3hceI3HvtCxqsUOl7Q + cache-control: + - no-cache + content-length: + - '813' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:40:59 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/d7edc53a-b63b-431b-ab27-652f6641cd66 + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: D6B2F7549BFF44898C29C06992E025DE Ref B: SYD281080710060 Ref C: 2026-09-21T04:40:59Z' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --mode --auth-type --repository --log-level --sync-schedule --sync-window + --notifications --gc-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration/operationStatuses/token-a247ff8e-b576-11f1-b229-3cefa50a58cc?api-version=2026-09-01-preview&t=639255624599136421&c=MIIHlTCCBn2gAwIBAgIRAN0yZzL8aR42UZysboj3ciowDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgRVVTMiBDQSAwMTAeFw0yNjA4MTQwMDQwMTRaFw0yNzAyMDkwNjQwMTRaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzoSOkVR7MNj87TdZrq2tsL7eEWBZ1UxYUjlHs2t1x6Xn31o-6e5yM1I79Xw17HpG_ZRC01sH0DmLucuBF6EGQR50aTJ6mx22HrEe4YQhQiTieYabApNFEW7C1Z3sqhwTVaWGvV9-nw9anTx1HztS5s2jjMeJoebstq-wBIvYIOyM7hj12vYY5vdXTn9Sask3V8S3KBxdPpOFhQ5pKF6CgT-fQ9-scbzgeKeWuPXZTO0EeH02xAsj1c-lki5VGv0RewzD2beJxGO1-CxJFOfH9H3UnlZMKLg6kT-aBTn6RuYVuLJoMYYC-eHbYtahA3x5r3yutNG8gegIMlLlcdTGAQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQU7naFfTwmNksX70OjHOYQPsR55KIwHwYDVR0jBBgwFoAU_Ow-26p8H4IeBbihBvlD5wKzCrkwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9lYXN0dXMyL2NybHMvY2NtZWVhc3R1czJwa2kvY2NtZWVhc3R1czJpY2EwMS8zOS9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZWVhc3R1czJwa2kuZWFzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWVlYXN0dXMyaWNhMDEvMzkvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY2FjZXJ0cy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21lZWFzdHVzMnBraS5lYXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZWVhc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAJrRoJWjIzsymA0Vpio4e2hRDOWlG5PpWmWos3Gflt8XcQwRsU-vvdeWk-uT-wHYn52846N5Ue5cbvM8NV-labOA852VL2mtuHnz7bkkRfWTlP-tB-JYDS8l0yGcTENq-UNlakbleLgtfD-Qr09l853jhegiUP3vJKLXMCFF1C2maSNhwZg1MlrEswNSPzRH0Xj9q0-487lH42RncuRXCIqd8ljf1_8v-IXMl6WtDdQDYjQE_s-OHN0BNXt0t4wTd5ikeG6NCH2SHC2wB-PchAiE5P4oHK6Vx3M0q3TEexP11Up6I9ksnpNBw256ZKPa0pX3urxLa215fDhtScA9RzA&s=OcFQKnISu4MoxtO9I1iGTNbT2srXy2EVSM1ULPFlzodZ82AfSZWqAhVoV4pzyEe4DibUPbBl1Q9u-3Hv2xKGIQhXND8pd-tpXknmRTjLinzTge15V4xQbP8Ct20wrf8KEFv3Dj8Mlhuiu10TJGskbuvrAg3DfmnDMUtoYnrT4yk8VEI44Y-aQMT4u_QYk65kQBnnSq3ZODwTV3Wq1RV7mtKCkGsqucV-1NhpF0-NI6MEdJWTiY-rhgKFbl8xl66_8OUjQezfdC6a0hLmqGGOxCEGEHAGRsA5bqzXfr2zcDwpGw9UaEoLLYdFoklQstSBVCn5HBrI1yZc5ikSHAKbNg&h=iabC062MiIDAEIu0nnddLgasL3hceI3HvtCxqsUOl7Q + response: + body: + string: '{"status":"Succeeded"}' + headers: + api-supported-versions: + - 2019-05-01-preview, 2020-11-01-preview, 2021-06-01-preview, 2021-08-01-preview, + 2021-12-01-preview, 2022-02-01-preview, 2022-12-01, 2023-01-01-preview, 2023-06-01-preview, + 2023-07-01, 2023-08-01-preview, 2023-11-01-preview, 2024-01-01-preview, 2024-11-01-preview, + 2025-03-01-preview, 2025-04-01, 2025-05-01-preview, 2025-06-01-preview, 2025-09-01-preview, + 2025-11-01, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, 2026-09-01-preview, + 2026-11-01 + azure-asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration/operationStatuses/token-a247ff8e-b576-11f1-b229-3cefa50a58cc?api-version=2026-09-01-preview&t=639255624606387261&c=MIIHlTCCBn2gAwIBAgIRAN0yZzL8aR42UZysboj3ciowDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgRVVTMiBDQSAwMTAeFw0yNjA4MTQwMDQwMTRaFw0yNzAyMDkwNjQwMTRaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzoSOkVR7MNj87TdZrq2tsL7eEWBZ1UxYUjlHs2t1x6Xn31o-6e5yM1I79Xw17HpG_ZRC01sH0DmLucuBF6EGQR50aTJ6mx22HrEe4YQhQiTieYabApNFEW7C1Z3sqhwTVaWGvV9-nw9anTx1HztS5s2jjMeJoebstq-wBIvYIOyM7hj12vYY5vdXTn9Sask3V8S3KBxdPpOFhQ5pKF6CgT-fQ9-scbzgeKeWuPXZTO0EeH02xAsj1c-lki5VGv0RewzD2beJxGO1-CxJFOfH9H3UnlZMKLg6kT-aBTn6RuYVuLJoMYYC-eHbYtahA3x5r3yutNG8gegIMlLlcdTGAQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQU7naFfTwmNksX70OjHOYQPsR55KIwHwYDVR0jBBgwFoAU_Ow-26p8H4IeBbihBvlD5wKzCrkwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9lYXN0dXMyL2NybHMvY2NtZWVhc3R1czJwa2kvY2NtZWVhc3R1czJpY2EwMS8zOS9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZWVhc3R1czJwa2kuZWFzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWVlYXN0dXMyaWNhMDEvMzkvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY2FjZXJ0cy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21lZWFzdHVzMnBraS5lYXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZWVhc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAJrRoJWjIzsymA0Vpio4e2hRDOWlG5PpWmWos3Gflt8XcQwRsU-vvdeWk-uT-wHYn52846N5Ue5cbvM8NV-labOA852VL2mtuHnz7bkkRfWTlP-tB-JYDS8l0yGcTENq-UNlakbleLgtfD-Qr09l853jhegiUP3vJKLXMCFF1C2maSNhwZg1MlrEswNSPzRH0Xj9q0-487lH42RncuRXCIqd8ljf1_8v-IXMl6WtDdQDYjQE_s-OHN0BNXt0t4wTd5ikeG6NCH2SHC2wB-PchAiE5P4oHK6Vx3M0q3TEexP11Up6I9ksnpNBw256ZKPa0pX3urxLa215fDhtScA9RzA&s=BYyfVl0b-cvv2dobB6IAdfiPHhXwtpBVi4qKOoz5Zjs3XBfRq1IbtH1lmdfDPFtL-6hT43ew2VkZvCDv4irSWef3ymUth2ZCzbGRqFS3k67Pux5jrJRTOAgkqcINlJX7L1amiMt5cjEV5FZdAM6j1ms2-Z1Zc2JuzmZy_W-utSIUiANbPsZ02RCDGQcGoAj78t9TlD8qmiUKwyNWgFAXn7BhleIN-bz5K7sUl2XCq83ZGgWLtfNk4ZOCEX0xOG4bwTfdDlowPaUtMegXzxMxVE3H58zhOVwKdkgk_qdobZBZly3V-Fogj-VgQQKVpLk_X3Ti3EnWBac-p1ZV2TScFQ&h=CnsMQC23z2CpepU3IKag6txIOMm1qWRu71lyST09PgM + cache-control: + - no-cache + content-length: + - '22' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:00 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/a3fa96ec-3ef5-44d2-b851-403234888a5f + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 47ECD7CF695D402A8E5E8A138BC73060 Ref B: SYD281080706036 Ref C: 2026-09-21T04:41:00Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --mode --auth-type --repository --log-level --sync-schedule --sync-window + --notifications --gc-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/tokens","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:59.7573903+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:59.7573903+00:00"},"properties":{"creationDate":"2026-09-21T04:40:59.7950047+00:00","provisioningState":"Succeeded","scopeMapId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/scopeMaps/crmigration","credentials":{"passwords":[]},"status":"enabled"}}' + headers: + api-supported-versions: + - 2019-05-01-preview, 2020-11-01-preview, 2021-06-01-preview, 2021-08-01-preview, + 2021-12-01-preview, 2022-02-01-preview, 2022-12-01, 2023-01-01-preview, 2023-06-01-preview, + 2023-07-01, 2023-08-01-preview, 2023-11-01-preview, 2024-01-01-preview, 2024-11-01-preview, + 2025-03-01-preview, 2025-04-01, 2025-05-01-preview, 2025-06-01-preview, 2025-09-01-preview, + 2025-11-01, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, 2026-09-01-preview, + 2026-11-01 + cache-control: + - no-cache + content-length: + - '814' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:01 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/e8d96691-2b39-4fe7-ab82-edea8e073450 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 5A1477C2F01D40208075679BC678F22A Ref B: SYD281080712036 Ref C: 2026-09-21T04:41:01Z' + status: + code: 200 + message: OK +- request: + body: '{"properties": {"mode": "readonly", "notificationsList": ["hello-world:tag:push"], + "parent": {"syncProperties": {"tokenId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration", + "schedule": "0 0/10 * * *", "messageTtl": "P2D", "syncWindow": "PT4H", "authType": + "SyncToken"}}, "garbageCollection": {"enabled": false, "schedule": "0 0 * * + *"}, "logging": {"logLevel": "Warning", "auditLogStatus": "Disabled"}}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry create + Connection: + - keep-alive + Content-Length: + - '522' + Content-Type: + - application/json + ParameterSetName: + - -n -r -g --mode --auth-type --repository --log-level --sync-schedule --sync-window + --notifications --gc-enabled + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:41:02.12424+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:41:02.12424+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"tokenId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration","schedule":"0 + 0/10 * * *","syncWindow":"PT4H","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"SyncToken"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Warning","auditLogStatus":"Disabled"},"notificationsList":["hello-world:tag:push"],"garbageCollection":{"enabled":false,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1192' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:01 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/62a2ba6b-a47f-4794-89e1-9236a42556d0 + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: 386B648B794441C181045D6D4C8E9DC8 Ref B: SYD281080707025 Ref C: 2026-09-21T04:41:01Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry show + Connection: + - keep-alive + ParameterSetName: + - -n -r -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:02 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: AB6A15367E564FBA958003CE6B01C9AF Ref B: SYD281080705034 Ref C: 2026-09-21T04:41:02Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry show + Connection: + - keep-alive + ParameterSetName: + - -n -r -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:41:02.12424+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:41:02.12424+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"tokenId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration","schedule":"0 + 0/10 * * *","syncWindow":"PT4H","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"SyncToken"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Warning","auditLogStatus":"Disabled"},"notificationsList":["hello-world:tag:push"],"garbageCollection":{"enabled":false,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1192' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:02 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/c3d8ca51-f01c-48bb-b418-3bc7d1e79bbf + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: A2775DE7984B4E9581DD7907880A8FE6 Ref B: SYD281080708060 Ref C: 2026-09-21T04:41:03Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry update + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --auth-type --identity + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:04 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 8E8D4A800B0F4AABB1DBF07BDDEEA725 Ref B: SYD281080706025 Ref C: 2026-09-21T04:41:03Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry update + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --auth-type --identity + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:04 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 7B3F180F50404C7588861B1618A9FC6E Ref B: SYD281080708054 Ref C: 2026-09-21T04:41:04Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry update + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --auth-type --identity + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:41:02.12424+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:41:02.12424+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"tokenId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/tokens/crmigration","schedule":"0 + 0/10 * * *","syncWindow":"PT4H","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"SyncToken"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Warning","auditLogStatus":"Disabled"},"notificationsList":["hello-world:tag:push"],"garbageCollection":{"enabled":false,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1192' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:04 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/b2f65fc2-8e7d-4f35-bb18-de78e9cc2ce1 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 1F25A72497754D61B13B8CEEE67AFD2A Ref B: SYD281080708029 Ref C: 2026-09-21T04:41:05Z' + status: + code: 200 + message: OK +- request: + body: '{"identity": {"type": "UserAssigned", "userAssignedIdentities": {"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003": + {}}}, "properties": {"syncProperties": {"authType": "ManagedIdentity"}, "garbageCollection": + {}, "logging": {}}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry update + Connection: + - keep-alive + Content-Length: + - '338' + Content-Type: + - application/json + ParameterSetName: + - -n -r -g --auth-type --identity + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: PATCH + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"eb1bd128-216b-4383-b86e-11cc2b90e7c9","clientId":"ecc4d608-39bc-45e8-a83b-10e52b43567c"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:41:05.9950386+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:41:05.9950386+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"0 + 0/10 * * *","syncWindow":"PT4H","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Warning","auditLogStatus":"Disabled"},"notificationsList":["hello-world:tag:push"],"garbageCollection":{"enabled":false,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1352' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:05 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/b67ec326-abb5-4cfd-a2ae-f6204640afc5 + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: 9D152CC29A5449A98F7BFB5DB8A2E5E0 Ref B: SYD281080705052 Ref C: 2026-09-21T04:41:05Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry show + Connection: + - keep-alive + ParameterSetName: + - -n -r -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:06 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 0497EFC463D14F2F86452DBF9FDD2DC6 Ref B: SYD281080707023 Ref C: 2026-09-21T04:41:06Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry show + Connection: + - keep-alive + ParameterSetName: + - -n -r -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"eb1bd128-216b-4383-b86e-11cc2b90e7c9","clientId":"ecc4d608-39bc-45e8-a83b-10e52b43567c"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:41:05.9950386+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:41:05.9950386+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"0 + 0/10 * * *","syncWindow":"PT4H","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Warning","auditLogStatus":"Disabled"},"notificationsList":["hello-world:tag:push"],"garbageCollection":{"enabled":false,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1352' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:06 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/310833ec-ba6b-403a-a9ab-5456fe2eb05c + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: FC725E67DD9E452A85B865C6F73C298D Ref B: SYD281080711060 Ref C: 2026-09-21T04:41:07Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry get-settings + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --parent-protocol + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:08 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 549FDCEFE73C4DEA939953F8A55AC882 Ref B: SYD281080709023 Ref C: 2026-09-21T04:41:08Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry get-settings + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --parent-protocol + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:09 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: F3A2B892BA8D4E6F88076AAC0C973C20 Ref B: SYD281080709060 Ref C: 2026-09-21T04:41:09Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry get-settings + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --parent-protocol + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"eb1bd128-216b-4383-b86e-11cc2b90e7c9","clientId":"ecc4d608-39bc-45e8-a83b-10e52b43567c"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:41:05.9950386+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:41:05.9950386+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"0 + 0/10 * * *","syncWindow":"PT4H","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Warning","auditLogStatus":"Disabled"},"notificationsList":["hello-world:tag:push"],"garbageCollection":{"enabled":false,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1352' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:10 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/2ec0f7b9-f1b4-4157-8a27-ef5d503c0583 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: A1F504180D514629AD16DB51AA423F2A Ref B: SYD281080711034 Ref C: 2026-09-21T04:41:09Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --cleanup -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:11 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: A510166E2D774FE7B36E9DCCB7AD397D Ref B: SYD281080706031 Ref C: 2026-09-21T04:41:11Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --cleanup -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Succeeded","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1758' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:12 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 0FCC3578AB8A445A91688EDDD04702FB Ref B: SYD281080707040 Ref C: 2026-09-21T04:41:11Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + ParameterSetName: + - -n -r -g --cleanup -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '{"type":"Microsoft.ContainerRegistry/registries/connectedRegistries","identity":{"type":"userAssigned","userAssignedIdentities":{"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003":{"principalId":"eb1bd128-216b-4383-b86e-11cc2b90e7c9","clientId":"ecc4d608-39bc-45e8-a83b-10e52b43567c"}}},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration","name":"crmigration","systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:41:05.9950386+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:41:05.9950386+00:00"},"properties":{"provisioningState":"Succeeded","mode":"ReadOnly","connectionState":"Offline","activation":{"status":"Inactive"},"parent":{"syncProperties":{"schedule":"0 + 0/10 * * *","syncWindow":"PT4H","messageTtl":"P2D","gatewayEndpoint":"clireg000002.eastus.data.azurecr.io","authType":"ManagedIdentity"}},"loginServer":{"tls":{"certificate":{}}},"logging":{"logLevel":"Warning","auditLogStatus":"Disabled"},"notificationsList":["hello-world:tag:push"],"garbageCollection":{"enabled":false,"schedule":"0 + 0 * * *"}}}' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1352' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:11 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/fc52b27d-46b0-42c8-bd87-46906c400003 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 59F9408203C04104B5EE2E2EF5851D7A Ref B: SYD281080712031 Ref C: 2026-09-21T04:41:12Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr connected-registry delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -n -r -g --cleanup -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002/connectedRegistries/crmigration?api-version=2026-09-01-preview + response: + body: + string: '' + headers: + api-supported-versions: + - 2025-09-01-preview, 2025-12-01-preview, 2026-01-01-preview, 2026-03-01-preview, + 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:41:13 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/ed63f7ea-80e2-4988-bd01-05ef83b8feda + x-ms-ratelimit-remaining-subscription-deletes: + - '799' + x-ms-ratelimit-remaining-subscription-global-deletes: + - '11999' + x-msedge-ref: + - 'Ref A: F217DF8256F240869AF724E39C8B9A3D Ref B: SYD281080710042 Ref C: 2026-09-21T04:41:13Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - identity show + Connection: + - keep-alive + ParameterSetName: + - -n -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003?api-version=2025-05-31-preview + response: + body: + string: '{"location":"eastus","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003","name":"cr-mi-id000003","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"isolationScope":"None","assignmentRestrictions":{"providers":[]},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","principalId":"eb1bd128-216b-4383-b86e-11cc2b90e7c9","clientId":"ecc4d608-39bc-45e8-a83b-10e52b43567c"}}' + headers: + cache-control: + - no-cache + content-length: + - '512' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:13 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: D7FA6E37EABE42ECB67EEF3E25B47E3F Ref B: SYD281080711060 Ref C: 2026-09-21T04:41:14Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -n -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002?api-version=2026-09-01-preview + response: + body: + string: '{"sku":{"name":"Premium","tier":"Premium"},"type":"Microsoft.ContainerRegistry/registries","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ContainerRegistry/registries/clireg000002","name":"clireg000002","location":"eastus","tags":{},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-09-21T04:40:39.2175714+00:00","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-09-21T04:40:50.9476009+00:00"},"properties":{"loginServer":"clireg000002.azurecr.io","creationDate":"2026-09-21T04:40:39.2175714Z","provisioningState":"Deleting","adminUserEnabled":false,"networkRuleSet":{"defaultAction":"Allow","virtualNetworkRules":[],"ipRules":[]},"policies":{"quarantinePolicy":{"status":"disabled"},"trustPolicy":{"type":"Notary","status":"disabled"},"retentionPolicy":{"days":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134338+00:00","status":"disabled"},"exportPolicy":{"status":"enabled"},"azureADAuthenticationAsArmPolicy":{"status":"enabled"},"softDeletePolicy":{"retentionDays":7,"lastUpdatedTime":"2026-09-21T04:40:46.6134663+00:00","status":"disabled"}},"encryption":{"status":"disabled"},"dataEndpointEnabled":true,"regionalEndpoints":"Disabled","dataEndpointHostNames":["clireg000002.eastus.data.azurecr.io"],"regionalEndpointHostNames":[],"endpointProtocol":"IPv4","privateEndpointConnections":[],"publicNetworkAccess":"Enabled","networkRuleBypassOptions":"AzureServices","networkRuleBypassAllowedForTasks":false,"zoneRedundancy":"Disabled","anonymousPullEnabled":false,"metadataSearch":"Disabled","roleAssignmentMode":"AbacRepositoryPermissions","autoGeneratedDomainNameLabelScope":"Unsecure","writableCacheRepos":"Disabled"}}' + headers: + api-supported-versions: + - 2026-09-01-preview + cache-control: + - no-cache + content-length: + - '1757' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 21 Sep 2026 04:41:14 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-ad708138-b576-11f1-8612-3cefa50a58cc?api-version=2026-09-01-preview&t=639255624753450448&c=MIIHlTCCBn2gAwIBAgIRAN0yZzL8aR42UZysboj3ciowDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgRVVTMiBDQSAwMTAeFw0yNjA4MTQwMDQwMTRaFw0yNzAyMDkwNjQwMTRaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzoSOkVR7MNj87TdZrq2tsL7eEWBZ1UxYUjlHs2t1x6Xn31o-6e5yM1I79Xw17HpG_ZRC01sH0DmLucuBF6EGQR50aTJ6mx22HrEe4YQhQiTieYabApNFEW7C1Z3sqhwTVaWGvV9-nw9anTx1HztS5s2jjMeJoebstq-wBIvYIOyM7hj12vYY5vdXTn9Sask3V8S3KBxdPpOFhQ5pKF6CgT-fQ9-scbzgeKeWuPXZTO0EeH02xAsj1c-lki5VGv0RewzD2beJxGO1-CxJFOfH9H3UnlZMKLg6kT-aBTn6RuYVuLJoMYYC-eHbYtahA3x5r3yutNG8gegIMlLlcdTGAQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQU7naFfTwmNksX70OjHOYQPsR55KIwHwYDVR0jBBgwFoAU_Ow-26p8H4IeBbihBvlD5wKzCrkwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9lYXN0dXMyL2NybHMvY2NtZWVhc3R1czJwa2kvY2NtZWVhc3R1czJpY2EwMS8zOS9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZWVhc3R1czJwa2kuZWFzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWVlYXN0dXMyaWNhMDEvMzkvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY2FjZXJ0cy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21lZWFzdHVzMnBraS5lYXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZWVhc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAJrRoJWjIzsymA0Vpio4e2hRDOWlG5PpWmWos3Gflt8XcQwRsU-vvdeWk-uT-wHYn52846N5Ue5cbvM8NV-labOA852VL2mtuHnz7bkkRfWTlP-tB-JYDS8l0yGcTENq-UNlakbleLgtfD-Qr09l853jhegiUP3vJKLXMCFF1C2maSNhwZg1MlrEswNSPzRH0Xj9q0-487lH42RncuRXCIqd8ljf1_8v-IXMl6WtDdQDYjQE_s-OHN0BNXt0t4wTd5ikeG6NCH2SHC2wB-PchAiE5P4oHK6Vx3M0q3TEexP11Up6I9ksnpNBw256ZKPa0pX3urxLa215fDhtScA9RzA&s=OZvJ1_qztoF-MC6TjVrQaW0VNC5Dofrxl8KLB56YTEewEUzT55hLY2S1A_hzSjsy5e9d8NlEsKRnDENOp8jQm3Aje1ByKYrNV3bt3QvPdn5-NchXJGj48H5zRTwwRfkS1A9EfDbVcPLNbIwfBDDFBhV19bCh5s5XBZ_gRPNT00hH9d9NPc7BIDdKREhGx5T-o9DWhgF-W-mVqydQeafXSuozPcSZuTUoyEPkOLotgTEWaPIKsXOxW4EbFPyxDCFuVYPIyA4jxoiB9CXiizRPX38qr3ztjUsXZHk8sKpCUP7eUqzWMR4ohy0WkNtd7a0ycvjxp4x574l4HmHCDEY_NA&h=l-ykf5qpe5v5y5SZCEFH44SBelDMNP4TcN35IUm1OtE + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/b5c7bd55-dcb8-42c5-b7c3-282ccf237f3a + x-ms-ratelimit-remaining-subscription-deletes: + - '799' + x-ms-ratelimit-remaining-subscription-global-deletes: + - '11999' + x-msedge-ref: + - 'Ref A: 9230E94364FF4C3DA95BCBA844BEFE4B Ref B: SYD281080706060 Ref C: 2026-09-21T04:41:14Z' + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr delete + Connection: + - keep-alive + ParameterSetName: + - -n -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-ad708138-b576-11f1-8612-3cefa50a58cc?api-version=2026-09-01-preview&t=639255624753450448&c=MIIHlTCCBn2gAwIBAgIRAN0yZzL8aR42UZysboj3ciowDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgRVVTMiBDQSAwMTAeFw0yNjA4MTQwMDQwMTRaFw0yNzAyMDkwNjQwMTRaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzoSOkVR7MNj87TdZrq2tsL7eEWBZ1UxYUjlHs2t1x6Xn31o-6e5yM1I79Xw17HpG_ZRC01sH0DmLucuBF6EGQR50aTJ6mx22HrEe4YQhQiTieYabApNFEW7C1Z3sqhwTVaWGvV9-nw9anTx1HztS5s2jjMeJoebstq-wBIvYIOyM7hj12vYY5vdXTn9Sask3V8S3KBxdPpOFhQ5pKF6CgT-fQ9-scbzgeKeWuPXZTO0EeH02xAsj1c-lki5VGv0RewzD2beJxGO1-CxJFOfH9H3UnlZMKLg6kT-aBTn6RuYVuLJoMYYC-eHbYtahA3x5r3yutNG8gegIMlLlcdTGAQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQU7naFfTwmNksX70OjHOYQPsR55KIwHwYDVR0jBBgwFoAU_Ow-26p8H4IeBbihBvlD5wKzCrkwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC9lYXN0dXMyL2NybHMvY2NtZWVhc3R1czJwa2kvY2NtZWVhc3R1czJpY2EwMS8zOS9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL2Vhc3R1czIvY3Jscy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxLzM5L2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZWVhc3R1czJwa2kuZWFzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWVlYXN0dXMyaWNhMDEvMzkvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L2Vhc3R1czIvY2FjZXJ0cy9jY21lZWFzdHVzMnBraS9jY21lZWFzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vZWFzdHVzMi9jYWNlcnRzL2NjbWVlYXN0dXMycGtpL2NjbWVlYXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21lZWFzdHVzMnBraS5lYXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZWVhc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAJrRoJWjIzsymA0Vpio4e2hRDOWlG5PpWmWos3Gflt8XcQwRsU-vvdeWk-uT-wHYn52846N5Ue5cbvM8NV-labOA852VL2mtuHnz7bkkRfWTlP-tB-JYDS8l0yGcTENq-UNlakbleLgtfD-Qr09l853jhegiUP3vJKLXMCFF1C2maSNhwZg1MlrEswNSPzRH0Xj9q0-487lH42RncuRXCIqd8ljf1_8v-IXMl6WtDdQDYjQE_s-OHN0BNXt0t4wTd5ikeG6NCH2SHC2wB-PchAiE5P4oHK6Vx3M0q3TEexP11Up6I9ksnpNBw256ZKPa0pX3urxLa215fDhtScA9RzA&s=OZvJ1_qztoF-MC6TjVrQaW0VNC5Dofrxl8KLB56YTEewEUzT55hLY2S1A_hzSjsy5e9d8NlEsKRnDENOp8jQm3Aje1ByKYrNV3bt3QvPdn5-NchXJGj48H5zRTwwRfkS1A9EfDbVcPLNbIwfBDDFBhV19bCh5s5XBZ_gRPNT00hH9d9NPc7BIDdKREhGx5T-o9DWhgF-W-mVqydQeafXSuozPcSZuTUoyEPkOLotgTEWaPIKsXOxW4EbFPyxDCFuVYPIyA4jxoiB9CXiizRPX38qr3ztjUsXZHk8sKpCUP7eUqzWMR4ohy0WkNtd7a0ycvjxp4x574l4HmHCDEY_NA&h=l-ykf5qpe5v5y5SZCEFH44SBelDMNP4TcN35IUm1OtE + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:41:15 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-ad708138-b576-11f1-8612-3cefa50a58cc?api-version=2026-09-01-preview&t=639255624766329565&c=MIIHlTCCBn2gAwIBAgIRAPRMjwgFgYEmfefMzTACKKQwDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgV1VTMiBDQSAwMTAeFw0yNjA4MTQwMDUxMjNaFw0yNzAyMDkwNjUxMjNaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwO_WpR6Xr2lz5oFVtaRK8FiZGg7b-PWeL-Dogy0Cr-qJhUgwo0Hqhe5nZmG2OL7c3CV71c0njXVt4nqBxWLM-CYPCPRB5c_xQ3lWFYnJFuP5lpJcW4uZXUHp8eZTQtInUyLcK0jXbihFpBBxuDm-xtr12Nkoqlx6yfZthAf7X6nB-Nuq26aPqupUCz6hZNjOtE7BUQY499BrTsag1LYCTzXxrkHU9figVwTEB45ZBG40HxC45VUtUdNGtwILcvy145pR4VtdCfskQErR2tLvJYujyFBPwEaJbCjjg2I1v7yWN6nrl1enYFSNx4MBskHhL6EQxWUAfo6IVyV85F9MoQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQUUdq1KVdmsEox8BScI1WzBgBA700wHwYDVR0jBBgwFoAUrONy-gOyc549lcjvh1uu3Ruh7WgwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkxL2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC93ZXN0dXMyL2NybHMvY2NtZXdlc3R1czJwa2kvY2NtZXdlc3R1czJpY2EwMS85MS9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkxL2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZXdlc3R1czJwa2kud2VzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWV3ZXN0dXMyaWNhMDEvOTEvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY2FjZXJ0cy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21ld2VzdHVzMnBraS53ZXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZXdlc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAKcH3XHRFmCqmjLmxABqawQYyIEqlIbq0Ba_dNN6BRkjWSrxWZutW-VgnQV_hVg5p2AtqFKVXKbf9oTaSl3Skd60_jTB_UiVMwJQXe1Lqe_KvIxdSTigB2URtOmQbyJmVQ78A-PH__nQ3si9J4f4_0C8pfMN42X8eIofyFEcaNxOMslJaba_Ber-fVFYnl3Ble7fQL67IV004LBcHkBvnYh2Xdi1sJpCbVSWb8-URtUiV5cbz1KgImEEzn7YTGQksXJCsSxcrGKLboCmWsn8zaUbhd1gA8M4giY8jHxeVXMvNNISFWZYx4OJ5f-B9TGnvWZEGCnf-LAn1ed9ImLRvcA&s=m83btO1cflWs466cpcBtZBhEcGSyzU_owxfxLYhhYvklETNpSGWEhStNeV7atFzI6ON9VlRWLgGBJ_7_saPMbMMT3KegDOUsWzxpfM59VkOTMyuUnKH2D51BO4coXcJhwhm2aFtTr2knYxFfr3Mq0SFlXz17JzWCveox65pMmzF7SIlKcWCBik6lpNxyIQofty8KrsnCNKETbhFlofBWHO2tF3Dm91fNG5HNfX7xTVvf93ItyLjt_ejPjg5ZQo9Xvn_kD7NP1AqGUWmKQOvmrX5gY3ppZhr3z5dfssyefDEdGtGnnBlTGhpXHY3uk9k5ozIWrI1SFARwh7-xu7u3lQ&h=Tg5io5B_LogWcttCln3LPeEzNTKhozG3e56FLY2rZmo + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/c79fa35e-56c2-4c3e-b986-548a14c8de8f + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 91BBEE9EE76A4E66AC0F8304367F4ABD Ref B: SYD281080709034 Ref C: 2026-09-21T04:41:15Z' + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - acr delete + Connection: + - keep-alive + ParameterSetName: + - -n -g -y + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerRegistry/locations/eastus/operationResults/delete-clireg000002-ad708138-b576-11f1-8612-3cefa50a58cc?api-version=2026-09-01-preview&t=639255624766329565&c=MIIHlTCCBn2gAwIBAgIRAPRMjwgFgYEmfefMzTACKKQwDQYJKoZIhvcNAQELBQAwNjE0MDIGA1UEAxMrQ0NNRSBHMSBUTFMgUlNBIDIwNDggU0hBMjU2IDIwNDkgV1VTMiBDQSAwMTAeFw0yNjA4MTQwMDUxMjNaFw0yNzAyMDkwNjUxMjNaMEAxPjA8BgNVBAMTNWFzeW5jb3BlcmF0aW9uc2lnbmluZ2NlcnRpZmljYXRlLm1hbmFnZW1lbnQuYXp1cmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwO_WpR6Xr2lz5oFVtaRK8FiZGg7b-PWeL-Dogy0Cr-qJhUgwo0Hqhe5nZmG2OL7c3CV71c0njXVt4nqBxWLM-CYPCPRB5c_xQ3lWFYnJFuP5lpJcW4uZXUHp8eZTQtInUyLcK0jXbihFpBBxuDm-xtr12Nkoqlx6yfZthAf7X6nB-Nuq26aPqupUCz6hZNjOtE7BUQY499BrTsag1LYCTzXxrkHU9figVwTEB45ZBG40HxC45VUtUdNGtwILcvy145pR4VtdCfskQErR2tLvJYujyFBPwEaJbCjjg2I1v7yWN6nrl1enYFSNx4MBskHhL6EQxWUAfo6IVyV85F9MoQIDAQABo4IEkjCCBI4wgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB_wQEAwIFoDAdBgNVHQ4EFgQUUdq1KVdmsEox8BScI1WzBgBA700wHwYDVR0jBBgwFoAUrONy-gOyc549lcjvh1uu3Ruh7WgwggGyBgNVHR8EggGpMIIBpTBpoGegZYZjaHR0cDovL3ByaW1hcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkxL2N1cnJlbnQuY3JsMGugaaBnhmVodHRwOi8vc2Vjb25kYXJ5LWNkbi5wa2kuY29yZS53aW5kb3dzLm5ldC93ZXN0dXMyL2NybHMvY2NtZXdlc3R1czJwa2kvY2NtZXdlc3R1czJpY2EwMS85MS9jdXJyZW50LmNybDBaoFigVoZUaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3dlc3R1czIvY3Jscy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxLzkxL2N1cnJlbnQuY3JsMG-gbaBrhmlodHRwOi8vY2NtZXdlc3R1czJwa2kud2VzdHVzMi5wa2kuY29yZS53aW5kb3dzLm5ldC9jZXJ0aWZpY2F0ZUF1dGhvcml0aWVzL2NjbWV3ZXN0dXMyaWNhMDEvOTEvY3VycmVudC5jcmwwggG3BggrBgEFBQcBAQSCAakwggGlMGwGCCsGAQUFBzAChmBodHRwOi8vcHJpbWFyeS1jZG4ucGtpLmNvcmUud2luZG93cy5uZXQvd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwbgYIKwYBBQUHMAKGYmh0dHA6Ly9zZWNvbmRhcnktY2RuLnBraS5jb3JlLndpbmRvd3MubmV0L3dlc3R1czIvY2FjZXJ0cy9jY21ld2VzdHVzMnBraS9jY21ld2VzdHVzMmljYTAxL2NlcnQuY2VyMF0GCCsGAQUFBzAChlFodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vd2VzdHVzMi9jYWNlcnRzL2NjbWV3ZXN0dXMycGtpL2NjbWV3ZXN0dXMyaWNhMDEvY2VydC5jZXIwZgYIKwYBBQUHMAKGWmh0dHA6Ly9jY21ld2VzdHVzMnBraS53ZXN0dXMyLnBraS5jb3JlLndpbmRvd3MubmV0L2NlcnRpZmljYXRlQXV0aG9yaXRpZXMvY2NtZXdlc3R1czJpY2EwMTANBgkqhkiG9w0BAQsFAAOCAQEAKcH3XHRFmCqmjLmxABqawQYyIEqlIbq0Ba_dNN6BRkjWSrxWZutW-VgnQV_hVg5p2AtqFKVXKbf9oTaSl3Skd60_jTB_UiVMwJQXe1Lqe_KvIxdSTigB2URtOmQbyJmVQ78A-PH__nQ3si9J4f4_0C8pfMN42X8eIofyFEcaNxOMslJaba_Ber-fVFYnl3Ble7fQL67IV004LBcHkBvnYh2Xdi1sJpCbVSWb8-URtUiV5cbz1KgImEEzn7YTGQksXJCsSxcrGKLboCmWsn8zaUbhd1gA8M4giY8jHxeVXMvNNISFWZYx4OJ5f-B9TGnvWZEGCnf-LAn1ed9ImLRvcA&s=m83btO1cflWs466cpcBtZBhEcGSyzU_owxfxLYhhYvklETNpSGWEhStNeV7atFzI6ON9VlRWLgGBJ_7_saPMbMMT3KegDOUsWzxpfM59VkOTMyuUnKH2D51BO4coXcJhwhm2aFtTr2knYxFfr3Mq0SFlXz17JzWCveox65pMmzF7SIlKcWCBik6lpNxyIQofty8KrsnCNKETbhFlofBWHO2tF3Dm91fNG5HNfX7xTVvf93ItyLjt_ejPjg5ZQo9Xvn_kD7NP1AqGUWmKQOvmrX5gY3ppZhr3z5dfssyefDEdGtGnnBlTGhpXHY3uk9k5ozIWrI1SFARwh7-xu7u3lQ&h=Tg5io5B_LogWcttCln3LPeEzNTKhozG3e56FLY2rZmo + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:41:27 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/australiaeast/9095003b-b4f2-408a-b0ac-43e6ea44ff64 + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 0C1B3DAAF40D4D1AA99A84A8487B2CA7 Ref B: SYD281080707025 Ref C: 2026-09-21T04:41:27Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - identity delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -n -g + User-Agent: + - AZURECLI/2.90.0 azsdk-python-core/1.39.0 Python/3.13.15 (Windows-11-10.0.26100-SP0) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cr-mi-id000003?api-version=2025-05-31-preview + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + date: + - Mon, 21 Sep 2026 04:41:31 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=4b5b0cef-cf82-4cf5-9ab1-ff84c9f11f35/eastus/b034e8eb-29ce-434a-aa88-4759b8a04a0b + x-ms-ratelimit-remaining-subscription-deletes: + - '799' + x-ms-ratelimit-remaining-subscription-global-deletes: + - '11999' + x-msedge-ref: + - 'Ref A: 3BA520F5C1C848E4B37DD41A821C97DA Ref B: SYD281080712036 Ref C: 2026-09-21T04:41:28Z' + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py index 22071aa5453..bda38b6b5ae 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py @@ -301,3 +301,88 @@ def test_acr_connectedregistry_managed_identity(self): self.cmd('acr delete -n {registry_name} -g {rg} -y') # Shared RG: clean up the user-assigned identity too. self.cmd('identity delete --name {identity_name} -g {rg}') + + @ResourceGroupPreparer(location='eastus') + @AllowLargeResponse(size_kb=99999) + def test_acr_connectedregistry_managed_identity_migration(self, resource_group_location): + self.kwargs.update({ + 'registry_name': self.create_random_name('clireg', 20), + 'cr_name': 'crmigration', + 'identity_name': self.create_random_name('cr-mi-id', 20), + 'rg_loc': resource_group_location, + 'repository': 'hello-world', + 'sync_schedule': '0 0/10 * * *', + 'notification': 'hello-world:tag:push', + }) + + self.cmd('acr create -n {registry_name} -g {rg} -l {rg_loc} --sku Premium ' + '--role-assignment-mode rbac-abac', + checks=[self.check('provisioningState', 'Succeeded'), + self.check('roleAssignmentMode', 'AbacRepositoryPermissions')]) + self.cmd('acr update -n {registry_name} -g {rg} --data-endpoint-enabled true', + checks=[self.check('dataEndpointEnabled', True), + self.check('roleAssignmentMode', 'AbacRepositoryPermissions')]) + + identity = self.cmd('identity create -n {identity_name} -g {rg} -l {rg_loc}').get_output_in_json() + self.kwargs['identity_id'] = identity['id'] + + self.cmd('acr connected-registry create -n {cr_name} -r {registry_name} -g {rg} ' + '--mode ReadOnly --auth-type SyncToken --repository {repository} --log-level Warning ' + '--sync-schedule "{sync_schedule}" --sync-window PT4H ' + '--notifications {notification} --gc-enabled false') + + # No agent is started, so the new registry is already offline and needs no deactivation. + before = self.cmd( + 'acr connected-registry show -n {cr_name} -r {registry_name} -g {rg}', + checks=[self.check('name', '{cr_name}'), + self.check('mode', 'ReadOnly'), + self.check('provisioningState', 'Succeeded'), + self.check('connectionState', 'Offline'), + self.check('activation.status', 'Inactive'), + self.check('parent.syncProperties.authType', 'SyncToken'), + self.exists('parent.syncProperties.tokenId'), + self.check('logging.logLevel', 'Warning'), + self.check('parent.syncProperties.schedule', '{sync_schedule}'), + self.check('parent.syncProperties.syncWindow', '4:00:00'), + self.check('notificationsList[0]', '{notification}'), + self.check('garbageCollection.enabled', False)]).get_output_in_json() + + self.cmd('acr connected-registry update -n {cr_name} -r {registry_name} -g {rg} ' + '--auth-type ManagedIdentity --identity {identity_id}', + checks=[self.check('provisioningState', 'Succeeded'), + self.check('parent.syncProperties.authType', 'ManagedIdentity')]) + + after = self.cmd( + 'acr connected-registry show -n {cr_name} -r {registry_name} -g {rg}', + checks=[self.check('provisioningState', 'Succeeded'), + self.check('connectionState', 'Offline'), + self.check('parent.syncProperties.authType', 'ManagedIdentity'), + self.check('identity.type', 'userAssigned', case_sensitive=False)]).get_output_in_json() + + assigned_identities = after['identity']['userAssignedIdentities'] + self.assertEqual({resource_id.lower() for resource_id in assigned_identities}, + {identity['id'].lower()}) + self.assertEqual(next(iter(assigned_identities.values()))['clientId'], identity['clientId']) + + for property_name in ('id', 'name', 'mode', 'logging', 'notificationsList', 'garbageCollection'): + self.assertEqual(after[property_name], before[property_name], property_name) + self.assertEqual(after['parent'].get('id'), before['parent'].get('id')) + for property_name in ('schedule', 'syncWindow', 'messageTtl'): + self.assertEqual(after['parent']['syncProperties'][property_name], + before['parent']['syncProperties'][property_name], property_name) + + settings = self.cmd( + 'acr connected-registry get-settings -n {cr_name} -r {registry_name} -g {rg} ' + '--parent-protocol https').get_output_in_json() + connection_string = settings['ACR_REGISTRY_CONNECTION_STRING'] + self.assertIn('ManagedIdentityClientId={};'.format(identity['clientId']), connection_string) + self.assertNotIn('SyncTokenName=', connection_string) + self.assertNotIn('SyncTokenPassword=', connection_string) + self.assertNotIn('SYNC_TOKEN_USER', settings) + self.assertNotIn('SYNC_TOKEN_PASSWORD', settings) + + self.cmd('acr connected-registry delete -n {cr_name} -r {registry_name} -g {rg} --cleanup -y') + self.cmd('identity show -n {identity_name} -g {rg}', + checks=self.check('clientId', identity['clientId'])) + self.cmd('acr delete -n {registry_name} -g {rg} -y') + self.cmd('identity delete -n {identity_name} -g {rg}') From b6b39cfe037a5eaec475259aec502e6f5f4fa0f8 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Mon, 21 Sep 2026 14:47:56 +1000 Subject: [PATCH 09/16] fix --- .../azure/cli/command_modules/acr/connected_registry.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index e5aa629f1cf..9487083edd5 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -622,7 +622,6 @@ def acr_connected_registry_get_settings(cmd, # pylint: disable=too-many-locals raise CLIError( "Connected registry '{}' is in ManagedIdentity mode but no user-assigned identity is " "attached.".format(connected_registry_name)) - # exactly one user-assigned identity is expected. msi_resource_id, msi = next(iter(user_assigned.items())) client_id = getattr(msi, 'client_id', None) From cf618d89152e7759a131923c78d0d0b610dfca7b Mon Sep 17 00:00:00 2001 From: nihalvar Date: Mon, 21 Sep 2026 16:19:10 +1000 Subject: [PATCH 10/16] update migration instructions for connected registry Clarify migration prerequisites for connected registry. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/azure-cli/azure/cli/command_modules/acr/_help.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/_help.py b/src/azure-cli/azure/cli/command_modules/acr/_help.py index 4188d41dde7..af553187b11 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_help.py @@ -1713,7 +1713,7 @@ long-summary: | Only one-way migration from SyncToken to ManagedIdentity authentication is supported. The service validates migration eligibility, including the required Offline state. - Run `az acr connected-registry deactivate` before invoking the migration. + Ensure the connected registry is Offline/Inactive before invoking the migration; run `az acr connected-registry deactivate` first only if it is currently Online/Active. examples: - name: Update the connected registry client Tokens. text: | From 5d369243928fbd1d33641b609148811bc03af987 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Wed, 23 Sep 2026 16:59:15 +1000 Subject: [PATCH 11/16] update help --- src/azure-cli/azure/cli/command_modules/acr/_params.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/_params.py b/src/azure-cli/azure/cli/command_modules/acr/_params.py index 439965e0871..bf81388be89 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_params.py @@ -565,12 +565,12 @@ def load_arguments(self, _): # pylint: disable=too-many-statements c.argument('parent_name', options_list=['--parent', '-p'], help='The name of the parent connected registry.') c.argument('repositories', options_list=['--repository'], nargs='+', help='Specify the repositories that need to be sync to the connected registry. It can be in the format [REPO01] [REPO02]...') c.argument('sync_token_name', options_list=['--sync-token'], help='Specifies the sync token used to synchronize the connected registry with its parent. It most have only repo permissions and at least the actions required for its mode. It can include access for multiple repositories.') - c.argument('cleanup', help='Delete the sync token and scope map resources for SyncToken authentication. No effect for ManagedIdentity authentication; the managed identity and role assignments are not deleted.') + c.argument('cleanup', help='Delete the associated sync token and scope map for a connected registry configured with SyncToken authentication. This option has no effect for a connected registry configured with ManagedIdentity authentication. The connected registry is still deleted, but the managed identity and role assignments are retained.') c.argument('no_children', help='Used to remove all children from the list.', action='store_true') c.argument('sync_audit_logs_enabled', options_list=['--audit-logs-enabled'], help='Indicate whether audit log synchronization is enabled. It is enabled by default.', required=False, arg_type=get_three_state_flag(), deprecate_info=c.deprecate(hide=True)) c.argument('parent_protocol', arg_type=get_enum_type(['http', 'https']), options_list=['--parent-protocol'], help='Specify the protocol used to communicate with its parent.', required=True) - c.argument('generate_password', arg_type=get_enum_type(['1', '2']), options_list=['--generate-password'], help='Select which password you want to generate, and it is required to retrieve the password from the sync token. Not supported with ManagedIdentity authentication.') + c.argument('generate_password', arg_type=get_enum_type(['1', '2']), options_list=['--generate-password'], help='Select which password you want to generate, and it is required to retrieve the password from the sync token. Not supported for a connected registry configured with ManagedIdentity authentication.') with self.argument_context('acr connected-registry create') as c: c.argument('log_level', help='Set the log level for logging on the instance. Accepted log levels are Debug, Information, Warning, Error, and None.', required=False, default="Information") @@ -604,7 +604,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements help='Indicate whether garbage collection is enabled. It is enabled by default.', arg_type=get_three_state_flag()) c.argument('garbage_collection_schedule', options_list=['--gc-schedule'], help='Used to determine garbage collection schedule. Uses cron expression to determine the schedule. If not specified, garbage collection is set to run once a day.') c.argument('identity', help='Resource ID of a user-assigned managed identity. Requires --auth-type ManagedIdentity.') - c.argument('auth_type', arg_type=get_enum_type([ConnectedRegistryAuthType.MANAGED_IDENTITY.value]), options_list=['--auth-type'], help='Target authentication type. Only one-way migration from SyncToken to ManagedIdentity is supported. The service validates migration eligibility, including the required Offline state.') + c.argument('auth_type', arg_type=get_enum_type([ConnectedRegistryAuthType.MANAGED_IDENTITY.value]), options_list=['--auth-type'], help='Target authentication type. Only one-way migration from SyncToken to ManagedIdentity is supported.') with self.argument_context('acr connected-registry permissions') as c: c.argument('add_repos', options_list=['--add'], nargs='*', help='repository permissions to be added to the targeted connected registry and it\'s ancestors sync scope maps. Use the format "--add [REPO1 REPO2 ...]" per flag. ' + repo_valid_actions) From 7d2871aafd658f1c6aa2d9d033e5353cc07b5444 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Wed, 23 Sep 2026 16:59:42 +1000 Subject: [PATCH 12/16] connected-registry update long summary --- src/azure-cli/azure/cli/command_modules/acr/_help.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/_help.py b/src/azure-cli/azure/cli/command_modules/acr/_help.py index af553187b11..d3dfddc740a 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_help.py @@ -1712,8 +1712,8 @@ short-summary: Update a connected registry for an Azure Container Registry. long-summary: | Only one-way migration from SyncToken to ManagedIdentity authentication is supported. - The service validates migration eligibility, including the required Offline state. - Ensure the connected registry is Offline/Inactive before invoking the migration; run `az acr connected-registry deactivate` first only if it is currently Online/Active. + The connected registry must have an Offline connection state before migration. If it is Online, run `az acr connected-registry deactivate` and wait until it is Offline. + Changing the managed identity of a connected registry already using ManagedIdentity authentication is not supported. examples: - name: Update the connected registry client Tokens. text: | From b4a6a390edaf670a0d2260674649d1cace82a40d Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Wed, 23 Sep 2026 16:59:58 +1000 Subject: [PATCH 13/16] address comments --- .../command_modules/acr/connected_registry.py | 45 ++++-- .../test_acr_connected_registry_mi_unit.py | 134 ++++++++++-------- .../test_acr_connectedregistry_commands.py | 3 + 3 files changed, 111 insertions(+), 71 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index 9487083edd5..c5c754c00d1 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -11,7 +11,7 @@ from azure.cli.core.commands import LongRunningOperation from azure.cli.core.commands.client_factory import get_subscription_id from azure.cli.core.util import user_confirmation -from azure.mgmt.containerregistry.models import ManagedServiceIdentityType +from azure.mgmt.containerregistry.models import ConnectionState, ManagedServiceIdentityType from ._client_factory import cf_acr_tokens, cf_acr_scope_maps, cf_acr_registries from ._constants import ConnectedRegistryAuthType from ._utils import ( @@ -46,6 +46,7 @@ class ConnectedRegistryModes(Enum): AUTH_TYPE_SYNC_TOKEN = ConnectedRegistryAuthType.SYNC_TOKEN.value AUTH_TYPE_MANAGED_IDENTITY = ConnectedRegistryAuthType.MANAGED_IDENTITY.value MSI_TYPE_USER_ASSIGNED = ManagedServiceIdentityType.USER_ASSIGNED.value +CONNECTION_STATE_OFFLINE = ConnectionState.OFFLINE.value def _get_current_auth_type(connected_registry): @@ -123,6 +124,16 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m subscription_id = get_subscription_id(cmd.cli_ctx) registry, resource_group_name = get_registry_by_name(cmd.cli_ctx, registry_name, resource_group_name) + if not registry.data_endpoint_enabled: + user_confirmation("Dedicated data endpoints must be enabled to use connected-registry. Enabling might " + + "impact your firewall rules. Are you sure you want to enable it for '{}' registry?".format( + registry_name), yes) + acr_update_custom(cmd, registry, data_endpoint_enabled=True) + registry_client = cf_acr_registries(cmd.cli_ctx) + LongRunningOperation(cmd.cli_ctx)( + acr_update_set(cmd, registry_client, registry_name, resource_group_name, registry) + ) + from azure.core.exceptions import HttpResponseError as ErrorResponseException parent = None mode = mode.lower() @@ -146,18 +157,6 @@ def acr_connected_registry_create(cmd, # pylint: disable=too-many-locals, too-m "when the connected registry parent '{}' mode is '{}'. ".format(parent_name, parent.mode) + "For more information on connected registries " + "please visit https://aka.ms/acr/connected-registry.") - - if not registry.data_endpoint_enabled: - user_confirmation("Dedicated data endpoints must be enabled to use connected-registry. Enabling might " + - "impact your firewall rules. Are you sure you want to enable it for '{}' registry?".format( - registry_name), yes) - acr_update_custom(cmd, registry, data_endpoint_enabled=True) - registry_client = cf_acr_registries(cmd.cli_ctx) - LongRunningOperation(cmd.cli_ctx)( - acr_update_set(cmd, registry_client, registry_name, resource_group_name, registry) - ) - - if parent_name: _update_ancestor_permissions(cmd, family_tree, resource_group_name, registry_name, parent.id, connected_registry_name, repositories, mode, False) @@ -257,6 +256,20 @@ def acr_connected_registry_update(cmd, # pylint: disable=too-many-locals, too-m "argument error: a non-empty --identity is required " "when migrating to --auth-type ManagedIdentity." ) + if _get_current_auth_type(current_connected_registry) == AUTH_TYPE_MANAGED_IDENTITY: + raise ArgumentUsageError( + "Connected registry is already using 'ManagedIdentity' authentication. " + "Same-mode credential rotation is not supported." + ) + current_state = getattr(current_connected_registry, 'connection_state', None) + current_state = getattr(current_state, 'value', current_state) + if current_state != CONNECTION_STATE_OFFLINE: + raise ArgumentUsageError( + "Connected registry must be in '{}' state to migrate authentication mode. " + "Current state is '{}'. Deactivate it first with " + "'az acr connected-registry deactivate' and wait until it is Offline.".format( + CONNECTION_STATE_OFFLINE, current_state) + ) identity_update = _build_user_assigned_identity(cmd, identity) sync_auth_type_update = AUTH_TYPE_MANAGED_IDENTITY @@ -361,6 +374,10 @@ def acr_connected_registry_delete(cmd, cmd, client, connected_registry_name, registry_name, resource_group_name) result = client.begin_delete(resource_group_name, registry_name, connected_registry_name).result() if _get_current_auth_type(connected_registry) == AUTH_TYPE_MANAGED_IDENTITY: + if cleanup: + logger.warning( + "'--cleanup' has no effect for connected registry '%s' using ManagedIdentity authentication. " + "The managed identity and role assignments are retained.", connected_registry_name) return result sync_token = get_token_from_id(cmd, connected_registry.parent.sync_properties.token_id) sync_token_name = sync_token.name @@ -636,7 +653,7 @@ def acr_connected_registry_get_settings(cmd, # pylint: disable=too-many-locals parent_gateway_endpoint, parent_endpoint_protocol, auth_connection_fragment="ManagedIdentityClientId={};".format(client_id), - auth_env={}, + auth_env={"ACR_MANAGED_IDENTITY_RESOURCE_ID": msi_resource_id}, ) sync_token_name = connected_registry.parent.sync_properties.token_id.split('/tokens/')[1] diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py index 3e689ad2cf6..f428ba6fc35 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -223,30 +223,6 @@ def test_mi_rejects_parent_before_registry_lookup(self): get_registry.assert_not_called() get_subscription.assert_not_called() - def test_mi_parent_rejected_before_mutations(self): - parent = _fake_cr(has_identity=True) - client = mock.MagicMock() - registry = mock.MagicMock(data_endpoint_enabled=False) - with mock.patch(UPDATE_MODULE + '.get_subscription_id', return_value=TEST_SUB), \ - mock.patch(UPDATE_MODULE + '.get_registry_by_name', return_value=(registry, TEST_RG)), \ - mock.patch(UPDATE_MODULE + '.acr_connected_registry_show', return_value=parent) as show, \ - mock.patch(UPDATE_MODULE + '.acr_update_custom') as update_registry, \ - mock.patch(UPDATE_MODULE + '.acr_update_set') as set_registry, \ - mock.patch(UPDATE_MODULE + '._create_sync_token') as create_token, \ - mock.patch(UPDATE_MODULE + '._update_ancestor_permissions') as update_permissions: - for auth_type in (None, AUTH_TYPE_SYNC_TOKEN, AUTH_TYPE_MANAGED_IDENTITY): - with self.subTest(auth_type=auth_type), self.assertRaises(ArgumentUsageError): - options = {'identity': TEST_MSI_ID} if auth_type == AUTH_TYPE_MANAGED_IDENTITY else { - 'repositories': ['r1']} - self._create(client=client, parent_name='parentcr', auth_type=auth_type, **options) - self.assertEqual(show.call_count, 2) - client.list.assert_not_called() - client.begin_create.assert_not_called() - update_registry.assert_not_called() - set_registry.assert_not_called() - create_token.assert_not_called() - update_permissions.assert_not_called() - class TestConnectedRegistryCreatePayload(unittest.TestCase): @@ -370,7 +346,30 @@ def test_mi_delete_skips_token_cleanup(self): delete_scope.assert_not_called() family_tree.assert_not_called() update_permissions.assert_not_called() - warning.assert_not_called() + if cleanup: + warning.assert_called_once_with( + "'--cleanup' has no effect for connected registry '%s' using " + "ManagedIdentity authentication. The managed identity and role assignments " + "are retained.", TEST_CR) + else: + warning.assert_not_called() + + def test_mi_failed_delete_does_not_report_cleanup_success(self): + cr = _fake_cr(has_identity=True) + client = mock.MagicMock() + client.get.return_value = cr + error = HttpResponseError(message='Connected registry deletion failed.') + client.begin_delete.return_value.result.side_effect = error + with mock.patch(UPDATE_MODULE + '.validate_managed_registry', return_value=(None, TEST_RG)), \ + mock.patch(UPDATE_MODULE + '.user_confirmation'), \ + mock.patch(UPDATE_MODULE + '.get_token_from_id') as token_lookup, \ + mock.patch(UPDATE_MODULE + '.logger.warning') as warning: + with self.assertRaises(HttpResponseError) as caught: + acr_connected_registry_delete( + _make_cmd(), client, TEST_CR, TEST_REGISTRY, cleanup=True, yes=True, resource_group_name=TEST_RG) + self.assertIs(caught.exception, error) + token_lookup.assert_not_called() + warning.assert_not_called() def test_sync_token_delete_preserves_cleanup_and_warning(self): token_id = ( @@ -520,23 +519,33 @@ def test_identity_without_auth_type_errors(self): self._run_update(cur, client=client, identity=identity) client.begin_update.assert_not_called() - def test_migration_eligibility_errors_are_deferred_to_rp(self): - for auth_type, state, identity in ( - (AUTH_TYPE_SYNC_TOKEN, 'Online', TEST_MSI_ID), - (AUTH_TYPE_MANAGED_IDENTITY, 'Offline', TEST_MSI_ID2), - (AUTH_TYPE_MANAGED_IDENTITY, 'Offline', TEST_MSI_ID)): - with self.subTest(auth_type=auth_type, state=state, identity=identity): - cur = _fake_cr(auth_type=auth_type, - has_identity=auth_type == AUTH_TYPE_MANAGED_IDENTITY, - connection_state=state) + def test_migration_rejects_existing_managed_identity(self): + for identity in (TEST_MSI_ID, TEST_MSI_ID2): + with self.subTest(identity=identity): + cur = _fake_cr(has_identity=True, connection_state='Offline') client = mock.MagicMock() - error = HttpResponseError(message='The requested migration is not allowed.') - client.begin_update.side_effect = error - with self.assertRaises(HttpResponseError) as caught: + with self.assertRaisesRegex(ArgumentUsageError, "already using 'ManagedIdentity'"): self._run_update(cur, client=client, auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=identity) - self.assertIs(caught.exception, error) - client.begin_update.assert_called_once() - client.list.assert_not_called() + client.begin_update.assert_not_called() + + def test_migration_requires_offline_connection_state(self): + for state in ('Online', models.ConnectionState.ONLINE, None): + with self.subTest(state=state): + cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN, connection_state=state) + client = mock.MagicMock() + with self.assertRaisesRegex(ArgumentUsageError, "must be in 'Offline' state"): + self._run_update(cur, client=client, auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=TEST_MSI_ID) + client.begin_update.assert_not_called() + + def test_migration_service_errors_propagate_after_local_validation(self): + cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN, connection_state='Offline') + client = mock.MagicMock() + error = HttpResponseError(message='The requested migration is not allowed.') + client.begin_update.side_effect = error + with self.assertRaises(HttpResponseError) as caught: + self._run_update(cur, client=client, auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=TEST_MSI_ID) + self.assertIs(caught.exception, error) + client.begin_update.assert_called_once() def test_migrate_to_mi_requires_identity(self): cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN) @@ -564,21 +573,19 @@ def _extract_update_body(self, client): return kwargs['connected_registry_update_parameters'] def test_migrate_sync_token_to_mi_sends_identity(self): - cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN, connection_state='Offline') - client = self._run_update(cur, auth_type=AUTH_TYPE_MANAGED_IDENTITY, - identity=TEST_MSI_ID) - body = self._extract_update_body(client) - self.assertIsNotNone(body.identity) - self.assertEqual(body.identity.type, MSI_TYPE_USER_ASSIGNED) - self.assertIn(TEST_MSI_ID, body.identity.user_assigned_identities) - self.assertEqual(body.sync_properties.auth_type, AUTH_TYPE_MANAGED_IDENTITY) - serialized = body.as_dict() - self.assertEqual(serialized['identity'], { - 'type': 'UserAssigned', 'userAssignedIdentities': {TEST_MSI_ID: {}}}) - self.assertEqual(serialized['properties']['syncProperties'], { - 'authType': AUTH_TYPE_MANAGED_IDENTITY}) - self.assertNotIn('parent', serialized['properties']) - self.assertNotIn('tokenId', serialized['properties']['syncProperties']) + for auth_type, state in ( + (None, 'Offline'), + (AUTH_TYPE_SYNC_TOKEN, 'Offline'), + (models.AuthType.SYNC_TOKEN, models.ConnectionState.OFFLINE)): + with self.subTest(auth_type=auth_type, state=state): + cur = _fake_cr(auth_type=auth_type, connection_state=state) + client = self._run_update(cur, auth_type=AUTH_TYPE_MANAGED_IDENTITY, identity=TEST_MSI_ID) + serialized = self._extract_update_body(client).as_dict() + self.assertEqual(serialized['identity'], { + 'type': 'UserAssigned', 'userAssignedIdentities': {TEST_MSI_ID: {}}}) + self.assertEqual(serialized['properties']['syncProperties'], { + 'authType': AUTH_TYPE_MANAGED_IDENTITY}) + self.assertNotIn('parent', serialized['properties']) def test_migration_combines_with_ordinary_property_updates(self): cur = _fake_cr(auth_type=AUTH_TYPE_SYNC_TOKEN, connection_state='Offline') @@ -679,7 +686,20 @@ def test_happy_path_returns_mi_connection_string(self): self.assertNotIn('SYNC_TOKEN_USER', result) self.assertNotIn('SYNC_TOKEN_PASSWORD', result) self.assertNotIn('ACR_MANAGED_IDENTITY_CLIENT_ID', result) - self.assertNotIn('ACR_MANAGED_IDENTITY_RESOURCE_ID', result) + self.assertEqual(result['ACR_MANAGED_IDENTITY_RESOURCE_ID'], TEST_MSI_ID) + + def test_migrated_settings_report_attached_identity_despite_stale_token(self): + cr = _fake_cr(auth_type=models.AuthType.MANAGED_IDENTITY, has_identity=True, + token_id='/tokens/old-sync', client_id='cid-migrated') + cr.identity.user_assigned_identities = { + TEST_MSI_ID2: cr.identity.user_assigned_identities[TEST_MSI_ID]} + result = self._invoke(cr) + self.assertEqual(result['ACR_MANAGED_IDENTITY_RESOURCE_ID'], TEST_MSI_ID2) + self.assertIn('ManagedIdentityClientId=cid-migrated;', result['ACR_REGISTRY_CONNECTION_STRING']) + self.assertNotIn(TEST_MSI_ID2, result['ACR_REGISTRY_CONNECTION_STRING']) + self.assertNotIn('SyncToken', result['ACR_REGISTRY_CONNECTION_STRING']) + self.assertNotIn('SYNC_TOKEN_USER', result) + self.assertNotIn('SYNC_TOKEN_PASSWORD', result) def test_source_settings_use_get_without_token_or_credential_calls(self): cr = _fake_cr(has_identity=True, client_id='cid-happy') @@ -703,8 +723,8 @@ def test_source_settings_use_get_without_token_or_credential_calls(self): cred_factory.assert_not_called() generate.assert_not_called() confirm.assert_not_called() - # Preserve the pinned source format (including its request name), not a verified spec contract. self.assertEqual(result, { + 'ACR_MANAGED_IDENTITY_RESOURCE_ID': TEST_MSI_ID, 'ACR_REGISTRY_CERTIFICATE_VOLUME': '/var/acr/certs', 'ACR_REGISTRY_DATA_VOLUME': '/var/acr/data', 'ACR_REGISTRY_CONNECTION_STRING': ( diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py index bda38b6b5ae..8004ee2d91a 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connectedregistry_commands.py @@ -295,6 +295,8 @@ def test_acr_connectedregistry_managed_identity(self): self.assertNotIn('SyncTokenPassword=', connection_string) self.assertNotIn('SYNC_TOKEN_USER', settings) self.assertNotIn('SYNC_TOKEN_PASSWORD', settings) + self.assertEqual(settings['ACR_MANAGED_IDENTITY_RESOURCE_ID'].lower(), + self.kwargs['identity_id'].lower()) # --- MI-mode delete (no sync token / scope map cleanup path) --- self.cmd('acr connected-registry delete -n {cr_mi_name} -r {registry_name} -g {rg} -y') @@ -380,6 +382,7 @@ def test_acr_connectedregistry_managed_identity_migration(self, resource_group_l self.assertNotIn('SyncTokenPassword=', connection_string) self.assertNotIn('SYNC_TOKEN_USER', settings) self.assertNotIn('SYNC_TOKEN_PASSWORD', settings) + self.assertEqual(settings['ACR_MANAGED_IDENTITY_RESOURCE_ID'].lower(), identity['id'].lower()) self.cmd('acr connected-registry delete -n {cr_name} -r {registry_name} -g {rg} --cleanup -y') self.cmd('identity show -n {identity_name} -g {rg}', From b1aa745867022619391e40b657b54bfd89952f27 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Thu, 24 Sep 2026 09:59:43 +1000 Subject: [PATCH 14/16] fix --- .../azure/cli/command_modules/acr/connected_registry.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index c5c754c00d1..4cfb18505b4 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -364,11 +364,9 @@ def acr_connected_registry_delete(cmd, resource_group_name=None): _, resource_group_name = validate_managed_registry( cmd, registry_name, resource_group_name) - extraMsg = "" - if not cleanup: - extraMsg = " without cleanup flag enabled" - user_confirmation("Are you sure you want to delete the connected registry '{}' in '{}'{}?".format( - connected_registry_name, registry_name, extraMsg), yes) + + user_confirmation("Are you sure you want to delete the connected registry '{}' in '{}'?".format( + connected_registry_name, registry_name), yes) try: connected_registry = acr_connected_registry_show( cmd, client, connected_registry_name, registry_name, resource_group_name) From 7d0a13d579146d8cd0533bcf3486a8028f76dfe1 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Thu, 24 Sep 2026 10:45:20 +1000 Subject: [PATCH 15/16] tests: remove "without cleanup flag enabled" --- .../tests/latest/test_acr_connected_registry_mi_unit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py index f428ba6fc35..42a295cf55c 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -336,8 +336,8 @@ def test_mi_delete_skips_token_cleanup(self): mock.call.begin_delete().result(), ]) confirm.assert_called_once_with( - "Are you sure you want to delete the connected registry '{}' in '{}'{}?".format( - TEST_CR, TEST_REGISTRY, '' if cleanup else ' without cleanup flag enabled'), False) + "Are you sure you want to delete the connected registry '{}' in '{}'?".format( + TEST_CR, TEST_REGISTRY), False) token_lookup.assert_not_called() scope_lookup.assert_not_called() tokens.assert_not_called() @@ -407,8 +407,8 @@ def test_sync_token_delete_preserves_cleanup_and_warning(self): client.begin_delete.assert_called_once_with(TEST_RG, TEST_REGISTRY, TEST_CR) client.begin_delete.return_value.result.assert_called_once_with() confirm.assert_called_once_with( - "Are you sure you want to delete the connected registry '{}' in '{}'{}?".format( - TEST_CR, TEST_REGISTRY, '' if cleanup else ' without cleanup flag enabled'), True) + "Are you sure you want to delete the connected registry '{}' in '{}'?".format( + TEST_CR, TEST_REGISTRY), True) token_lookup.assert_called_once_with(cmd, token_id) if cleanup: tokens.assert_called_once_with(cmd.cli_ctx) From 11066ad9b83ca8f5b8d359f2e2ebad5192939495 Mon Sep 17 00:00:00 2001 From: Nihal Varadachari Date: Thu, 24 Sep 2026 11:17:38 +1000 Subject: [PATCH 16/16] fix: cleanup extra mssg only enabled for sync token --- .../azure/cli/command_modules/acr/connected_registry.py | 7 +++++-- .../tests/latest/test_acr_connected_registry_mi_unit.py | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py index 4cfb18505b4..7dc5ca6cb05 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py +++ b/src/azure-cli/azure/cli/command_modules/acr/connected_registry.py @@ -365,11 +365,14 @@ def acr_connected_registry_delete(cmd, _, resource_group_name = validate_managed_registry( cmd, registry_name, resource_group_name) - user_confirmation("Are you sure you want to delete the connected registry '{}' in '{}'?".format( - connected_registry_name, registry_name), yes) try: connected_registry = acr_connected_registry_show( cmd, client, connected_registry_name, registry_name, resource_group_name) + extra_msg = "" + if not cleanup and _get_current_auth_type(connected_registry) == AUTH_TYPE_SYNC_TOKEN: + extra_msg = " without cleanup flag enabled" + user_confirmation("Are you sure you want to delete the connected registry '{}' in '{}'{}?".format( + connected_registry_name, registry_name, extra_msg), yes) result = client.begin_delete(resource_group_name, registry_name, connected_registry_name).result() if _get_current_auth_type(connected_registry) == AUTH_TYPE_MANAGED_IDENTITY: if cleanup: diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py index 42a295cf55c..11ec19c5b7f 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_connected_registry_mi_unit.py @@ -407,8 +407,8 @@ def test_sync_token_delete_preserves_cleanup_and_warning(self): client.begin_delete.assert_called_once_with(TEST_RG, TEST_REGISTRY, TEST_CR) client.begin_delete.return_value.result.assert_called_once_with() confirm.assert_called_once_with( - "Are you sure you want to delete the connected registry '{}' in '{}'?".format( - TEST_CR, TEST_REGISTRY), True) + "Are you sure you want to delete the connected registry '{}' in '{}'{}?".format( + TEST_CR, TEST_REGISTRY, '' if cleanup else ' without cleanup flag enabled'), True) token_lookup.assert_called_once_with(cmd, token_id) if cleanup: tokens.assert_called_once_with(cmd.cli_ctx)