From 0a9e7d5431a0af835b2bc05a817638a4097661ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 05:39:58 +0000 Subject: [PATCH 1/2] Initial plan From 25a9e98248f3f387624202b978692eed30197b45 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 05:47:14 +0000 Subject: [PATCH 2/2] Guard VM SSH cert flow for managed identity and Cloud Shell Agent-Logs-Url: https://github.com/Azure/azure-cli/sessions/04d2b8e6-e20c-4382-849d-f45677f0171f Co-authored-by: a0x1ab <59631311+a0x1ab@users.noreply.github.com> --- src/azure-cli-core/azure/cli/core/_profile.py | 5 +++ .../azure/cli/core/tests/test_profile.py | 41 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/azure-cli-core/azure/cli/core/_profile.py b/src/azure-cli-core/azure/cli/core/_profile.py index de0c8efe70f..13f47ed417c 100644 --- a/src/azure-cli-core/azure/cli/core/_profile.py +++ b/src/azure-cli-core/azure/cli/core/_profile.py @@ -441,6 +441,11 @@ def get_raw_token(self, resource=None, scopes=None, subscription=None, tenant=No def get_msal_token(self, scopes, data): """Get VM SSH certificate. DO NOT use it for other purposes. To get an access token, use get_raw_token instead. """ + account = self.get_subscription() + managed_identity_type, _ = Profile._parse_managed_identity_account(account) + if managed_identity_type or (in_cloud_console() and account[_USER_ENTITY].get(_CLOUD_SHELL_ID)): + raise AuthenticationError("VM SSH currently doesn't support managed identity or Cloud Shell.") + credential, _, _ = self.get_login_credentials(sdk_credential=False) from .auth.constants import ACCESS_TOKEN certificate_string = credential.acquire_token(scopes, data=data)[ACCESS_TOKEN] diff --git a/src/azure-cli-core/azure/cli/core/tests/test_profile.py b/src/azure-cli-core/azure/cli/core/tests/test_profile.py index bef9b67a39c..d62464ca5d3 100644 --- a/src/azure-cli-core/azure/cli/core/tests/test_profile.py +++ b/src/azure-cli-core/azure/cli/core/tests/test_profile.py @@ -12,8 +12,9 @@ from unittest import mock from azure.cli.core._profile import (Profile, SubscriptionFinder, _attach_token_tenant, - _transform_subscription_for_multiapi, - _TENANT_LEVEL_ACCOUNT_NAME) + _transform_subscription_for_multiapi, + _TENANT_LEVEL_ACCOUNT_NAME) +from azure.cli.core.azclierror import AuthenticationError from azure.cli.core.auth.util import AccessToken from azure.cli.core.mock import DummyCli from azure.mgmt.resource.subscriptions.models import \ @@ -1350,6 +1351,42 @@ def test_get_msal_token(self, get_user_credential_mock): assert credential_mock_temp.acquire_token_scopes == ['https://pas.windows.net/CheckMyAccess/Linux/.default'] assert credential_mock_temp.acquire_token_data == MOCK_DATA + @mock.patch('azure.cli.core.auth.msal_credentials.ManagedIdentityCredential', ManagedIdentityCredentialStub) + def test_get_msal_token_mi_unsupported(self): + profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + consolidated = profile._normalize_properties('systemAssignedIdentity', + [deepcopy(self.test_mi_subscription)], + True, + assigned_identity_info='MSI') + profile._set_subscriptions(consolidated) + + with self.assertRaisesRegex(AuthenticationError, + "VM SSH currently doesn't support managed identity or Cloud Shell."): + profile.get_msal_token(['https://pas.windows.net/CheckMyAccess/Linux/.default'], + {'token_type': 'ssh-cert'}) + + @mock.patch('azure.cli.core._profile.in_cloud_console', autospec=True) + @mock.patch('azure.cli.core.auth.msal_credentials.CloudShellCredential', autospec=True) + def test_get_msal_token_cloud_shell_unsupported(self, cloud_shell_credential_mock, mock_in_cloud_console): + mock_in_cloud_console.return_value = True + cloud_shell_credential_mock.return_value = CloudShellCredentialStub() + + profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + test_subscription_id = '12345678-1bf0-4dda-aec3-cb9272f09590' + test_tenant_id = '12345678-38d6-4fb2-bad9-b7b93a3e1234' + cloud_shell_subscription = SubscriptionStub('/subscriptions/' + test_subscription_id, + self.display_name1, self.state1, test_tenant_id) + consolidated = profile._normalize_properties(self.user1, + [cloud_shell_subscription], + True) + consolidated[0]['user']['cloudShellID'] = True + profile._set_subscriptions(consolidated) + + with self.assertRaisesRegex(AuthenticationError, + "VM SSH currently doesn't support managed identity or Cloud Shell."): + profile.get_msal_token(['https://pas.windows.net/CheckMyAccess/Linux/.default'], + {'token_type': 'ssh-cert'}) + @mock.patch('azure.cli.core.auth.identity.Identity.logout_service_principal') @mock.patch('azure.cli.core.auth.identity.Identity.logout_user') def test_logout(self, logout_user_mock, logout_service_principal_mock):