Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acr/_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,8 @@ def format_error_message(self, *args):
"UNEXPECTED_ERROR",
"An unexpected error occurred."
)

CMK_MANAGED_IDENTITY_ERROR = ErrorClass(
"CMK_ERROR",
"The identity used for registry '{}' encryption doesn't exist."
)
10 changes: 10 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acr/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,3 +562,13 @@ def get_scope_map_from_id(cmd, scope_map_id):
scope_map_name = scope_info[9]
return acr_scope_map_show(cmd, scope_map_client, registry_name, scope_map_name, resource_group_name)
# endregion


def resolve_identity_client_id(cli_ctx, managed_identity_resource_id):
from azure.mgmt.msi import ManagedServiceIdentityClient
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from msrestazure.tools import parse_resource_id

res = parse_resource_id(managed_identity_resource_id)
client = get_mgmt_service_client(cli_ctx, ManagedServiceIdentityClient, subscription_id=res['subscription'])
return client.user_assigned_identities.get(res['resource_group'], res['name']).client_id
25 changes: 22 additions & 3 deletions src/azure-cli/azure/cli/command_modules/acr/check_health.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .custom import get_docker_command
from ._docker_utils import _get_aad_token
from .helm import get_helm_command
from ._utils import get_registry_by_name
from ._utils import get_registry_by_name, resolve_identity_client_id
from ._errors import ErrorClass

logger = get_logger(__name__)
Expand Down Expand Up @@ -295,11 +295,12 @@ def _get_endpoint_and_token_status(cmd, login_server, ignore_errors):
print_pass("Fetch access token for registry '{}'".format(login_server))


def _check_health_connectivity(cmd, registry_name, ignore_errors):
def _check_registry_health(cmd, registry_name, ignore_errors):
if registry_name is None:
logger.warning("Registry name must be provided to check connectivity.")
return

# Connectivity
try:
registry, _ = get_registry_by_name(cmd.cli_ctx, registry_name)
login_server = registry.login_server.rstrip('/')
Expand All @@ -318,6 +319,24 @@ def _check_health_connectivity(cmd, registry_name, ignore_errors):
if status_validated:
_get_endpoint_and_token_status(cmd, login_server, ignore_errors)

# CMK settings
if registry.encryption and registry.encryption.key_vault_properties: # pylint: disable=too-many-nested-blocks
client_id = registry.encryption.key_vault_properties.identity
valid_identity = False
if registry.identity:
valid_identity = (client_id == 'system') and bool(registry.identity.principal_id) # use system identity?
if not valid_identity and registry.identity.user_assigned_identities:
for k, v in registry.identity.user_assigned_identities.items():
if v.client_id == client_id:
from msrestazure.azure_exceptions import CloudError
try:
valid_identity = (resolve_identity_client_id(cmd.cli_ctx, k) == client_id)
except CloudError:
pass
if not valid_identity:
from ._errors import CMK_MANAGED_IDENTITY_ERROR
_handle_error(CMK_MANAGED_IDENTITY_ERROR.format_error_message(registry_name), ignore_errors)


# General command
def acr_check_health(cmd, # pylint: disable useless-return
Expand All @@ -332,7 +351,7 @@ def acr_check_health(cmd, # pylint: disable useless-return
_get_docker_status_and_version(ignore_errors, yes)
_get_cli_version()

_check_health_connectivity(cmd, registry_name, ignore_errors)
_check_registry_health(cmd, registry_name, ignore_errors)

if not in_cloud_console:
_get_helm_version(ignore_errors)
Expand Down
17 changes: 4 additions & 13 deletions src/azure-cli/azure/cli/command_modules/acr/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
validate_managed_registry,
validate_sku_update,
get_resource_group_name_by_registry_name,
user_confirmation
user_confirmation,
resolve_identity_client_id
)
from ._docker_utils import get_login_credentials, EMPTY_GUID
from .network_rule import NETWORK_RULE_NOT_SUPPORTED
Expand Down Expand Up @@ -403,7 +404,7 @@ def _configure_cmk(cmd, registry, resource_group_name, identity, key_encryption_
resource_group=resource_group_name,
resource=identity)

identity_client_id = _resolve_identity_client_id(cmd.cli_ctx, identity)
identity_client_id = resolve_identity_client_id(cmd.cli_ctx, identity)

KeyVaultProperties, EncryptionProperty = cmd.get_models('KeyVaultProperties', 'EncryptionProperty')
registry.encryption = EncryptionProperty(status='enabled', key_vault_properties=KeyVaultProperties(
Expand Down Expand Up @@ -524,7 +525,7 @@ def rotate_key(cmd, client, registry_name, identity=None, key_encryption_key=Non
identity = _ensure_identity_resource_id(subscription_id=get_subscription_id(cmd.cli_ctx),
resource_group=resource_group_name,
resource=identity)
client_id = _resolve_identity_client_id(cmd.cli_ctx, identity)
client_id = resolve_identity_client_id(cmd.cli_ctx, identity)

registry.encryption.key_vault_properties.identity = client_id

Expand All @@ -547,16 +548,6 @@ def _ensure_identity_resource_id(subscription_id, resource_group, resource):
name=resource)


def _resolve_identity_client_id(cli_ctx, managed_identity_resource_id):
from azure.mgmt.msi import ManagedServiceIdentityClient
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from msrestazure.tools import parse_resource_id

res = parse_resource_id(managed_identity_resource_id)
client = get_mgmt_service_client(cli_ctx, ManagedServiceIdentityClient, subscription_id=res['subscription'])
return client.user_assigned_identities.get(res['resource_group'], res['name']).client_id


def list_private_link_resources(cmd, client, registry_name, resource_group_name=None):
resource_group_name = get_resource_group_name_by_registry_name(cmd.cli_ctx, registry_name, resource_group_name)
return client.list_private_link_resources(resource_group_name, registry_name)