Skip to content

Commit 74d9c1a

Browse files
committed
mi-arc
1 parent 41c2910 commit 74d9c1a

File tree

2 files changed

+75
-38
lines changed

2 files changed

+75
-38
lines changed

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

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -216,48 +216,56 @@ def login(self,
216216
return deepcopy(consolidated)
217217

218218
def login_with_managed_identity(self, identity_id=None, allow_no_subscriptions=None):
219-
import jwt
220-
from azure.mgmt.core.tools import is_valid_resource_id
221-
from azure.cli.core.auth.adal_authentication import MSIAuthenticationWrapper
222-
resource = self.cli_ctx.cloud.endpoints.active_directory_resource_id
223-
224-
if identity_id:
225-
if is_valid_resource_id(identity_id):
226-
msi_creds = MSIAuthenticationWrapper(resource=resource, msi_res_id=identity_id)
227-
identity_type = MsiAccountTypes.user_assigned_resource_id
228-
else:
229-
authenticated = False
230-
from azure.cli.core.azclierror import AzureResponseError
231-
try:
232-
msi_creds = MSIAuthenticationWrapper(resource=resource, client_id=identity_id)
233-
identity_type = MsiAccountTypes.user_assigned_client_id
234-
authenticated = True
235-
except AzureResponseError as ex:
236-
if 'http error: 400, reason: Bad Request' in ex.error_msg:
237-
logger.info('Sniff: not an MSI client id')
238-
else:
239-
raise
240-
241-
if not authenticated:
219+
identity_type = None
220+
if _on_azure_arc():
221+
identity_type = MsiAccountTypes.system_assigned
222+
from .auth.msal_authentication import ManagedIdentityCredential
223+
cred = ManagedIdentityCredential()
224+
token = cred.get_token(self._arm_scope).token
225+
else:
226+
import jwt
227+
from azure.mgmt.core.tools import is_valid_resource_id
228+
from azure.cli.core.auth.adal_authentication import MSIAuthenticationWrapper
229+
resource = self.cli_ctx.cloud.endpoints.active_directory_resource_id
230+
231+
if identity_id:
232+
if is_valid_resource_id(identity_id):
233+
msi_creds = MSIAuthenticationWrapper(resource=resource, msi_res_id=identity_id)
234+
identity_type = MsiAccountTypes.user_assigned_resource_id
235+
else:
236+
authenticated = False
237+
from azure.cli.core.azclierror import AzureResponseError
242238
try:
243-
identity_type = MsiAccountTypes.user_assigned_object_id
244-
msi_creds = MSIAuthenticationWrapper(resource=resource, object_id=identity_id)
239+
msi_creds = MSIAuthenticationWrapper(resource=resource, client_id=identity_id)
240+
identity_type = MsiAccountTypes.user_assigned_client_id
245241
authenticated = True
246242
except AzureResponseError as ex:
247243
if 'http error: 400, reason: Bad Request' in ex.error_msg:
248-
logger.info('Sniff: not an MSI object id')
244+
logger.info('Sniff: not an MSI client id')
249245
else:
250246
raise
251247

252-
if not authenticated:
253-
raise CLIError('Failed to connect to MSI, check your managed service identity id.')
248+
if not authenticated:
249+
try:
250+
identity_type = MsiAccountTypes.user_assigned_object_id
251+
msi_creds = MSIAuthenticationWrapper(resource=resource, object_id=identity_id)
252+
authenticated = True
253+
except AzureResponseError as ex:
254+
if 'http error: 400, reason: Bad Request' in ex.error_msg:
255+
logger.info('Sniff: not an MSI object id')
256+
else:
257+
raise
254258

255-
else:
256-
identity_type = MsiAccountTypes.system_assigned
257-
msi_creds = MSIAuthenticationWrapper(resource=resource)
259+
if not authenticated:
260+
raise CLIError('Failed to connect to MSI, check your managed service identity id.')
261+
262+
else:
263+
identity_type = MsiAccountTypes.system_assigned
264+
msi_creds = MSIAuthenticationWrapper(resource=resource)
265+
266+
token_entry = msi_creds.token
267+
token = token_entry['access_token']
258268

259-
token_entry = msi_creds.token
260-
token = token_entry['access_token']
261269
logger.info('MSI: token was retrieved. Now trying to initialize local accounts...')
262270
decode = jwt.decode(token, algorithms=['RS256'], options={"verify_signature": False})
263271
tenant = decode['tid']
@@ -364,7 +372,11 @@ def get_login_credentials(self, resource=None, client_id=None, subscription_id=N
364372
resource=resource)
365373
else:
366374
# managed identity
367-
cred = MsiAccountTypes.msi_auth_factory(managed_identity_type, managed_identity_id, resource)
375+
if _on_azure_arc():
376+
from .auth.msal_authentication import ManagedIdentityCredential
377+
cred = ManagedIdentityCredential()
378+
else:
379+
cred = MsiAccountTypes.msi_auth_factory(managed_identity_type, managed_identity_id, resource)
368380
return (cred,
369381
str(account[_SUBSCRIPTION_ID]),
370382
str(account[_TENANT_ID]))
@@ -390,9 +402,12 @@ def get_raw_token(self, resource=None, scopes=None, subscription=None, tenant=No
390402
if tenant:
391403
raise CLIError("Tenant shouldn't be specified for managed identity account")
392404
from .auth.util import scopes_to_resource
393-
msi_creds = MsiAccountTypes.msi_auth_factory(identity_type, identity_id,
394-
scopes_to_resource(scopes))
395-
sdk_token = msi_creds.get_token(*scopes)
405+
if _on_azure_arc():
406+
from .auth.msal_authentication import ManagedIdentityCredential
407+
cred = ManagedIdentityCredential()
408+
else:
409+
cred = MsiAccountTypes.msi_auth_factory(identity_type, identity_id, scopes_to_resource(scopes))
410+
sdk_token = cred.get_token(*scopes)
396411
elif in_cloud_console() and account[_USER_ENTITY].get(_CLOUD_SHELL_ID):
397412
# Cloud Shell, which is just a system-assigned managed identity.
398413
if tenant:
@@ -900,3 +915,7 @@ def _create_identity_instance(cli_ctx, *args, **kwargs):
900915
return Identity(*args, encrypt=encrypt, use_msal_http_cache=use_msal_http_cache,
901916
enable_broker_on_windows=enable_broker_on_windows,
902917
instance_discovery=instance_discovery, **kwargs)
918+
919+
920+
def _on_azure_arc():
921+
return "IDENTITY_ENDPOINT" in os.environ and "IMDS_ENDPOINT" in os.environ

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
from knack.log import get_logger
2020
from knack.util import CLIError
21-
from msal import PublicClientApplication, ConfidentialClientApplication
21+
from msal import (PublicClientApplication, ConfidentialClientApplication,
22+
ManagedIdentityClient, SystemAssignedManagedIdentity)
2223

2324
from .util import check_result, build_sdk_access_token
2425

@@ -138,3 +139,20 @@ def get_token(self, *scopes, **kwargs):
138139
result = self.acquire_token_for_client(scopes, **kwargs)
139140
check_result(result)
140141
return build_sdk_access_token(result)
142+
143+
144+
class ManagedIdentityCredential:
145+
"""Currently, only Azure Arc's system-assigned managed identity is supported.
146+
"""
147+
148+
def __init__(self):
149+
import requests
150+
self._msal_client = ManagedIdentityClient(SystemAssignedManagedIdentity(), http_client=requests.Session())
151+
152+
def get_token(self, *scopes, **kwargs):
153+
logger.debug("ManagedIdentityCredential.get_token: scopes=%r, kwargs=%r", scopes, kwargs)
154+
155+
from .util import scopes_to_resource
156+
result = self._msal_client.acquire_token_for_client(resource=scopes_to_resource(scopes))
157+
check_result(result)
158+
return build_sdk_access_token(result)

0 commit comments

Comments
 (0)