Skip to content

Commit 9ab1c4b

Browse files
committed
Merge branch 'dev' into trisavo/dnl-warnings
2 parents 84a96bd + 77ce1bb commit 9ab1c4b

239 files changed

Lines changed: 108428 additions & 74041 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/azure-cli-core/azure/cli/core/auth/binary_cache.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ def load(self):
4242
logger.debug("load: %s", self.filename)
4343
try:
4444
self.data = self._load()
45-
except (pickle.UnpicklingError, EOFError) as ex:
46-
# We still get exception after retry:
45+
except Exception as ex: # pylint: disable=broad-exception-caught
46+
# If we still get exception after retry, ignore all types of exceptions and use a new cache.
4747
# - pickle.UnpicklingError is caused by corrupted cache file, perhaps due to concurrent writes.
4848
# - EOFError is caused by empty cache file created by other az instance, but hasn't been filled yet.
49+
# - AttributeError is caused by reading cache generated by different MSAL versions.
4950
logger.debug("Failed to load cache: %s. Using a fresh one.", ex)
5051
self.data = {} # Ignore a non-existing or corrupted http_cache
5152

src/azure-cli-core/azure/cli/core/cloud.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ def get_clouds(cli_ctx):
583583
except configparser.MissingSectionHeaderError:
584584
os.remove(CLOUD_CONFIG_FILE)
585585
logger.warning("'%s' is in bad format and has been removed.", CLOUD_CONFIG_FILE)
586+
active_cloud_name = get_active_cloud_name(cli_ctx)
586587
for section in config.sections():
587588
c = Cloud(section)
588589
for option in config.options(section):
@@ -602,19 +603,20 @@ def get_clouds(cli_ctx):
602603
"2019-03-01-hybrid",
603604
"2020-09-01-hybrid",
604605
):
605-
logger.error(
606-
"The azure stack profile '%s' has been deprecated and removed, using the 'latest' profile instead.\n"
607-
"To continue using Azure Stack, please install the Azure CLI `2.66.*` (LTS) version. For more details, refer to: https://learn.microsoft.com/en-us/cli/azure/whats-new-overview#important-notice-for-azure-stack-hub-customers", c.profile
608-
)
609-
c.profile = 'latest'
606+
if c.name == active_cloud_name:
607+
# only apply to the active cloud
608+
logger.error(
609+
"The azure stack profile '%s' has been deprecated and removed, using the 'latest' profile instead.\n"
610+
"To continue using Azure Stack, please install the Azure CLI `2.66.*` (LTS) version. For more details, refer to: https://learn.microsoft.com/en-us/cli/azure/whats-new-overview#important-notice-for-azure-stack-hub-customers", c.profile
611+
)
612+
c.profile = 'latest'
610613
else:
611614
raise CLIError('Profile {} does not exist or is not supported.'.format(c.profile))
612615
if not c.endpoints.has_endpoint_set('management') and \
613616
c.endpoints.has_endpoint_set('resource_manager'):
614617
# If management endpoint not set, use resource manager endpoint
615618
c.endpoints.management = c.endpoints.resource_manager
616619
clouds.append(c)
617-
active_cloud_name = get_active_cloud_name(cli_ctx)
618620
for c in clouds:
619621
if c.name == active_cloud_name:
620622
c.is_active = True

src/azure-cli-core/azure/cli/core/profiles/_shared.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,10 @@ def default_api_version(self):
195195
'provider_operations_metadata': '2018-01-01-preview'
196196
}),
197197
ResourceType.MGMT_CONTAINERREGISTRY: SDKProfile('2025-03-01-preview', {
198-
'agent_pools': '2019-06-01-preview',
199-
'tasks': '2019-06-01-preview',
200-
'task_runs': '2019-06-01-preview',
201-
'runs': '2019-06-01-preview',
198+
'agent_pools': '2025-03-01-preview',
199+
'tasks': '2025-03-01-preview',
200+
'task_runs': '2025-03-01-preview',
201+
'runs': '2025-03-01-preview',
202202
'network_rule': '2021-08-01-preview',
203203
'cache_rules': '2023-01-01-preview',
204204
'credential_sets': '2023-01-01-preview'

src/azure-cli/azure/cli/command_modules/acr/_client_factory.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
VERSION_2022_02_01_PREVIEW = "2022-02-01-preview"
1313
VERSION_2023_01_01_PREVIEW = "2023-01-01-preview"
1414
VERSION_2024_11_01_PREVIEW = "2024-11-01-preview"
15+
VERSION_2025_03_01_PREVIEW = "2025-03-01-preview"
1516

1617

1718
def get_acr_service_client(cli_ctx, api_version=None):
@@ -38,7 +39,7 @@ def cf_acr_network_rules(cli_ctx, *_):
3839

3940

4041
def cf_acr_registries_tasks(cli_ctx, *_):
41-
return get_acr_service_client(cli_ctx, api_version=VERSION_2019_06_01_PREVIEW).registries
42+
return get_acr_service_client(cli_ctx, api_version=VERSION_2025_03_01_PREVIEW).registries
4243

4344

4445
def cf_acr_replications(cli_ctx, *_):
@@ -54,15 +55,15 @@ def cf_acr_private_endpoint_connections(cli_ctx, *_):
5455

5556

5657
def cf_acr_tasks(cli_ctx, *_):
57-
return get_acr_service_client(cli_ctx, VERSION_2019_06_01_PREVIEW).tasks
58+
return get_acr_service_client(cli_ctx, VERSION_2025_03_01_PREVIEW).tasks
5859

5960

6061
def cf_acr_taskruns(cli_ctx, *_):
61-
return get_acr_service_client(cli_ctx, VERSION_2019_06_01_PREVIEW).task_runs
62+
return get_acr_service_client(cli_ctx, VERSION_2025_03_01_PREVIEW).task_runs
6263

6364

6465
def cf_acr_runs(cli_ctx, *_):
65-
return get_acr_service_client(cli_ctx, VERSION_2019_06_01_PREVIEW).runs
66+
return get_acr_service_client(cli_ctx, VERSION_2025_03_01_PREVIEW).runs
6667

6768

6869
def cf_acr_scope_maps(cli_ctx, *_):
@@ -78,7 +79,7 @@ def cf_acr_token_credentials(cli_ctx, *_):
7879

7980

8081
def cf_acr_agentpool(cli_ctx, *_):
81-
return get_acr_service_client(cli_ctx, VERSION_2019_06_01_PREVIEW).agent_pools
82+
return get_acr_service_client(cli_ctx, VERSION_2025_03_01_PREVIEW).agent_pools
8283

8384

8485
def cf_acr_connected_registries(cli_ctx, *_):

src/azure-cli/azure/cli/command_modules/acr/_help.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
- name: Queue a local context as a Linux build on arm/v7 architecture, tag it, and push it to the registry.
3838
text: >
3939
az acr build -t sample/hello-world:{{.Run.ID}} -r myregistry . --platform linux/arm/v7
40+
- name: Queue a local context as a Linux build, tag it, and push it to the ABAC-based Repository Permission enabled registry and use the caller's Entra identity to authenticate with the source registry.
41+
text: >
42+
az acr build -t sample/hello-world:{{.Run.ID}} -r myregistry . --source-acr-auth-id [caller]
4043
"""
4144

4245
helps['acr check-health'] = """
@@ -812,6 +815,9 @@
812815
- name: Queue a remote OCI Artifact context and runs the task.
813816
text: >
814817
az acr run -r myregistry oci://myregistry.azurecr.io/myartifact:mytag -f hello-world.yaml
818+
- name: Queue a run to execute a container command in an ABAC-based Repository Permission enabled registry and use the caller's Entra identity to authenticate with the source registry.
819+
text: >
820+
az acr run -r myregistry --cmd '$Registry/myimage' /dev/null --source-acr-auth-id [caller]
815821
"""
816822

817823
helps['acr scope-map'] = """
@@ -941,12 +947,22 @@
941947
az acr task create -t acb:{{.Run.ID}} -n acb-win -r myregistry \\
942948
-c https://github.com/Azure/acr-builder.git -f Windows.Dockerfile \\
943949
--commit-trigger-enabled false --platform Windows/amd64
944-
- name: Create a Linux multi-step task from a public GitHub repository with with both system-assigned and user-assigned managed identities and base image, git commit, pull request, and timer triggers that run the task at noon on Mondays through Fridays with the timer trigger name provided.
950+
- name: Create a Linux multi-step task from a public GitHub repository with both system-assigned and user-assigned managed identities and base image, git commit, pull request, and timer triggers that run the task at noon on Mondays through Fridays with the timer trigger name provided.
945951
text: |
946952
az acr task create -t hello-world:{{.Run.ID}} -n hello-world -r myregistry \\
947953
--pull-request-trigger-enabled true --schedule "dailyTimer:0 12 * * Mon-Fri" \\
948954
-c https://github.com/Azure-Samples/acr-tasks.git#:multipleRegistries -f testtask.yaml \\
949955
--assign-identity [system] "/subscriptions/<subscriptionId>/resourcegroups/<myResourceGroup>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<myUserAssignedIdentitiy>"
956+
- name: Create a task without the source location in an ABAC-based Repository Permission registry and specify a system-assigned managed identity used for auth with the source registry.
957+
text: >
958+
az acr task create -n hello-world -r myregistry --cmd '$Registry/myimage' -c /dev/null --source-acr-auth-id [system]
959+
- name: Create a task without the source location in an ABAC-based Repository Permission registry and specify a user-assigned managed identity used for auth with the source registry.
960+
text: >
961+
az acr task create -n hello-world -r myregistry --cmd '$Registry/myimage' -c /dev/null --source-acr-auth-id "/subscriptions/<subscriptionId>/resourcegroups/<myResourceGroup>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<myUserAssignedIdentitiy>"
962+
- name: Create a task without the source location in an ABAC-based Repository Permission registry with both system-assigned and user-assigned managed identities, and specify the system-assigned managed identity used for auth with the source registry.
963+
text: |
964+
az acr task create -n hello-world -r myregistry --cmd '$Registry/myimage' -c /dev/null --source-acr-auth-id [system]
965+
--assign-identity [system] "/subscriptions/<subscriptionId>/resourcegroups/<myResourceGroup>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<myUserAssignedIdentitiy>"
950966
"""
951967

952968
helps['acr task credential'] = """
@@ -1220,6 +1236,12 @@
12201236
az acr task update --image MyImage --name MyTask --registry myregistry \\
12211237
--context https://github.com/Azure-Samples/acr-build-helloworld-node.git
12221238
crafted: true
1239+
- name: Update the task using the system-assigned managed identity for authentication with the source registry in Azure Container Registry.
1240+
text: >
1241+
az acr task update -n MyTask -r myregistry --source-acr-auth-id [system]
1242+
- name: Update the task using the user-assigned managed identity for authentication with the source registry in Azure Container Registry.
1243+
text: >
1244+
az acr task update -n MyTask -r myregistry --source-acr-auth-id "/subscriptions/<subscriptionId>/resourcegroups/<myResourceGroup>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<myUserAssignedIdentitiy>"
12231245
"""
12241246

12251247
helps['acr task update-run'] = """

src/azure-cli/azure/cli/command_modules/acr/_params.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
315315
c.argument('set_secret', help="Secret value in '--set name[=value]' format. Multiples supported by passing --set multiple times.", action='append', validator=validate_set_secret)
316316
c.argument('agent_pool_name', options_list=['--agent-pool'], help='The name of the agent pool.', is_preview=True)
317317
c.argument('log_template', options_list=['--log-template'], help="The repository and tag template for run log artifact using the format: 'log/repo:tag' (e.g., 'acr/logs:{{.Run.ID}}'). Only applicable to CMK enabled registry.", is_preview=True)
318+
c.argument('source_acr_auth_id', is_preview=True, arg_type=get_enum_type(["[caller]", "none"]), help="Assign the identity used for source registry login. Use '[caller]' for caller identity.")
318319

319320
with self.argument_context('acr pack build') as c:
320321
c.argument('registry_name', options_list=['--registry', '-r'])
@@ -334,6 +335,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
334335
c.argument('secret_arg', options_list=['--secret-build-arg'], help="Secret build argument in '--secret-build-arg name[=value]' format. Multiples are supported by passing '--secret-build-arg name[=value]' multiple times. This parameter value is not surfaced to the ACR team and is more suitable for sensitive information.", action='append', validator=validate_secret_arg)
335336
c.argument('agent_pool_name', options_list=['--agent-pool'], help='The name of the agent pool.', is_preview=True)
336337
c.argument('log_template', options_list=['--log-template'], help="The repository and tag template for run log artifact using the format: 'log/repo:tag' (e.g., 'acr/logs:{{.Run.ID}}'). Only applicable to CMK enabled registry.", is_preview=True)
338+
c.argument('source_acr_auth_id', is_preview=True, arg_type=get_enum_type(["[caller]", "none"]), help="Assign the identity used for source registry login. Use '[caller]' for caller identity.")
337339

338340
with self.argument_context('acr task') as c:
339341
c.argument('registry_name', options_list=['--registry', '-r'])
@@ -376,16 +378,20 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
376378
c.argument('cpu', type=int, help='The CPU configuration in terms of number of cores required for the run.')
377379

378380
# MSI parameter
379-
c.argument('assign_identity', nargs='*', help="Assigns managed identities to the task. Use '[system]' to refer to the system-assigned identity or a resource ID to refer to a user-assigned identity. Please see https://aka.ms/acr/tasks/task-create-managed-identity for more information.")
381+
c.argument('assign_identity', nargs='*', help="Assign managed identities to the task. Use '[system]' to refer to the system-assigned identity or a resource ID to refer to a user-assigned identity. Please see https://aka.ms/acr/tasks/task-create-managed-identity for more information.")
380382

381383
# Agent Pool Parameter
382384
c.argument('agent_pool_name', options_list=['--agent-pool'], help='The name of the agent pool.', is_preview=True)
383385

384386
with self.argument_context('acr task create') as c:
385387
c.argument('task_name', completer=None)
388+
c.argument('source_acr_auth_id', is_preview=True, help="Assign the managed identity used for source registry login. Use '[system]' to refer to the system-assigned identity or a resource ID to refer to a user-assigned managed identity.")
389+
390+
with self.argument_context('acr task update') as c:
391+
c.argument('source_acr_auth_id', is_preview=True, help="Assign the managed identity used for source registry login. Use '[system]' to refer to the system-assigned identity or a resource ID to refer to a user-assigned managed identity.")
386392

387393
with self.argument_context('acr task identity') as c:
388-
c.argument('identities', options_list=['--identities'], nargs='*', help="Assigns managed identities to the task. Use '[system]' to refer to the system-assigned identity or a resource ID to refer to a user-assigned identity.")
394+
c.argument('identities', options_list=['--identities'], nargs='*', help="Assign managed identities to the task. Use '[system]' to refer to the system-assigned identity or a resource ID to refer to a user-assigned identity.")
389395

390396
with self.argument_context('acr task credential') as c:
391397
# Custom registry credentials

src/azure-cli/azure/cli/command_modules/acr/_utils.py

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232

3333
from ._archive_utils import upload_source_code, check_remote_source_code
3434

35+
CALLER_IDENTITY_ALIAS = '[caller]'
36+
SYSTEM_ASSIGNED_IDENTITY_ALIAS = '[system]'
37+
3538
logger = get_logger(__name__)
3639

3740

@@ -278,30 +281,59 @@ def get_yaml_template(cmd_value, timeout, file):
278281
return yaml_template
279282

280283

281-
def get_custom_registry_credentials(cmd,
282-
auth_mode=None,
283-
login_server=None,
284-
username=None,
285-
password=None,
286-
identity=None,
287-
is_remove=False):
284+
def get_source_and_custom_registry_credentials(cmd,
285+
auth_mode=None,
286+
login_server=None,
287+
username=None,
288+
password=None,
289+
identity=None,
290+
is_remove=False,
291+
source_acr_auth_id=None,
292+
registry_abac_enabled=False,
293+
deprecate_auth_mode=False):
288294
"""Get the credential object from the input
289295
:param str auth_mode: The login mode for the source registry
290296
:param str login_server: The login server of custom registry
291297
:param str username: The username for custom registry (plain text or a key vault secret URI)
292298
:param str password: The password for custom registry (plain text or a key vault secret URI)
293299
:param str identity: The task managed identity used for the credential
300+
:param str source_acr_auth_id: the managed identity used for the source registry authentication
301+
:param bool registry_abac_enabled: whether the registry is ABAC-enabled
302+
:param bool deprecate_auth_mode: whether to print the auth mode deprecation warning
294303
"""
295304
Credentials, CustomRegistryCredentials, SourceRegistryCredentials, SecretObject, \
296305
SecretObjectType = cmd.get_models(
297306
'Credentials', 'CustomRegistryCredentials', 'SourceRegistryCredentials', 'SecretObject',
298307
'SecretObjectType',
299308
operation_group='tasks')
300309

310+
if deprecate_auth_mode:
311+
check_auth_mode_for_abac(registry_abac_enabled, auth_mode)
312+
313+
source_registry_identity = None
314+
if source_acr_auth_id:
315+
# "Default" and "None" are the allowed values for source registry auth mode.
316+
# For a non-ABAC-enabled registry, "--source-acr-auth-id" will not take effect, and authentication
317+
# will fail if the auth mode is "None". Therefore, we need to throw an error here.
318+
if not registry_abac_enabled and auth_mode and auth_mode.lower() == "none":
319+
raise CLIError('Error: Conflicting Authentication Parameters for Task Access to Source Registry. Task '
320+
'authentication mode for source registry access is set to "None", but an identity was '
321+
'provided for authentication. Remove the identity or update the authentication mode to '
322+
'resolve this conflict.')
323+
324+
if source_acr_auth_id.lower() == "none":
325+
source_registry_identity = None
326+
elif source_acr_auth_id.startswith('/subscriptions/'): # user-assigned MI resource ID
327+
source_registry_identity = resolve_identity_client_id(cmd.cli_ctx, source_acr_auth_id)
328+
elif source_acr_auth_id == CALLER_IDENTITY_ALIAS or source_acr_auth_id == SYSTEM_ASSIGNED_IDENTITY_ALIAS:
329+
source_registry_identity = source_acr_auth_id
330+
else:
331+
raise CLIError('Error: Invalid value for --source-acr-auth-id.')
332+
301333
source_registry_credentials = None
302-
if auth_mode:
334+
if auth_mode or source_registry_identity:
303335
source_registry_credentials = SourceRegistryCredentials(
304-
login_mode=auth_mode)
336+
login_mode=auth_mode, identity=source_registry_identity)
305337

306338
custom_registries = None
307339
if login_server:
@@ -606,3 +638,10 @@ def get_task_details_by_name(cli_ctx, resource_group_name, registry_name, task_n
606638
from ._client_factory import cf_acr_tasks
607639
client = cf_acr_tasks(cli_ctx)
608640
return client.get_details(resource_group_name, registry_name, task_name)
641+
642+
643+
def check_auth_mode_for_abac(registry_abac_enabled, auth_mode):
644+
if registry_abac_enabled and auth_mode is not None:
645+
logger.warning("The --auth-mode flag is deprecated for specifying access to an ABAC-enabled source registry. "
646+
"Please use --source-acr-auth-id to specify an Entra identity for use in accessing an "
647+
"ABAC-enabled source registry.")

0 commit comments

Comments
 (0)