Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package azure-cli-core for openSUSE:Factory 
checked in at 2025-04-02 17:14:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/azure-cli-core (Old)
 and      /work/SRC/openSUSE:Factory/.azure-cli-core.new.1907 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "azure-cli-core"

Wed Apr  2 17:14:30 2025 rev:79 rq:1266203 version:2.71.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/azure-cli-core/azure-cli-core.changes    
2025-03-13 15:08:32.936117957 +0100
+++ /work/SRC/openSUSE:Factory/.azure-cli-core.new.1907/azure-cli-core.changes  
2025-04-02 17:16:08.136327261 +0200
@@ -1,0 +2,9 @@
+Tue Apr  1 06:16:56 UTC 2025 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- New upstream release
+  + Version 2.71.0
+  + For detailed information about changes see the
+    HISTORY.rst file provided with this package
+- Update Requires from setup.py
+
+-------------------------------------------------------------------

Old:
----
  azure_cli_core-2.70.0.tar.gz

New:
----
  azure_cli_core-2.71.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ azure-cli-core.spec ++++++
--- /var/tmp/diff_new_pack.yxKNtX/_old  2025-04-02 17:16:09.708393224 +0200
+++ /var/tmp/diff_new_pack.yxKNtX/_new  2025-04-02 17:16:09.708393224 +0200
@@ -24,7 +24,7 @@
 %global _sitelibdir %{%{pythons}_sitelib}
 
 Name:           azure-cli-core
-Version:        2.70.0
+Version:        2.71.0
 Release:        0
 Summary:        Microsoft Azure CLI Core Module
 License:        MIT
@@ -50,7 +50,7 @@
 Requires:       %{pythons}-jmespath
 Requires:       %{pythons}-knack < 1.0.0
 Requires:       %{pythons}-knack >= 0.11.0
-Requires:       %{pythons}-microsoft-security-utilities-secret-masker >= 
1.0.0~b2
+Requires:       %{pythons}-microsoft-security-utilities-secret-masker >= 
1.0.0~b4
 Requires:       %{pythons}-msal < 2.0.0
 Requires:       %{pythons}-msal >= 1.31.2~b1
 Requires:       %{pythons}-msal-extensions < 2.0.0

++++++ azure_cli_core-2.70.0.tar.gz -> azure_cli_core-2.71.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_cli_core-2.70.0/HISTORY.rst 
new/azure_cli_core-2.71.0/HISTORY.rst
--- old/azure_cli_core-2.70.0/HISTORY.rst       2025-02-26 07:24:09.000000000 
+0100
+++ new/azure_cli_core-2.71.0/HISTORY.rst       2025-03-25 10:17:55.000000000 
+0100
@@ -3,6 +3,10 @@
 Release History
 ===============
 
+2.71.0
+++++++
+* PREVIEW: Support managed identity authentication with MSAL. Run `az config 
set core.use_msal_managed_identity=true` or set environment variable 
`AZURE_CORE_USE_MSAL_MANAGED_IDENTITY` to enable it (#31092)
+
 2.70.0
 ++++++
 * Resolve CVE-2024-12797 (#30816)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_cli_core-2.70.0/PKG-INFO 
new/azure_cli_core-2.71.0/PKG-INFO
--- old/azure_cli_core-2.70.0/PKG-INFO  2025-02-26 07:24:39.789584600 +0100
+++ new/azure_cli_core-2.71.0/PKG-INFO  2025-03-25 10:18:48.041750200 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: azure-cli-core
-Version: 2.70.0
+Version: 2.71.0
 Summary: Microsoft Azure Command-Line Tools Core Module
 Home-page: https://github.com/Azure/azure-cli
 Author: Microsoft Corporation
@@ -26,7 +26,7 @@
 Requires-Dist: humanfriendly~=10.0
 Requires-Dist: jmespath
 Requires-Dist: knack~=0.11.0
-Requires-Dist: microsoft-security-utilities-secret-masker~=1.0.0b2
+Requires-Dist: microsoft-security-utilities-secret-masker~=1.0.0b4
 Requires-Dist: msal-extensions==1.2.0
 Requires-Dist: msal[broker]==1.31.2b1
 Requires-Dist: msrestazure~=0.6.4
@@ -43,6 +43,7 @@
 Dynamic: description
 Dynamic: home-page
 Dynamic: license
+Dynamic: license-file
 Dynamic: requires-dist
 Dynamic: requires-python
 Dynamic: summary
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_cli_core-2.70.0/azure/cli/core/__init__.py 
new/azure_cli_core-2.71.0/azure/cli/core/__init__.py
--- old/azure_cli_core-2.70.0/azure/cli/core/__init__.py        2025-02-26 
07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/__init__.py        2025-03-25 
10:17:55.000000000 +0100
@@ -4,7 +4,7 @@
 # 
--------------------------------------------------------------------------------------------
 # pylint: disable=line-too-long
 
-__version__ = "2.70.0"
+__version__ = "2.71.0"
 
 import os
 import sys
@@ -489,6 +489,26 @@
 
         return self.command_table
 
+    @staticmethod
+    def _sort_command_loaders(command_loaders):
+        module_command_loaders = []
+        extension_command_loaders = []
+
+        # Separate module and extension command loaders
+        for loader in command_loaders:
+            if loader.__module__.startswith('azext'):
+                extension_command_loaders.append(loader)
+            else:
+                module_command_loaders.append(loader)
+
+        # Sort name in each command loader list
+        module_command_loaders.sort(key=lambda loader: 
loader.__class__.__name__)
+        extension_command_loaders.sort(key=lambda loader: 
loader.__class__.__name__)
+
+        # Module first, then extension
+        sorted_command_loaders = module_command_loaders + 
extension_command_loaders
+        return sorted_command_loaders
+
     def load_arguments(self, command=None):
         from azure.cli.core.commands.parameters import (
             resource_group_name_type, get_location_type, deployment_name_type, 
vnet_name_type, subnet_name_type)
@@ -499,6 +519,8 @@
             command_loaders = set()
             for loaders in self.cmd_to_loader_map.values():
                 command_loaders = command_loaders.union(set(loaders))
+            # sort command loaders for consistent order when loading all 
commands for docs generation to avoid random diff
+            command_loaders = self._sort_command_loaders(command_loaders)
             logger.info('Applying %s command loaders...', len(command_loaders))
         else:
             command_loaders = self.cmd_to_loader_map.get(command, None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_cli_core-2.70.0/azure/cli/core/_profile.py 
new/azure_cli_core-2.71.0/azure/cli/core/_profile.py
--- old/azure_cli_core-2.70.0/azure/cli/core/_profile.py        2025-02-26 
07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/_profile.py        2025-03-25 
10:17:55.000000000 +0100
@@ -11,6 +11,7 @@
 from azure.cli.core._session import ACCOUNT
 from azure.cli.core.azclierror import AuthenticationError
 from azure.cli.core.cloud import get_active_cloud, set_cloud_subscription
+from azure.cli.core.auth.credential_adaptor import CredentialAdaptor
 from azure.cli.core.util import in_cloud_console, can_launch_browser, 
is_github_codespaces
 from knack.log import get_logger
 from knack.util import CLIError
@@ -60,11 +61,6 @@
 
 _AZ_LOGIN_MESSAGE = "Please run 'az login' to setup account."
 
-MANAGED_IDENTITY_ID_WARNING = (
-    "Passing the managed identity ID with --username is deprecated and will be 
removed in a future release. "
-    "Please use --client-id, --object-id or --resource-id instead."
-)
-
 
 def load_subscriptions(cli_ctx, all_clouds=False, refresh=False):
     profile = Profile(cli_ctx=cli_ctx)
@@ -226,9 +222,13 @@
 
     def login_with_managed_identity(self, identity_id=None, client_id=None, 
object_id=None, resource_id=None,
                                     allow_no_subscriptions=None):
-        if _on_azure_arc():
-            return self.login_with_managed_identity_azure_arc(
-                identity_id=identity_id, 
allow_no_subscriptions=allow_no_subscriptions)
+        if _use_msal_managed_identity(self.cli_ctx):
+            if identity_id:
+                raise CLIError('--username is not supported by MSAL managed 
identity. '
+                               'Use --client-id, --object-id or --resource-id 
instead.')
+            return self.login_with_managed_identity_msal(
+                client_id=client_id, object_id=object_id, 
resource_id=resource_id,
+                allow_no_subscriptions=allow_no_subscriptions)
 
         import jwt
         from azure.mgmt.core.tools import is_valid_resource_id
@@ -256,7 +256,6 @@
             msi_creds = MSIAuthenticationWrapper(resource=resource, 
msi_res_id=resource_id)
         # The old way of re-using the same --username for 3 types of ID
         elif identity_id:
-            logger.warning(MANAGED_IDENTITY_ID_WARNING)
             if is_valid_resource_id(identity_id):
                 msi_creds = MSIAuthenticationWrapper(resource=resource, 
msi_res_id=identity_id)
                 identity_type = MsiAccountTypes.user_assigned_resource_id
@@ -309,21 +308,23 @@
         self._set_subscriptions(consolidated)
         return deepcopy(consolidated)
 
-    def login_with_managed_identity_azure_arc(self, identity_id=None, 
allow_no_subscriptions=None):
+    def login_with_managed_identity_msal(self, client_id=None, object_id=None, 
resource_id=None,
+                                         allow_no_subscriptions=None):
         import jwt
-        identity_type = MsiAccountTypes.system_assigned
-        from .auth.msal_credentials import ManagedIdentityCredential
+        from .auth.constants import ACCESS_TOKEN
 
-        cred = ManagedIdentityCredential()
-        token = cred.get_token(*self._arm_scope).token
+        identity_id_type, identity_id_value = MsiAccountTypes.parse_ids(
+            client_id=client_id, object_id=object_id, resource_id=resource_id)
+        cred = MsiAccountTypes.msal_credential_factory(identity_id_type, 
identity_id_value)
+        token = cred.acquire_token(self._arm_scope)[ACCESS_TOKEN]
         logger.info('Managed identity: token was retrieved. Now trying to 
initialize local accounts...')
         decode = jwt.decode(token, algorithms=['RS256'], 
options={"verify_signature": False})
         tenant = decode['tid']
 
         subscription_finder = SubscriptionFinder(self.cli_ctx)
         subscriptions = subscription_finder.find_using_specific_tenant(tenant, 
cred)
-        base_name = ('{}-{}'.format(identity_type, identity_id) if identity_id 
else identity_type)
-        user = _USER_ASSIGNED_IDENTITY if identity_id else 
_SYSTEM_ASSIGNED_IDENTITY
+        base_name = ('{}-{}'.format(identity_id_type, identity_id_value) if 
identity_id_value else identity_id_type)
+        user = _USER_ASSIGNED_IDENTITY if identity_id_value else 
_SYSTEM_ASSIGNED_IDENTITY
         if not subscriptions:
             if allow_no_subscriptions:
                 subscriptions = self._build_tenant_level_accounts([tenant])
@@ -339,9 +340,10 @@
     def login_in_cloud_shell(self):
         import jwt
         from .auth.msal_credentials import CloudShellCredential
+        from .auth.constants import ACCESS_TOKEN
 
         cred = CloudShellCredential()
-        token = cred.get_token(*self._arm_scope).token
+        token = cred.acquire_token(self._arm_scope)[ACCESS_TOKEN]
         logger.info('Cloud Shell token was retrieved. Now trying to initialize 
local accounts...')
         decode = jwt.decode(token, algorithms=['RS256'], 
options={"verify_signature": False})
         tenant = decode['tid']
@@ -397,21 +399,19 @@
         if in_cloud_console() and account[_USER_ENTITY].get(_CLOUD_SHELL_ID):
             # Cloud Shell
             from .auth.msal_credentials import CloudShellCredential
-            from azure.cli.core.auth.credential_adaptor import 
CredentialAdaptor
             # The credential must be wrapped by CredentialAdaptor so that it 
can work with Track 1 SDKs.
-            cred = CredentialAdaptor(CloudShellCredential())
+            sdk_cred = CredentialAdaptor(CloudShellCredential())
 
         elif managed_identity_type:
             # managed identity
-            if _on_azure_arc():
-                from .auth.msal_credentials import ManagedIdentityCredential
-                from azure.cli.core.auth.credential_adaptor import 
CredentialAdaptor
+            if _use_msal_managed_identity(self.cli_ctx):
                 # The credential must be wrapped by CredentialAdaptor so that 
it can work with Track 1 SDKs.
-                cred = CredentialAdaptor(ManagedIdentityCredential())
+                cred = 
MsiAccountTypes.msal_credential_factory(managed_identity_type, 
managed_identity_id)
+                sdk_cred = CredentialAdaptor(cred)
             else:
                 # The resource is merely used by msrestazure to get the first 
access token.
                 # It is not actually used in an API invocation.
-                cred = MsiAccountTypes.msi_auth_factory(
+                sdk_cred = MsiAccountTypes.msi_auth_factory(
                     managed_identity_type, managed_identity_id,
                     self.cli_ctx.cloud.endpoints.active_directory_resource_id)
 
@@ -431,14 +431,14 @@
             external_credentials = []
             for external_tenant in external_tenants:
                 external_credentials.append(self._create_credential(account, 
tenant_id=external_tenant))
-            from azure.cli.core.auth.credential_adaptor import 
CredentialAdaptor
-            cred = CredentialAdaptor(credential, 
auxiliary_credentials=external_credentials)
+            sdk_cred = CredentialAdaptor(credential, 
auxiliary_credentials=external_credentials)
 
-        return (cred,
+        return (sdk_cred,
                 str(account[_SUBSCRIPTION_ID]),
                 str(account[_TENANT_ID]))
 
-    def get_raw_token(self, resource=None, scopes=None, subscription=None, 
tenant=None):
+    def get_raw_token(self, resource=None, scopes=None, subscription=None, 
tenant=None, credential_out=None):
+        # credential_out is only used by unit tests to inspect the credential. 
Do not use it!
         # Convert resource to scopes
         if resource and not scopes:
             from .auth.util import resource_to_scopes
@@ -460,24 +460,26 @@
             if tenant:
                 raise CLIError("Tenant shouldn't be specified for Cloud Shell 
account")
             from .auth.msal_credentials import CloudShellCredential
-            cred = CloudShellCredential()
+            sdk_cred = CredentialAdaptor(CloudShellCredential())
 
         elif managed_identity_type:
             # managed identity
             if tenant:
                 raise CLIError("Tenant shouldn't be specified for managed 
identity account")
-            if _on_azure_arc():
-                from .auth.msal_credentials import ManagedIdentityCredential
-                cred = ManagedIdentityCredential()
+            if _use_msal_managed_identity(self.cli_ctx):
+                cred = 
MsiAccountTypes.msal_credential_factory(managed_identity_type, 
managed_identity_id)
+                if credential_out:
+                    credential_out['credential'] = cred
+                sdk_cred = CredentialAdaptor(cred)
             else:
                 from .auth.util import scopes_to_resource
-                cred = MsiAccountTypes.msi_auth_factory(managed_identity_type, 
managed_identity_id,
-                                                        
scopes_to_resource(scopes))
+                sdk_cred = 
MsiAccountTypes.msi_auth_factory(managed_identity_type, managed_identity_id,
+                                                            
scopes_to_resource(scopes))
 
         else:
-            cred = self._create_credential(account, tenant_id=tenant)
+            sdk_cred = CredentialAdaptor(self._create_credential(account, 
tenant_id=tenant))
 
-        sdk_token = cred.get_token(*scopes)
+        sdk_token = sdk_cred.get_token(*scopes)
         # Convert epoch int 'expires_on' to datetime string 'expiresOn' for 
backward compatibility
         # WARNING: expiresOn is deprecated and will be removed in future 
release.
         import datetime
@@ -816,6 +818,41 @@
             return MSIAuthenticationWrapper(resource=resource, 
msi_res_id=identity)
         raise ValueError("unrecognized msi account name 
'{}'".format(cli_account_name))
 
+    @staticmethod
+    def parse_ids(client_id=None, object_id=None, resource_id=None):
+        id_arg_count = len([arg for arg in (client_id, object_id, resource_id) 
if arg])
+        if id_arg_count > 1:
+            raise CLIError('Usage error: Provide only one of --client-id, 
--object-id, --resource-id.')
+
+        id_type = None
+        id_value = None
+        if id_arg_count == 0:
+            id_type = MsiAccountTypes.system_assigned
+            id_value = None
+        elif client_id:
+            id_type = MsiAccountTypes.user_assigned_client_id
+            id_value = client_id
+        elif object_id:
+            id_type = MsiAccountTypes.user_assigned_object_id
+            id_value = object_id
+        elif resource_id:
+            id_type = MsiAccountTypes.user_assigned_resource_id
+            id_value = resource_id
+        return id_type, id_value
+
+    @staticmethod
+    def msal_credential_factory(id_type, id_value):
+        from azure.cli.core.auth.msal_credentials import 
ManagedIdentityCredential
+        if id_type == MsiAccountTypes.system_assigned:
+            return ManagedIdentityCredential()
+        if id_type == MsiAccountTypes.user_assigned_client_id:
+            return ManagedIdentityCredential(client_id=id_value)
+        if id_type == MsiAccountTypes.user_assigned_object_id:
+            return ManagedIdentityCredential(object_id=id_value)
+        if id_type == MsiAccountTypes.user_assigned_resource_id:
+            return ManagedIdentityCredential(resource_id=id_value)
+        raise ValueError("Unrecognized managed identity ID type 
'{}'".format(id_type))
+
 
 class SubscriptionFinder:
     # An ARM client. It finds subscriptions for a user or service principal. 
It shouldn't do any
@@ -856,7 +893,6 @@
             specific_tenant_credential = identity.get_user_credential(username)
 
             try:
-
                 subscriptions = self.find_using_specific_tenant(tenant_id, 
specific_tenant_credential,
                                                                 
tenant_id_description=t)
             except AuthenticationError as ex:
@@ -927,9 +963,12 @@
             raise CLIInternalError("Unable to get '{}' in profile '{}'"
                                    
.format(ResourceType.MGMT_RESOURCE_SUBSCRIPTIONS, self.cli_ctx.cloud.profile))
         api_version = get_api_version(self.cli_ctx, 
ResourceType.MGMT_RESOURCE_SUBSCRIPTIONS)
-        client_kwargs = _prepare_mgmt_client_kwargs_track2(self.cli_ctx, 
credential)
 
-        client = client_type(credential, api_version=api_version,
+        # MSIAuthenticationWrapper already implements get_token, so no need to 
wrap it with CredentialAdaptor
+        from azure.cli.core.auth.adal_authentication import 
MSIAuthenticationWrapper
+        sdk_cred = credential if isinstance(credential, 
MSIAuthenticationWrapper) else CredentialAdaptor(credential)
+        client_kwargs = _prepare_mgmt_client_kwargs_track2(self.cli_ctx, 
sdk_cred)
+        client = client_type(sdk_cred, api_version=api_version,
                              
base_url=self.cli_ctx.cloud.endpoints.resource_manager,
                              **client_kwargs)
         return client
@@ -980,7 +1019,9 @@
                     instance_discovery=instance_discovery)
 
 
-def _on_azure_arc():
+def _use_msal_managed_identity(cli_ctx):
     # This indicates an Azure Arc-enabled server
     from msal.managed_identity import get_managed_identity_source, AZURE_ARC
-    return get_managed_identity_source() == AZURE_ARC
+    # PREVIEW: Use core.use_msal_managed_identity=true to enable managed 
identity authentication with MSAL
+    use_msal_managed_identity = cli_ctx.config.getboolean('core', 
'use_msal_managed_identity', fallback=False)
+    return use_msal_managed_identity or get_managed_identity_source() == 
AZURE_ARC
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure/cli/core/auth/constants.py 
new/azure_cli_core-2.71.0/azure/cli/core/auth/constants.py
--- old/azure_cli_core-2.70.0/azure/cli/core/auth/constants.py  2025-02-26 
07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/auth/constants.py  2025-03-25 
10:17:55.000000000 +0100
@@ -4,3 +4,6 @@
 # 
--------------------------------------------------------------------------------------------
 
 AZURE_CLI_CLIENT_ID = '04b07795-8ddb-461a-bbee-02f9e1bf7b46'
+
+ACCESS_TOKEN = 'access_token'
+EXPIRES_IN = "expires_in"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure/cli/core/auth/credential_adaptor.py 
new/azure_cli_core-2.71.0/azure/cli/core/auth/credential_adaptor.py
--- old/azure_cli_core-2.70.0/azure/cli/core/auth/credential_adaptor.py 
2025-02-26 07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/auth/credential_adaptor.py 
2025-03-25 10:17:55.000000000 +0100
@@ -4,19 +4,19 @@
 # 
--------------------------------------------------------------------------------------------
 
 from knack.log import get_logger
+from .util import build_sdk_access_token
 
 logger = get_logger(__name__)
 
 
 class CredentialAdaptor:
     def __init__(self, credential, auxiliary_credentials=None):
-        """Cross-tenant credential adaptor. It takes a main credential and 
auxiliary credentials.
-
+        """Credential adaptor between MSAL credential and SDK credential.
         It implements Track 2 SDK's azure.core.credentials.TokenCredential by 
exposing get_token.
 
-        :param credential: Main credential from .msal_authentication
-        :param auxiliary_credentials: Credentials from .msal_authentication 
for cross tenant authentication.
-            Details about cross tenant authentication:
+        :param credential: MSAL credential from ._msal_credentials
+        :param auxiliary_credentials: MSAL credentials for cross-tenant 
authentication.
+            Details about cross-tenant authentication:
             
https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/authenticate-multi-tenant
         """
 
@@ -24,19 +24,59 @@
         self._auxiliary_credentials = auxiliary_credentials
 
     def get_token(self, *scopes, **kwargs):
-        """Get an access token from the main credential."""
+        """Implement the old SDK token protocol 
azure.core.credentials.TokenCredential
+        Return azure.core.credentials.AccessToken
+        """
         logger.debug("CredentialAdaptor.get_token: scopes=%r, kwargs=%r", 
scopes, kwargs)
 
-        # Discard unsupported kwargs: tenant_id, enable_cae
-        filtered_kwargs = {}
-        if 'data' in kwargs:
-            filtered_kwargs['data'] = kwargs['data']
+        msal_kwargs = _prepare_msal_kwargs(kwargs)
+        msal_result = self._credential.acquire_token(list(scopes), 
**msal_kwargs)
+        return build_sdk_access_token(msal_result)
+
+    def get_token_info(self, *scopes, options=None):
+        """Implement the new SDK token protocol 
azure.core.credentials.SupportsTokenInfo
+        Return azure.core.credentials.AccessTokenInfo
+        """
+        logger.debug("CredentialAdaptor.get_token_info: scopes=%r, 
options=%r", scopes, options)
 
-        return self._credential.get_token(*scopes, **filtered_kwargs)
+        msal_kwargs = _prepare_msal_kwargs(options)
+        msal_result = self._credential.acquire_token(list(scopes), 
**msal_kwargs)
+        return _build_sdk_access_token_info(msal_result)
 
     def get_auxiliary_tokens(self, *scopes, **kwargs):
         """Get access tokens from auxiliary credentials."""
         # To test cross-tenant authentication, see 
https://github.com/Azure/azure-cli/issues/16691
         if self._auxiliary_credentials:
-            return [cred.get_token(*scopes, **kwargs) for cred in 
self._auxiliary_credentials]
+            return [build_sdk_access_token(cred.acquire_token(list(scopes), 
**kwargs))
+                    for cred in self._auxiliary_credentials]
         return None
+
+
+def _prepare_msal_kwargs(options=None):
+    # Preserve supported options and discard unsupported options (tenant_id, 
enable_cae).
+    # Both get_token's kwargs and get_token_info's options are accepted as 
their schema is the same (at least for now).
+    msal_kwargs = {}
+    if options:
+        # For VM SSH. 'data' support is a CLI-specific extension.
+        # SDK doesn't support 'data': 
https://github.com/Azure/azure-sdk-for-python/pull/16397
+        if 'data' in options:
+            msal_kwargs['data'] = options['data']
+        # For CAE
+        if 'claims' in options:
+            msal_kwargs['claims_challenge'] = options['claims']
+    return msal_kwargs
+
+
+def _build_sdk_access_token_info(token_entry):
+    # MSAL token entry sample:
+    # {
+    #     'access_token': 'eyJ0eXAiOiJKV...',
+    #     'token_type': 'Bearer',
+    #     'expires_in': 1618,
+    #     'token_source': 'cache'
+    # }
+    from .constants import ACCESS_TOKEN, EXPIRES_IN
+    from .util import _now_timestamp
+    from azure.core.credentials import AccessTokenInfo
+
+    return AccessTokenInfo(token_entry[ACCESS_TOKEN], _now_timestamp() + 
token_entry[EXPIRES_IN])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure/cli/core/auth/identity.py 
new/azure_cli_core-2.71.0/azure/cli/core/auth/identity.py
--- old/azure_cli_core-2.70.0/azure/cli/core/auth/identity.py   2025-02-26 
07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/auth/identity.py   2025-03-25 
10:17:55.000000000 +0100
@@ -41,10 +41,7 @@
 
 
 class Identity:  # pylint: disable=too-many-instance-attributes
-    """Class to manage identities:
-        - user
-        - service principal
-        - TODO: managed identity
+    """Manage user or service principal identities and log into Microsoft 
identity platform.
     """
 
     # MSAL token cache.
@@ -192,20 +189,13 @@
         """
         sp_auth = ServicePrincipalAuth.build_from_credential(self.tenant_id, 
client_id, credential)
         client_credential = sp_auth.get_msal_client_credential()
-        cca = ConfidentialClientApplication(client_id, 
client_credential=client_credential, **self._msal_app_kwargs)
-        result = cca.acquire_token_for_client(scopes)
-        check_result(result)
+        cred = ServicePrincipalCredential(client_id, client_credential, 
**self._msal_app_kwargs)
+        cred.acquire_token(scopes)
 
         # Only persist the service principal after a successful login
         entry = sp_auth.get_entry_to_persist()
         self._service_principal_store.save_entry(entry)
 
-    def login_with_managed_identity(self, scopes, identity_id=None):  # 
pylint: disable=too-many-statements
-        raise NotImplementedError
-
-    def login_in_cloud_shell(self, scopes):
-        raise NotImplementedError
-
     def logout_user(self, username):
         # If username is an SP client ID, it is ignored
         accounts = self._msal_app.get_accounts(username)
@@ -252,9 +242,6 @@
         client_credential = 
ServicePrincipalAuth(entry).get_msal_client_credential()
         return ServicePrincipalCredential(client_id, client_credential, 
**self._msal_app_kwargs)
 
-    def get_managed_identity_credential(self, client_id=None):
-        raise NotImplementedError
-
 
 class ServicePrincipalAuth:  # pylint: disable=too-many-instance-attributes
     def __init__(self, entry):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure/cli/core/auth/msal_credentials.py 
new/azure_cli_core-2.71.0/azure/cli/core/auth/msal_credentials.py
--- old/azure_cli_core-2.70.0/azure/cli/core/auth/msal_credentials.py   
2025-02-26 07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/auth/msal_credentials.py   
2025-03-25 10:17:55.000000000 +0100
@@ -4,25 +4,16 @@
 # 
--------------------------------------------------------------------------------------------
 
 """
-Credentials defined in this module are alternative implementations of 
credentials provided by Azure Identity.
-
-These credentials implement azure.core.credentials.TokenCredential by exposing 
`get_token` method for Track 2
-SDK invocation.
-
-If you want to implement your own credential, the credential must also expose 
`get_token` method.
-
-`get_token` method takes `scopes` as positional arguments and other optional 
`kwargs`, such as `claims`, `data`.
-The return value should be a named tuple containing two elements: token (str), 
expires_on (int). You may simply use
-azure.cli.core.auth.util.AccessToken to build the return value. See below 
credentials as examples.
+Credentials to acquire tokens from MSAL.
 """
 
 from knack.log import get_logger
 from knack.util import CLIError
 from msal import (PublicClientApplication, ConfidentialClientApplication,
-                  ManagedIdentityClient, SystemAssignedManagedIdentity)
+                  ManagedIdentityClient, SystemAssignedManagedIdentity, 
UserAssignedManagedIdentity)
 
 from .constants import AZURE_CLI_CLIENT_ID
-from .util import check_result, build_sdk_access_token
+from .util import check_result
 
 logger = get_logger(__name__)
 
@@ -30,7 +21,7 @@
 class UserCredential:  # pylint: disable=too-few-public-methods
 
     def __init__(self, client_id, username, **kwargs):
-        """User credential implementing get_token interface.
+        """User credential wrapping msal.application.PublicClientApplication
 
         :param client_id: Client ID of the CLI.
         :param username: The username for user credential.
@@ -52,20 +43,23 @@
 
         self._account = accounts[0]
 
-    def get_token(self, *scopes, claims=None, **kwargs):
-        # scopes = ['https://pas.windows.net/CheckMyAccess/Linux/.default']
-        logger.debug("UserCredential.get_token: scopes=%r, claims=%r, 
kwargs=%r", scopes, claims, kwargs)
+    def acquire_token(self, scopes, claims_challenge=None, **kwargs):
+        # scopes must be a list.
+        # For acquiring SSH certificate, scopes is 
['https://pas.windows.net/CheckMyAccess/Linux/.default']
+        # kwargs is already sanitized by CredentialAdaptor, so it can be 
safely passed to MSAL
+        logger.debug("UserCredential.acquire_token: scopes=%r, 
claims_challenge=%r, kwargs=%r",
+                     scopes, claims_challenge, kwargs)
 
-        if claims:
+        if claims_challenge:
             logger.warning('Acquiring new access token silently for tenant %s 
with claims challenge: %s',
-                           self._msal_app.authority.tenant, claims)
-        result = self._msal_app.acquire_token_silent_with_error(list(scopes), 
self._account, claims_challenge=claims,
-                                                                **kwargs)
+                           self._msal_app.authority.tenant, claims_challenge)
+        result = self._msal_app.acquire_token_silent_with_error(
+            scopes, self._account, claims_challenge=claims_challenge, **kwargs)
 
         from azure.cli.core.azclierror import AuthenticationError
         try:
             # Check if an access token is returned.
-            check_result(result, scopes=scopes, claims=claims)
+            check_result(result, scopes=scopes, 
claims_challenge=claims_challenge)
         except AuthenticationError as ex:
             # For VM SSH ('data' is passed), if getting access token fails 
because
             # Conditional Access MFA step-up or compliance check is required, 
re-launch
@@ -82,7 +76,7 @@
                 success_template, error_template = read_response_templates()
 
                 result = self._msal_app.acquire_token_interactive(
-                    list(scopes), login_hint=self._account['username'],
+                    scopes, login_hint=self._account['username'],
                     port=8400 if self._msal_app.authority.is_adfs else None,
                     success_template=success_template, 
error_template=error_template, **kwargs)
                 check_result(result)
@@ -91,25 +85,24 @@
             # launch browser, but show the error message and `az login` 
command instead.
             else:
                 raise
-        return build_sdk_access_token(result)
+        return result
 
 
 class ServicePrincipalCredential:  # pylint: disable=too-few-public-methods
 
     def __init__(self, client_id, client_credential, **kwargs):
-        """Service principal credential implementing get_token interface.
+        """Service principal credential wrapping 
msal.application.ConfidentialClientApplication.
 
         :param client_id: The service principal's client ID.
         :param client_credential: client_credential that will be passed to 
MSAL.
         """
-        self._msal_app = ConfidentialClientApplication(client_id, 
client_credential, **kwargs)
+        self._msal_app = ConfidentialClientApplication(client_id, 
client_credential=client_credential, **kwargs)
 
-    def get_token(self, *scopes, **kwargs):
-        logger.debug("ServicePrincipalCredential.get_token: scopes=%r, 
kwargs=%r", scopes, kwargs)
-
-        result = self._msal_app.acquire_token_for_client(list(scopes), 
**kwargs)
+    def acquire_token(self, scopes, **kwargs):
+        logger.debug("ServicePrincipalCredential.acquire_token: scopes=%r, 
kwargs=%r", scopes, kwargs)
+        result = self._msal_app.acquire_token_for_client(scopes, **kwargs)
         check_result(result)
-        return build_sdk_access_token(result)
+        return result
 
 
 class CloudShellCredential:  # pylint: disable=too-few-public-methods
@@ -126,12 +119,11 @@
             #   token_cache=...
         )
 
-    def get_token(self, *scopes, **kwargs):
-        logger.debug("CloudShellCredential.get_token: scopes=%r, kwargs=%r", 
scopes, kwargs)
-        # kwargs is already sanitized by CredentialAdaptor, so it can be 
safely passed to MSAL
-        result = self._msal_app.acquire_token_interactive(list(scopes), 
prompt="none", **kwargs)
+    def acquire_token(self, scopes, **kwargs):
+        logger.debug("CloudShellCredential.acquire_token: scopes=%r, 
kwargs=%r", scopes, kwargs)
+        result = self._msal_app.acquire_token_interactive(scopes, 
prompt="none", **kwargs)
         check_result(result, scopes=scopes)
-        return build_sdk_access_token(result)
+        return result
 
 
 class ManagedIdentityCredential:  # pylint: disable=too-few-public-methods
@@ -139,14 +131,19 @@
     Currently, only Azure Arc's system-assigned managed identity is supported.
     """
 
-    def __init__(self):
+    def __init__(self, client_id=None, resource_id=None, object_id=None):
         import requests
-        self._msal_client = 
ManagedIdentityClient(SystemAssignedManagedIdentity(), 
http_client=requests.Session())
+        if client_id or resource_id or object_id:
+            managed_identity = UserAssignedManagedIdentity(
+                client_id=client_id, resource_id=resource_id, 
object_id=object_id)
+        else:
+            managed_identity = SystemAssignedManagedIdentity()
+        self._msal_client = ManagedIdentityClient(managed_identity, 
http_client=requests.Session())
 
-    def get_token(self, *scopes, **kwargs):
-        logger.debug("ManagedIdentityCredential.get_token: scopes=%r, 
kwargs=%r", scopes, kwargs)
+    def acquire_token(self, scopes, **kwargs):
+        logger.debug("ManagedIdentityCredential.acquire_token: scopes=%r, 
kwargs=%r", scopes, kwargs)
 
         from .util import scopes_to_resource
         result = 
self._msal_client.acquire_token_for_client(resource=scopes_to_resource(scopes))
         check_result(result)
-        return build_sdk_access_token(result)
+        return result
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_cli_core-2.70.0/azure/cli/core/auth/util.py 
new/azure_cli_core-2.71.0/azure/cli/core/auth/util.py
--- old/azure_cli_core-2.70.0/azure/cli/core/auth/util.py       2025-02-26 
07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/auth/util.py       2025-03-25 
10:17:55.000000000 +0100
@@ -53,7 +53,7 @@
     raise AuthenticationError(error_description, msal_error=error, 
recommendation=recommendation)
 
 
-def _generate_login_command(scopes=None, claims=None):
+def _generate_login_command(scopes=None, claims_challenge=None):
     login_command = ['az login']
 
     # Rejected by Conditional Access policy, like MFA
@@ -61,7 +61,7 @@
         login_command.append('--scope {}'.format(' '.join(scopes)))
 
     # Rejected by CAE
-    if claims:
+    if claims_challenge:
         # Explicit logout is needed: 
https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/335
         return 'az logout\n' + ' '.join(login_command)
 
@@ -140,9 +140,6 @@
 
 
 def build_sdk_access_token(token_entry):
-    import time
-    request_time = int(time.time())
-
     # MSAL token entry sample:
     # {
     #     'access_token': 'eyJ0eXAiOiJKV...',
@@ -153,7 +150,8 @@
     # Importing azure.core.credentials.AccessToken is expensive.
     # This can slow down commands that doesn't need azure.core, like `az 
account get-access-token`.
     # So We define our own AccessToken.
-    return AccessToken(token_entry["access_token"], request_time + 
token_entry["expires_in"])
+    from .constants import ACCESS_TOKEN, EXPIRES_IN
+    return AccessToken(token_entry[ACCESS_TOKEN], _now_timestamp() + 
token_entry[EXPIRES_IN])
 
 
 def decode_access_token(access_token):
@@ -177,3 +175,8 @@
         error_template = f.read()
 
     return success_template, error_template
+
+
+def _now_timestamp():
+    import time
+    return int(time.time())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure/cli/core/breaking_change.py 
new/azure_cli_core-2.71.0/azure/cli/core/breaking_change.py
--- old/azure_cli_core-2.70.0/azure/cli/core/breaking_change.py 2025-02-26 
07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/breaking_change.py 2025-03-25 
10:17:55.000000000 +0100
@@ -4,6 +4,7 @@
 # 
--------------------------------------------------------------------------------------------
 import abc
 import argparse
+import re
 from collections import defaultdict
 
 from knack.log import get_logger
@@ -14,6 +15,7 @@
 logger = get_logger()
 
 NEXT_BREAKING_CHANGE_RELEASE = '2.73.0'
+NEXT_BREAKING_CHANGE_DATE = 'May 2025'
 DEFAULT_BREAKING_CHANGE_TAG = '[Breaking Change]'
 
 
@@ -24,7 +26,7 @@
     if isinstance(action, type) and issubclass(action, argparse.Action):
         action_class = action
     elif isinstance(action, str):
-        action_class = 
cli_ctx.invocation.command_loader.cli_ctx.invocation.parser._registries['action'][action]
  # pylint: disable=protected-access
+        action_class = cli_ctx.invocation.parser._registries['action'][action] 
 # pylint: disable=protected-access
     return action_class
 
 
@@ -151,9 +153,12 @@
 class NextBreakingChangeWindow(TargetVersion):
     def __str__(self):
         next_breaking_change_version = _next_breaking_change_version()
+        message = 'in next breaking change release'
         if next_breaking_change_version:
-            return f'in next breaking change 
release({next_breaking_change_version})'
-        return 'in next breaking change release'
+            message += f'({next_breaking_change_version})'
+        if NEXT_BREAKING_CHANGE_DATE:
+            message += f' scheduled for {NEXT_BREAKING_CHANGE_DATE}'
+        return message
 
     def version(self):
         return _next_breaking_change_version()
@@ -172,6 +177,18 @@
 
 
 # pylint: disable=too-few-public-methods
+class NonVersion(TargetVersion):
+    def __init__(self, msg):
+        self._msg = msg
+
+    def __str__(self):
+        return f'in {self._msg}'
+
+    def version(self):
+        return None
+
+
+# pylint: disable=too-few-public-methods
 class UnspecificVersion(TargetVersion):
     def __str__(self):
         return 'in a future release'
@@ -192,8 +209,10 @@
         self.target = target if target else '/'.join(self.args) if self.args 
else self.cmd
         if isinstance(target_version, TargetVersion):
             self._target_version = target_version
-        elif isinstance(target_version, str):
+        elif isinstance(target_version, str) and re.match(r'\d+.\d+.\d+', 
target_version):
             self._target_version = ExactVersion(target_version)
+        elif isinstance(target_version, str):
+            self._target_version = NonVersion(target_version)
         else:
             self._target_version = UnspecificVersion()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure/cli/core/profiles/_shared.py 
new/azure_cli_core-2.71.0/azure/cli/core/profiles/_shared.py
--- old/azure_cli_core-2.70.0/azure/cli/core/profiles/_shared.py        
2025-02-26 07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/profiles/_shared.py        
2025-03-25 10:17:55.000000000 +0100
@@ -165,7 +165,7 @@
             'snapshots': '2023-10-02',
             'galleries': '2021-10-01',
             'gallery_images': '2021-10-01',
-            'gallery_image_versions': '2023-07-03',
+            'gallery_image_versions': '2024-03-03',
             'gallery_applications': '2021-07-01',
             'gallery_application_versions': '2022-01-03',
             'shared_galleries': '2022-01-03',
@@ -186,9 +186,9 @@
         ResourceType.MGMT_RESOURCE_MANAGEDAPPLICATIONS: '2019-07-01',
         ResourceType.MGMT_NETWORK_DNS: '2018-05-01',
         ResourceType.MGMT_NETWORK_PRIVATEDNS: None,
-        ResourceType.MGMT_KEYVAULT: SDKProfile('2023-07-01', {
+        ResourceType.MGMT_KEYVAULT: SDKProfile('2024-11-01', {
             'vaults': '2023-02-01',
-            'managed_hsms': '2023-07-01'
+            'managed_hsms': '2024-11-01'
         }),
         ResourceType.MGMT_AUTHORIZATION: SDKProfile('2022-04-01', {
             'classic_administrators': '2015-06-01',
@@ -216,7 +216,7 @@
         ResourceType.DATA_STORAGE: '2018-11-09',
         ResourceType.DATA_STORAGE_BLOB: '2022-11-02',
         ResourceType.DATA_STORAGE_FILEDATALAKE: '2021-08-06',
-        ResourceType.DATA_STORAGE_FILESHARE: '2024-08-04',
+        ResourceType.DATA_STORAGE_FILESHARE: '2025-05-05',
         ResourceType.DATA_STORAGE_QUEUE: '2018-03-28',
         ResourceType.DATA_COSMOS_TABLE: '2017-04-17',
         ResourceType.MGMT_SERVICEBUS: '2022-10-01-preview',
@@ -262,7 +262,7 @@
         ResourceType.MGMT_ARO: '2023-11-22',
         ResourceType.MGMT_DATABOXEDGE: '2021-02-01-preview',
         ResourceType.MGMT_CUSTOMLOCATION: '2021-03-15-preview',
-        ResourceType.MGMT_CONTAINERSERVICE: SDKProfile('2024-10-01'),
+        ResourceType.MGMT_CONTAINERSERVICE: SDKProfile('2025-01-01'),
         ResourceType.MGMT_APPCONTAINERS: '2022-10-01',
     },
     '2020-09-01-hybrid': {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_cli_core-2.70.0/azure/cli/core/util.py 
new/azure_cli_core-2.71.0/azure/cli/core/util.py
--- old/azure_cli_core-2.70.0/azure/cli/core/util.py    2025-02-26 
07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure/cli/core/util.py    2025-03-25 
10:17:55.000000000 +0100
@@ -256,8 +256,8 @@
 
 # pylint: disable=inconsistent-return-statements
 def empty_on_404(ex):
-    from msrestazure.azure_exceptions import CloudError
-    if isinstance(ex, CloudError) and ex.status_code == 404:
+    from azure.core.exceptions import HttpResponseError
+    if isinstance(ex, HttpResponseError) and ex.status_code == 404:
         return None
     raise ex
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure_cli_core.egg-info/PKG-INFO 
new/azure_cli_core-2.71.0/azure_cli_core.egg-info/PKG-INFO
--- old/azure_cli_core-2.70.0/azure_cli_core.egg-info/PKG-INFO  2025-02-26 
07:24:39.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure_cli_core.egg-info/PKG-INFO  2025-03-25 
10:18:47.000000000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: azure-cli-core
-Version: 2.70.0
+Version: 2.71.0
 Summary: Microsoft Azure Command-Line Tools Core Module
 Home-page: https://github.com/Azure/azure-cli
 Author: Microsoft Corporation
@@ -26,7 +26,7 @@
 Requires-Dist: humanfriendly~=10.0
 Requires-Dist: jmespath
 Requires-Dist: knack~=0.11.0
-Requires-Dist: microsoft-security-utilities-secret-masker~=1.0.0b2
+Requires-Dist: microsoft-security-utilities-secret-masker~=1.0.0b4
 Requires-Dist: msal-extensions==1.2.0
 Requires-Dist: msal[broker]==1.31.2b1
 Requires-Dist: msrestazure~=0.6.4
@@ -43,6 +43,7 @@
 Dynamic: description
 Dynamic: home-page
 Dynamic: license
+Dynamic: license-file
 Dynamic: requires-dist
 Dynamic: requires-python
 Dynamic: summary
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_cli_core-2.70.0/azure_cli_core.egg-info/requires.txt 
new/azure_cli_core-2.71.0/azure_cli_core.egg-info/requires.txt
--- old/azure_cli_core-2.70.0/azure_cli_core.egg-info/requires.txt      
2025-02-26 07:24:39.000000000 +0100
+++ new/azure_cli_core-2.71.0/azure_cli_core.egg-info/requires.txt      
2025-03-25 10:18:47.000000000 +0100
@@ -5,7 +5,7 @@
 humanfriendly~=10.0
 jmespath
 knack~=0.11.0
-microsoft-security-utilities-secret-masker~=1.0.0b2
+microsoft-security-utilities-secret-masker~=1.0.0b4
 msal-extensions==1.2.0
 msal[broker]==1.31.2b1
 msrestazure~=0.6.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_cli_core-2.70.0/setup.py 
new/azure_cli_core-2.71.0/setup.py
--- old/azure_cli_core-2.70.0/setup.py  2025-02-26 07:24:09.000000000 +0100
+++ new/azure_cli_core-2.71.0/setup.py  2025-03-25 10:17:55.000000000 +0100
@@ -8,7 +8,7 @@
 from codecs import open
 from setuptools import setup, find_packages
 
-VERSION = "2.70.0"
+VERSION = "2.71.0"
 
 # If we have source, validate that our version numbers match
 # This should prevent uploading releases with mismatched versions.
@@ -52,7 +52,7 @@
     'humanfriendly~=10.0',
     'jmespath',
     'knack~=0.11.0',
-    'microsoft-security-utilities-secret-masker~=1.0.0b2',
+    'microsoft-security-utilities-secret-masker~=1.0.0b4',
     'msal-extensions==1.2.0',
     'msal[broker]==1.31.2b1',
     'msrestazure~=0.6.4',

Reply via email to