Skip to content

Commit 655720e

Browse files
committed
add managed identity support to cache rule create/update commands
1 parent 7cc90a5 commit 655720e

File tree

8 files changed

+1515
-307
lines changed

8 files changed

+1515
-307
lines changed

src/azure-cli/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Release History
66
2.84.0
77
++++++
88

9+
**ACR**
10+
11+
* `az acr cache create/update`: Add `--identity` parameter to support using user-assigned managed identity for cache rules
12+
913
**AKS**
1014

1115
* `az aks create`: Add `--enable-container-network-logs` parameter to enable container network logs (#32700)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
CREDENTIAL_SET_RESOURCE_ID_TEMPLATE = '/subscriptions/{sub_id}/resourceGroups/{rg}/providers/Microsoft.ContainerRegistry/registries/{reg_name}/credentialSets/{cred_set_name}'
1515

16+
USER_ASSIGNED_IDENTITY_RESOURCE_ID_TEMPLATE = '/subscriptions/{sub_id}/resourcegroups/{rg}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identity_name}'
17+
1618
TASK_RESOURCE_TYPE = REGISTRY_RESOURCE_TYPE + '/tasks'
1719
TASK_VALID_VSTS_URLS = ['visualstudio.com', 'dev.azure.com']
1820
TASK_RESOURCE_ID_TEMPLATE = '/subscriptions/{sub_id}/resourceGroups/{rg}/providers/Microsoft.ContainerRegistry/registries/{reg}/tasks/{name}'

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
validate_manifest_id,
4242
validate_repo_id,
4343
validate_repository,
44-
validate_permissive_repo_id
44+
validate_permissive_repo_id,
45+
validate_cache_credentials
4546
)
4647
from .scope_map import RepoScopeMapActions, GatewayScopeMapActions
4748

@@ -256,6 +257,8 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
256257
c.argument('source_repo', options_list=['--source-repo', '-s'], help="The full source repository path such as 'docker.io/library/ubuntu'.")
257258
c.argument('target_repo', options_list=['--target-repo', '-t'], help="The target repository namespace such as 'ubuntu'.")
258259
c.argument('remove_cred_set', action="store_true", help='Optional boolean indicating whether to remove the credential set from the cache rule. False by default.')
260+
c.argument('identity', options_list=['--identity'], validator=validate_cache_credentials,
261+
help='User-assigned managed identity resource ID for ACR to authenticate with the upstream registry. Format: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}.')
259262

260263
with self.argument_context('acr credential-set') as c:
261264
c.argument('registry_name', options_list=['--registry', '-r'])

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from knack.util import CLIError
99
from knack.log import get_logger
1010
from azure.cli.core.azclierror import FileOperationError, InvalidArgumentValueError
11-
from ._constants import ACR_NAME_VALIDATION_REGEX
11+
from ._constants import ACR_NAME_VALIDATION_REGEX, USER_ASSIGNED_IDENTITY_RESOURCE_ID_TEMPLATE
1212

1313
BAD_REPO_FQDN = "The positional parameter 'repo_id' must be a fully qualified repository specifier such"\
1414
" as 'myregistry.azurecr.io/hello-world'."
@@ -192,3 +192,30 @@ def validate_repository(namespace):
192192
def validate_docker_file_path(docker_file_path):
193193
if not os.path.isfile(docker_file_path):
194194
raise FileOperationError("Unable to find '{}'.".format(docker_file_path))
195+
196+
197+
def validate_cache_credentials(namespace):
198+
"""Validate cache credential options - allow both --identity and --cred-set, but --remove-cred-set is exclusive."""
199+
has_identity = namespace.identity is not None
200+
has_cred_set = namespace.cred_set is not None
201+
has_remove_cred_set = getattr(namespace, 'remove_cred_set', False)
202+
203+
if has_remove_cred_set and (has_identity or has_cred_set):
204+
raise InvalidArgumentValueError(
205+
"Cannot specify --remove-cred-set with other credential options. Use --remove-cred-set alone to remove credentials."
206+
)
207+
208+
# Validate identity format if provided
209+
if has_identity:
210+
identity_pattern = r'^/subscriptions/[^/]+/resource[Gg]roups/[^/]+/providers/Microsoft\.ManagedIdentity/userAssignedIdentities/[^/]+$'
211+
212+
if not re.match(identity_pattern, namespace.identity):
213+
example_format = USER_ASSIGNED_IDENTITY_RESOURCE_ID_TEMPLATE.format(
214+
sub_id='{subscriptionId}',
215+
rg='{resourceGroupName}',
216+
identity_name='{identityName}'
217+
)
218+
raise InvalidArgumentValueError(
219+
f"The --identity parameter must be a valid ARM resource ID for a user-assigned managed identity. "
220+
f"Format: {example_format}"
221+
)

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

Lines changed: 78 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
from azure.cli.core.azclierror import InvalidArgumentValueError
99
from azure.cli.core.commands.client_factory import get_subscription_id
1010
from azure.core.serialization import NULL as AzureCoreNull
11+
from azure.mgmt.containerregistry.models import (
12+
CacheRule,
13+
CacheRuleProperties,
14+
CacheRuleUpdateParameters,
15+
CacheRuleUpdateProperties,
16+
IdentityProperties,
17+
UserIdentityProperties
18+
)
1119

1220

1321
def acr_cache_show(cmd,
@@ -54,9 +62,12 @@ def acr_cache_create(cmd,
5462
source_repo,
5563
target_repo,
5664
resource_group_name=None,
57-
cred_set=None):
65+
cred_set=None,
66+
identity=None):
5867

5968
rg = get_resource_group_name_by_registry_name(cmd.cli_ctx, registry_name, resource_group_name)
69+
70+
# Handle credential set
6071
if cred_set:
6172
sub_id = get_subscription_id(cmd.cli_ctx)
6273
# Format the credential set ID using subscription ID, resource group, registry name, and credential set name
@@ -68,14 +79,30 @@ def acr_cache_create(cmd,
6879
)
6980
else:
7081
cred_set_id = AzureCoreNull
82+
83+
# Handle identity
84+
identity_properties = None
85+
if identity:
86+
# Create IdentityProperties with UserAssigned type
87+
identity_properties = IdentityProperties(
88+
type="UserAssigned",
89+
user_assigned_identities={
90+
identity: UserIdentityProperties()
91+
}
92+
)
7193

72-
CacheRuleCreateParameters = cmd.get_models('CacheRule', operation_group='cache_rules')
94+
# Create cache rule properties
95+
cache_rule_properties = CacheRuleProperties(
96+
source_repository=source_repo,
97+
target_repository=target_repo,
98+
credential_set_resource_id=cred_set_id
99+
)
73100

74-
cache_rule_create_params = CacheRuleCreateParameters()
75-
cache_rule_create_params.name = name
76-
cache_rule_create_params.source_repository = source_repo
77-
cache_rule_create_params.target_repository = target_repo
78-
cache_rule_create_params.credential_set_resource_id = cred_set_id
101+
# Create cache rule with direct SDK model
102+
cache_rule_create_params = CacheRule(
103+
properties=cache_rule_properties,
104+
identity=identity_properties
105+
)
79106

80107
return client.begin_create(resource_group_name=rg,
81108
registry_name=registry_name,
@@ -88,25 +115,50 @@ def acr_cache_update_custom(cmd,
88115
registry_name,
89116
resource_group_name=None,
90117
cred_set=None,
91-
remove_cred_set=False):
92-
93-
if cred_set is None and remove_cred_set is False:
94-
raise InvalidArgumentValueError("You must either update the credential set ID or remove it.")
95-
96-
if remove_cred_set:
97-
cred_set_id = AzureCoreNull
98-
else:
99-
sub_id = get_subscription_id(cmd.cli_ctx)
100-
rg = get_resource_group_name_by_registry_name(cmd.cli_ctx, registry_name, resource_group_name)
101-
# Format the credential set ID using subscription ID, resource group, registry name, and credential set name
102-
cred_set_id = CREDENTIAL_SET_RESOURCE_ID_TEMPLATE.format(
103-
sub_id=sub_id,
104-
rg=rg,
105-
reg_name=registry_name,
106-
cred_set_name=cred_set
107-
)
108-
109-
instance.credential_set_resource_id = cred_set_id
118+
remove_cred_set=False,
119+
identity=None):
120+
121+
# Check if any update parameters are provided
122+
has_cred_update = cred_set is not None or remove_cred_set
123+
has_identity_update = identity is not None
124+
125+
if not has_cred_update and not has_identity_update:
126+
raise InvalidArgumentValueError("You must provide at least one parameter to update (credential set, identity, or removal flag).")
127+
128+
#initilize properties if not already set
129+
if instance.properties is None:
130+
instance.properties = CacheRuleUpdateProperties()
131+
132+
# Handle credential set updates
133+
if has_cred_update:
134+
if remove_cred_set:
135+
instance.properties.credential_set_resource_id = AzureCoreNull
136+
else:
137+
sub_id = get_subscription_id(cmd.cli_ctx)
138+
rg = get_resource_group_name_by_registry_name(cmd.cli_ctx, registry_name, resource_group_name)
139+
# Format the credential set ID using subscription ID, resource group, registry name, and credential set name
140+
cred_set_id = CREDENTIAL_SET_RESOURCE_ID_TEMPLATE.format(
141+
sub_id=sub_id,
142+
rg=rg,
143+
reg_name=registry_name,
144+
cred_set_name=cred_set
145+
)
146+
instance.properties.credential_set_resource_id = cred_set_id
147+
148+
# Handle identity updates
149+
if has_identity_update:
150+
if identity:
151+
# Create IdentityProperties with UserAssigned type
152+
identity_properties = IdentityProperties(
153+
type="UserAssigned",
154+
user_assigned_identities={
155+
identity: UserIdentityProperties()
156+
}
157+
)
158+
instance.identity = identity_properties
159+
else:
160+
# Remove identity by setting to None
161+
instance.identity = None
110162

111163
return instance
112164

@@ -115,8 +167,6 @@ def acr_cache_update_get(cmd):
115167
"""Returns an empty CacheRuleUpdateParameters object.
116168
"""
117169

118-
CacheRuleUpdateParameters = cmd.get_models('CacheRuleUpdateParameters', operation_group='cache_rules')
119-
120170
return CacheRuleUpdateParameters()
121171

122172

src/azure-cli/azure/cli/command_modules/acr/tests/latest/recordings/test_acr_cache.yaml

Lines changed: 221 additions & 277 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)