From 398bd9fa5ba86df78f1d26363fe2147de73003c0 Mon Sep 17 00:00:00 2001 From: Siri Teja Reddy Kasireddy Date: Mon, 6 Dec 2021 19:43:16 +0530 Subject: [PATCH 1/6] Using msal token cache for az cli version >= 2.30 --- .../azext_connectedk8s/_constants.py | 1 + src/connectedk8s/azext_connectedk8s/_utils.py | 28 +++++++++- src/connectedk8s/azext_connectedk8s/custom.py | 55 ++++++++++++++----- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/connectedk8s/azext_connectedk8s/_constants.py b/src/connectedk8s/azext_connectedk8s/_constants.py index 56ae91c6de8..253de59832b 100644 --- a/src/connectedk8s/azext_connectedk8s/_constants.py +++ b/src/connectedk8s/azext_connectedk8s/_constants.py @@ -102,6 +102,7 @@ Error_disabling_Features = 'Error while updating agents for disabling features. Please run \"kubectl get pods -n azure-arc\" to check the pods in case of timeout error. Error: {}' Proxy_Kubeconfig_During_Deletion_Fault_Type = 'Encountered proxy kubeconfig during deletion.' CLIENT_PROXY_VERSION = '1.1.0' +AZ_CLI_ADAL_TO_MSAL_MIGRATE_VERSION = '2.30.0' API_SERVER_PORT = 47011 CLIENT_PROXY_PORT = 47010 CLIENTPROXY_CLIENT_ID = '04b07795-8ddb-461a-bbee-02f9e1bf7b46' diff --git a/src/connectedk8s/azext_connectedk8s/_utils.py b/src/connectedk8s/azext_connectedk8s/_utils.py index 6d16a7182b0..aa08f753c79 100644 --- a/src/connectedk8s/azext_connectedk8s/_utils.py +++ b/src/connectedk8s/azext_connectedk8s/_utils.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- +from logging import exception import os import shutil import subprocess @@ -25,7 +26,8 @@ from azext_connectedk8s._client_factory import _resource_client_factory import azext_connectedk8s._constants as consts from kubernetes import client as kube_client -from azure.cli.core.azclierror import CLIInternalError, ClientRequestError, ArgumentUsageError, ManualInterrupt, AzureResponseError, AzureInternalError, ValidationError +from azure.cli.core import get_default_cli +from packaging import version logger = get_logger(__name__) @@ -389,3 +391,27 @@ def names(self, names): V1ContainerImage.names = V1ContainerImage.names.setter(names) except Exception as ex: logger.debug("Error while trying to monkey patch the fix for list_node(): {}".format(str(ex))) + + +def use_msal_cache(): + response_cli_version = az_cli("version --output json") + try: + cli_version = response_cli_version['azure-cli'] + except Exception as ex: + raise CLIInternalError("Unable to decode the az cli version installed: {}".format(str(ex))) + if version.parse(cli_version) >= version.parse(consts.AZ_CLI_ADAL_TO_MSAL_MIGRATE_VERSION): + return True + else: + return False + + +def az_cli (args_str): + args = args_str.split() + cli = get_default_cli() + cli.invoke(args, out_file = open(os.devnull, 'w')) + if cli.result.result: + return cli.result.result + elif cli.result.error: + raise cli.result.error + return True + diff --git a/src/connectedk8s/azext_connectedk8s/custom.py b/src/connectedk8s/azext_connectedk8s/custom.py index 469caa6c019..f7c2979f253 100644 --- a/src/connectedk8s/azext_connectedk8s/custom.py +++ b/src/connectedk8s/azext_connectedk8s/custom.py @@ -14,6 +14,7 @@ import stat import platform from azure.core.exceptions import ClientAuthenticationError +from msal_extensions.token_cache import PersistedTokenCache import yaml import requests import urllib.request @@ -25,6 +26,7 @@ from knack.prompting import prompt_y_n from knack.prompting import NoTTYException from azure.cli.core.commands.client_factory import get_subscription_id +from msal import PublicClientApplication, ConfidentialClientApplication from azure.cli.core._profile import Profile from azure.cli.core.util import sdk_no_wait from azure.cli.core import telemetry @@ -41,9 +43,11 @@ from azext_connectedk8s._client_factory import get_graph_client_service_principals import azext_connectedk8s._constants as consts import azext_connectedk8s._utils as utils +from azext_connectedk8s._utils import az_cli from glob import glob from .vendored_sdks.models import ConnectedCluster, ConnectedClusterIdentity from threading import Timer, Thread +import msal_extensions import sys import hashlib import re @@ -54,7 +58,6 @@ # pylint: disable=too-many-statements # pylint: disable=line-too-long - def create_connectedk8s(cmd, client, resource_group_name, cluster_name, https_proxy="", http_proxy="", no_proxy="", proxy_cert="", location=None, kube_config=None, kube_context=None, no_wait=False, tags=None, distribution='auto', infrastructure='auto', disable_auto_upgrade=False, cl_oid=None): @@ -1596,12 +1599,16 @@ def client_side_proxy_wrapper(cmd, requestUri = f'{consts.CSP_Storage_Url}/{consts.RELEASE_DATE_WINDOWS}/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}.exe' older_version_string = f'.clientproxy\\arcProxy{operating_system}*.exe' creds_string = r'.azure\accessTokens.json' + msal_token_cache_user = r'.azure\msal_token_cache.bin' + msal_token_cache_spn = r'.azure\service_principal_entries.bin' elif(operating_system == 'Linux' or operating_system == 'Darwin'): install_location_string = f'.clientproxy/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}' requestUri = f'{consts.CSP_Storage_Url}/{consts.RELEASE_DATE_LINUX}/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}' older_version_string = f'.clientproxy/arcProxy{operating_system}*' creds_string = r'.azure/accessTokens.json' + msal_token_cache_user = r'.azure/msal_token_cache.bin' + msal_token_cache_spn = r'.azure/service_principal_entries.bin' else: telemetry.set_exception(exception='Unsupported OS', fault_type=consts.Unsupported_Fault_Type, @@ -1699,21 +1706,41 @@ def client_side_proxy_wrapper(cmd, raise FileOperationError("Failed to load credentials." + str(e)) user_name = account['user']['name'] + use_msal_cache = utils.use_msal_cache() + if not use_msal_cache: + if user_type == 'user': + key = 'userId' + key2 = 'refreshToken' + else: + key = 'servicePrincipalId' + key2 = 'accessToken' - if user_type == 'user': - key = 'userId' - key2 = 'refreshToken' - else: - key = 'servicePrincipalId' - key2 = 'accessToken' - - for i in range(len(creds_list)): - creds_obj = creds_list[i] - - if key in creds_obj and creds_obj[key] == user_name: - creds = creds_obj[key2] - break + for i in range(len(creds_list)): + creds_obj = creds_list[i] + if key in creds_obj and creds_obj[key] == user_name: + creds = creds_obj[key2] + break + else: + if user_type == "user": + response_user_objectid = az_cli("ad signed-in-user show --query objectId -o tsv") + token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_user)) + persistence=msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + token_cache=msal_extensions.PersistedTokenCache(persistence) + token_cache._reload_if_necessary() + home_account_id = response_user_objectid + "." + tenantId + owned_by_home_account = { + "home_account_id": home_account_id} + creds_info = token_cache.find(PersistedTokenCache.CredentialType.REFRESH_TOKEN, query=owned_by_home_account) + creds = creds_info[0]['secret'] + else: + token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_spn)) + persistence=msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + token_cache=msal_extensions.PersistedTokenCache(persistence) + token_cache._reload_if_necessary() + token_cache_string = token_cache.serialize() + cache_list = json.loads(token_cache_string) + creds = cache_list[0]['client_secret'] if creds == '': telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, summary='Unable to find creds of user') From c296d6c1aaabf6df351adea9ccc49de837b5d1c4 Mon Sep 17 00:00:00 2001 From: Siri Teja Reddy Kasireddy Date: Mon, 6 Dec 2021 19:43:16 +0530 Subject: [PATCH 2/6] Using msal token cache for az cli version >= 2.30 --- .../azext_connectedk8s/_constants.py | 1 + src/connectedk8s/azext_connectedk8s/_utils.py | 27 +++++++++ src/connectedk8s/azext_connectedk8s/custom.py | 55 ++++++++++++++----- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/connectedk8s/azext_connectedk8s/_constants.py b/src/connectedk8s/azext_connectedk8s/_constants.py index 56ae91c6de8..253de59832b 100644 --- a/src/connectedk8s/azext_connectedk8s/_constants.py +++ b/src/connectedk8s/azext_connectedk8s/_constants.py @@ -102,6 +102,7 @@ Error_disabling_Features = 'Error while updating agents for disabling features. Please run \"kubectl get pods -n azure-arc\" to check the pods in case of timeout error. Error: {}' Proxy_Kubeconfig_During_Deletion_Fault_Type = 'Encountered proxy kubeconfig during deletion.' CLIENT_PROXY_VERSION = '1.1.0' +AZ_CLI_ADAL_TO_MSAL_MIGRATE_VERSION = '2.30.0' API_SERVER_PORT = 47011 CLIENT_PROXY_PORT = 47010 CLIENTPROXY_CLIENT_ID = '04b07795-8ddb-461a-bbee-02f9e1bf7b46' diff --git a/src/connectedk8s/azext_connectedk8s/_utils.py b/src/connectedk8s/azext_connectedk8s/_utils.py index 6d16a7182b0..422a1b611eb 100644 --- a/src/connectedk8s/azext_connectedk8s/_utils.py +++ b/src/connectedk8s/azext_connectedk8s/_utils.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- +from logging import exception import os import shutil import subprocess @@ -26,6 +27,8 @@ import azext_connectedk8s._constants as consts from kubernetes import client as kube_client from azure.cli.core.azclierror import CLIInternalError, ClientRequestError, ArgumentUsageError, ManualInterrupt, AzureResponseError, AzureInternalError, ValidationError +from azure.cli.core import get_default_cli +from packaging import version logger = get_logger(__name__) @@ -389,3 +392,27 @@ def names(self, names): V1ContainerImage.names = V1ContainerImage.names.setter(names) except Exception as ex: logger.debug("Error while trying to monkey patch the fix for list_node(): {}".format(str(ex))) + + +def use_msal_cache(): + response_cli_version = az_cli("version --output json") + try: + cli_version = response_cli_version['azure-cli'] + except Exception as ex: + raise CLIInternalError("Unable to decode the az cli version installed: {}".format(str(ex))) + if version.parse(cli_version) >= version.parse(consts.AZ_CLI_ADAL_TO_MSAL_MIGRATE_VERSION): + return True + else: + return False + + +def az_cli (args_str): + args = args_str.split() + cli = get_default_cli() + cli.invoke(args, out_file = open(os.devnull, 'w')) + if cli.result.result: + return cli.result.result + elif cli.result.error: + raise cli.result.error + return True + diff --git a/src/connectedk8s/azext_connectedk8s/custom.py b/src/connectedk8s/azext_connectedk8s/custom.py index 469caa6c019..f7c2979f253 100644 --- a/src/connectedk8s/azext_connectedk8s/custom.py +++ b/src/connectedk8s/azext_connectedk8s/custom.py @@ -14,6 +14,7 @@ import stat import platform from azure.core.exceptions import ClientAuthenticationError +from msal_extensions.token_cache import PersistedTokenCache import yaml import requests import urllib.request @@ -25,6 +26,7 @@ from knack.prompting import prompt_y_n from knack.prompting import NoTTYException from azure.cli.core.commands.client_factory import get_subscription_id +from msal import PublicClientApplication, ConfidentialClientApplication from azure.cli.core._profile import Profile from azure.cli.core.util import sdk_no_wait from azure.cli.core import telemetry @@ -41,9 +43,11 @@ from azext_connectedk8s._client_factory import get_graph_client_service_principals import azext_connectedk8s._constants as consts import azext_connectedk8s._utils as utils +from azext_connectedk8s._utils import az_cli from glob import glob from .vendored_sdks.models import ConnectedCluster, ConnectedClusterIdentity from threading import Timer, Thread +import msal_extensions import sys import hashlib import re @@ -54,7 +58,6 @@ # pylint: disable=too-many-statements # pylint: disable=line-too-long - def create_connectedk8s(cmd, client, resource_group_name, cluster_name, https_proxy="", http_proxy="", no_proxy="", proxy_cert="", location=None, kube_config=None, kube_context=None, no_wait=False, tags=None, distribution='auto', infrastructure='auto', disable_auto_upgrade=False, cl_oid=None): @@ -1596,12 +1599,16 @@ def client_side_proxy_wrapper(cmd, requestUri = f'{consts.CSP_Storage_Url}/{consts.RELEASE_DATE_WINDOWS}/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}.exe' older_version_string = f'.clientproxy\\arcProxy{operating_system}*.exe' creds_string = r'.azure\accessTokens.json' + msal_token_cache_user = r'.azure\msal_token_cache.bin' + msal_token_cache_spn = r'.azure\service_principal_entries.bin' elif(operating_system == 'Linux' or operating_system == 'Darwin'): install_location_string = f'.clientproxy/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}' requestUri = f'{consts.CSP_Storage_Url}/{consts.RELEASE_DATE_LINUX}/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}' older_version_string = f'.clientproxy/arcProxy{operating_system}*' creds_string = r'.azure/accessTokens.json' + msal_token_cache_user = r'.azure/msal_token_cache.bin' + msal_token_cache_spn = r'.azure/service_principal_entries.bin' else: telemetry.set_exception(exception='Unsupported OS', fault_type=consts.Unsupported_Fault_Type, @@ -1699,21 +1706,41 @@ def client_side_proxy_wrapper(cmd, raise FileOperationError("Failed to load credentials." + str(e)) user_name = account['user']['name'] + use_msal_cache = utils.use_msal_cache() + if not use_msal_cache: + if user_type == 'user': + key = 'userId' + key2 = 'refreshToken' + else: + key = 'servicePrincipalId' + key2 = 'accessToken' - if user_type == 'user': - key = 'userId' - key2 = 'refreshToken' - else: - key = 'servicePrincipalId' - key2 = 'accessToken' - - for i in range(len(creds_list)): - creds_obj = creds_list[i] - - if key in creds_obj and creds_obj[key] == user_name: - creds = creds_obj[key2] - break + for i in range(len(creds_list)): + creds_obj = creds_list[i] + if key in creds_obj and creds_obj[key] == user_name: + creds = creds_obj[key2] + break + else: + if user_type == "user": + response_user_objectid = az_cli("ad signed-in-user show --query objectId -o tsv") + token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_user)) + persistence=msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + token_cache=msal_extensions.PersistedTokenCache(persistence) + token_cache._reload_if_necessary() + home_account_id = response_user_objectid + "." + tenantId + owned_by_home_account = { + "home_account_id": home_account_id} + creds_info = token_cache.find(PersistedTokenCache.CredentialType.REFRESH_TOKEN, query=owned_by_home_account) + creds = creds_info[0]['secret'] + else: + token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_spn)) + persistence=msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + token_cache=msal_extensions.PersistedTokenCache(persistence) + token_cache._reload_if_necessary() + token_cache_string = token_cache.serialize() + cache_list = json.loads(token_cache_string) + creds = cache_list[0]['client_secret'] if creds == '': telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, summary='Unable to find creds of user') From 0039e5f79db73d3e4148da3912d771516ab0dd70 Mon Sep 17 00:00:00 2001 From: Siri Teja Reddy Kasireddy Date: Mon, 6 Dec 2021 20:13:38 +0530 Subject: [PATCH 3/6] indentation fixes --- src/connectedk8s/azext_connectedk8s/_utils.py | 6 +++--- src/connectedk8s/azext_connectedk8s/custom.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/connectedk8s/azext_connectedk8s/_utils.py b/src/connectedk8s/azext_connectedk8s/_utils.py index bd45e446c3e..149ae8acb22 100644 --- a/src/connectedk8s/azext_connectedk8s/_utils.py +++ b/src/connectedk8s/azext_connectedk8s/_utils.py @@ -413,16 +413,16 @@ def use_msal_cache(): return False -def az_cli (args_str): +def az_cli(args_str): args = args_str.split() cli = get_default_cli() - cli.invoke(args, out_file = open(os.devnull, 'w')) + cli.invoke(args, out_file=open(os.devnull, 'w')) if cli.result.result: return cli.result.result elif cli.result.error: raise cli.result.error return True - + def check_provider_registrations(cli_ctx): try: diff --git a/src/connectedk8s/azext_connectedk8s/custom.py b/src/connectedk8s/azext_connectedk8s/custom.py index cda02469ba2..2822595518f 100644 --- a/src/connectedk8s/azext_connectedk8s/custom.py +++ b/src/connectedk8s/azext_connectedk8s/custom.py @@ -57,6 +57,7 @@ # pylint: disable=too-many-statements # pylint: disable=line-too-long + def create_connectedk8s(cmd, client, resource_group_name, cluster_name, https_proxy="", http_proxy="", no_proxy="", proxy_cert="", location=None, kube_config=None, kube_context=None, no_wait=False, tags=None, distribution='auto', infrastructure='auto', disable_auto_upgrade=False, cl_oid=None, onboarding_timeout="600"): @@ -1764,18 +1765,17 @@ def client_side_proxy_wrapper(cmd, if user_type == "user": response_user_objectid = az_cli("ad signed-in-user show --query objectId -o tsv") token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_user)) - persistence=msal_extensions.FilePersistenceWithDataProtection(token_cache_location) - token_cache=msal_extensions.PersistedTokenCache(persistence) + persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + token_cache = msal_extensions.PersistedTokenCache(persistence) token_cache._reload_if_necessary() home_account_id = response_user_objectid + "." + tenantId - owned_by_home_account = { - "home_account_id": home_account_id} + owned_by_home_account = {"home_account_id": home_account_id} creds_info = token_cache.find(PersistedTokenCache.CredentialType.REFRESH_TOKEN, query=owned_by_home_account) creds = creds_info[0]['secret'] else: token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_spn)) - persistence=msal_extensions.FilePersistenceWithDataProtection(token_cache_location) - token_cache=msal_extensions.PersistedTokenCache(persistence) + persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + token_cache = msal_extensions.PersistedTokenCache(persistence) token_cache._reload_if_necessary() token_cache_string = token_cache.serialize() cache_list = json.loads(token_cache_string) From 96bd30f755bd5c9893846c7a91bdb61ee6ab2ddf Mon Sep 17 00:00:00 2001 From: Siri Teja Reddy Kasireddy Date: Mon, 6 Dec 2021 20:22:34 +0530 Subject: [PATCH 4/6] indentation fix --- src/connectedk8s/azext_connectedk8s/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connectedk8s/azext_connectedk8s/_utils.py b/src/connectedk8s/azext_connectedk8s/_utils.py index 149ae8acb22..572388d3319 100644 --- a/src/connectedk8s/azext_connectedk8s/_utils.py +++ b/src/connectedk8s/azext_connectedk8s/_utils.py @@ -422,7 +422,7 @@ def az_cli(args_str): elif cli.result.error: raise cli.result.error return True - + def check_provider_registrations(cli_ctx): try: From 29cbd57b702d92e70230f18cf38f149b3d02aebd Mon Sep 17 00:00:00 2001 From: Siri Teja Reddy Kasireddy Date: Wed, 8 Dec 2021 15:19:15 +0530 Subject: [PATCH 5/6] history changes --- src/connectedk8s/HISTORY.rst | 1 + .../azext_connectedk8s/_constants.py | 1 + src/connectedk8s/azext_connectedk8s/custom.py | 55 +++++++++++++------ src/connectedk8s/setup.py | 2 +- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/connectedk8s/HISTORY.rst b/src/connectedk8s/HISTORY.rst index f4e4636f31f..9b1238aadaf 100644 --- a/src/connectedk8s/HISTORY.rst +++ b/src/connectedk8s/HISTORY.rst @@ -5,6 +5,7 @@ Release History 1.2.0 ++++++ +* Using MSAL from az-cli version >= 2.30.0 * Updated CSP version to 1.3.017131 * Updated GA SDK to 2021-10-01 * Updated CSP endpoint to CDN diff --git a/src/connectedk8s/azext_connectedk8s/_constants.py b/src/connectedk8s/azext_connectedk8s/_constants.py index 05bad7f7892..d95d4c16031 100644 --- a/src/connectedk8s/azext_connectedk8s/_constants.py +++ b/src/connectedk8s/azext_connectedk8s/_constants.py @@ -73,6 +73,7 @@ Remove_Config_Fault_Type = "Error while removing old csp config" Load_Creds_Fault_Type = "Error while loading accessToken.json" Creds_NotFound_Fault_Type = "Credentials of user not found" +MSAL_cache_not_retrieved_Fault_Type = "MSAL cache could not be retrieved" Create_Config_Fault_Type = "Error while creating config file for proxy" Run_RefreshThread_Fault_Type = "Error while starting refresh thread" Load_Kubeconfig_Fault_Type = "Error while loading kubeconfig" diff --git a/src/connectedk8s/azext_connectedk8s/custom.py b/src/connectedk8s/azext_connectedk8s/custom.py index 2822595518f..6560c56077e 100644 --- a/src/connectedk8s/azext_connectedk8s/custom.py +++ b/src/connectedk8s/azext_connectedk8s/custom.py @@ -1647,8 +1647,8 @@ def client_side_proxy_wrapper(cmd, requestUri = f'{consts.CSP_Storage_Url}/{consts.RELEASE_DATE_LINUX}/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}' older_version_string = f'.clientproxy/arcProxy{operating_system}*' creds_string = r'.azure/accessTokens.json' - msal_token_cache_user = r'.azure/msal_token_cache.bin' - msal_token_cache_spn = r'.azure/service_principal_entries.bin' + msal_token_cache_user = r'.azure/msal_token_cache.json' + msal_token_cache_spn = r'.azure/service_principal_entries.json' else: telemetry.set_exception(exception='Unsupported OS', fault_type=consts.Unsupported_Fault_Type, @@ -1761,30 +1761,53 @@ def client_side_proxy_wrapper(cmd, if key in creds_obj and creds_obj[key] == user_name: creds = creds_obj[key2] break + if creds == '': + telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, + summary='Unable to find creds of user while using ADAL') + raise UnclassifiedUserFault("Credentials of user not found.") else: if user_type == "user": response_user_objectid = az_cli("ad signed-in-user show --query objectId -o tsv") token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_user)) - persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) - token_cache = msal_extensions.PersistedTokenCache(persistence) + try: + if operating_system == 'Windows': + persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + elif operating_system == 'Darwin': + persistence = msal_extensions.KeychainPersistence(token_cache_location) + else: + persistence = msal_extensions.FilePersistence(token_cache_location) + token_cache = msal_extensions.PersistedTokenCache(persistence) + except Exception as e: + telemetry.set_exception(exception=e, fault_type=consts.MSAL_cache_not_retrieved_Fault_Type, + summary='Unable to retrieve MSAL cache') + raise CLIInternalError("Failed to authenticate with the cluster") token_cache._reload_if_necessary() home_account_id = response_user_objectid + "." + tenantId owned_by_home_account = {"home_account_id": home_account_id} - creds_info = token_cache.find(PersistedTokenCache.CredentialType.REFRESH_TOKEN, query=owned_by_home_account) - creds = creds_info[0]['secret'] + creds_list = token_cache.find(PersistedTokenCache.CredentialType.REFRESH_TOKEN, query=owned_by_home_account) + creds = creds_list[0]['secret'] else: token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_spn)) - persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) - token_cache = msal_extensions.PersistedTokenCache(persistence) + try: + if operating_system == 'Windows': + persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + elif operating_system == 'Darwin': + persistence = msal_extensions.KeychainPersistence(token_cache_location) + else: + persistence = msal_extensions.FilePersistence(token_cache_location) + token_cache = msal_extensions.PersistedTokenCache(persistence) + except Exception as e: + telemetry.set_exception(exception=e, fault_type=consts.MSAL_cache_not_retrieved_Fault_Type, + summary='Unable to retrieve MSAL cache') + raise CLIInternalError("Failed to authenticate with the cluster") token_cache._reload_if_necessary() - token_cache_string = token_cache.serialize() - cache_list = json.loads(token_cache_string) - creds = cache_list[0]['client_secret'] - if creds == '': - telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, - summary='Unable to find creds of user') - raise UnclassifiedUserFault("Credentials of user not found.") - + token_cache_decrypted = token_cache.serialize() + creds_list = json.loads(token_cache_decrypted) + creds = creds_list[0]['client_secret'] + if creds == '': + telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, + summary='Unable to find creds of user while using MSAL') + raise UnclassifiedUserFault("Credentials of user not found.") if user_type != 'user': dict_file['identity']['clientSecret'] = creds else: diff --git a/src/connectedk8s/setup.py b/src/connectedk8s/setup.py index 6223f2dd686..1ef4a25820d 100644 --- a/src/connectedk8s/setup.py +++ b/src/connectedk8s/setup.py @@ -17,7 +17,7 @@ # TODO: Confirm this is the right version number you want and it matches your # HISTORY.rst entry. -VERSION = '1.2.0' +VERSION = '1.2.1' # The full list of classifiers is available at # https://pypi.python.org/pypi?%3Aaction=list_classifiers From 96cb409a206801638814d02990a82a161be024cb Mon Sep 17 00:00:00 2001 From: Siri Teja Reddy Kasireddy Date: Wed, 8 Dec 2021 15:19:15 +0530 Subject: [PATCH 6/6] history changes --- src/connectedk8s/HISTORY.rst | 1 + .../azext_connectedk8s/_constants.py | 1 + src/connectedk8s/azext_connectedk8s/custom.py | 51 +++++++++++++------ src/connectedk8s/setup.py | 2 +- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/connectedk8s/HISTORY.rst b/src/connectedk8s/HISTORY.rst index f4e4636f31f..9b1238aadaf 100644 --- a/src/connectedk8s/HISTORY.rst +++ b/src/connectedk8s/HISTORY.rst @@ -5,6 +5,7 @@ Release History 1.2.0 ++++++ +* Using MSAL from az-cli version >= 2.30.0 * Updated CSP version to 1.3.017131 * Updated GA SDK to 2021-10-01 * Updated CSP endpoint to CDN diff --git a/src/connectedk8s/azext_connectedk8s/_constants.py b/src/connectedk8s/azext_connectedk8s/_constants.py index 05bad7f7892..d95d4c16031 100644 --- a/src/connectedk8s/azext_connectedk8s/_constants.py +++ b/src/connectedk8s/azext_connectedk8s/_constants.py @@ -73,6 +73,7 @@ Remove_Config_Fault_Type = "Error while removing old csp config" Load_Creds_Fault_Type = "Error while loading accessToken.json" Creds_NotFound_Fault_Type = "Credentials of user not found" +MSAL_cache_not_retrieved_Fault_Type = "MSAL cache could not be retrieved" Create_Config_Fault_Type = "Error while creating config file for proxy" Run_RefreshThread_Fault_Type = "Error while starting refresh thread" Load_Kubeconfig_Fault_Type = "Error while loading kubeconfig" diff --git a/src/connectedk8s/azext_connectedk8s/custom.py b/src/connectedk8s/azext_connectedk8s/custom.py index 2822595518f..41846f3ba53 100644 --- a/src/connectedk8s/azext_connectedk8s/custom.py +++ b/src/connectedk8s/azext_connectedk8s/custom.py @@ -1647,8 +1647,8 @@ def client_side_proxy_wrapper(cmd, requestUri = f'{consts.CSP_Storage_Url}/{consts.RELEASE_DATE_LINUX}/arcProxy{operating_system}{consts.CLIENT_PROXY_VERSION}' older_version_string = f'.clientproxy/arcProxy{operating_system}*' creds_string = r'.azure/accessTokens.json' - msal_token_cache_user = r'.azure/msal_token_cache.bin' - msal_token_cache_spn = r'.azure/service_principal_entries.bin' + msal_token_cache_user = r'.azure/msal_token_cache.json' + msal_token_cache_spn = r'.azure/service_principal_entries.json' else: telemetry.set_exception(exception='Unsupported OS', fault_type=consts.Unsupported_Fault_Type, @@ -1761,30 +1761,49 @@ def client_side_proxy_wrapper(cmd, if key in creds_obj and creds_obj[key] == user_name: creds = creds_obj[key2] break + if creds == '': + telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, + summary='Unable to find creds of user while using ADAL') + raise UnclassifiedUserFault("Credentials of user not found.") else: if user_type == "user": response_user_objectid = az_cli("ad signed-in-user show --query objectId -o tsv") token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_user)) - persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) - token_cache = msal_extensions.PersistedTokenCache(persistence) + try: + if operating_system == 'Windows': + persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + else: + persistence = msal_extensions.FilePersistence(token_cache_location) + token_cache = msal_extensions.PersistedTokenCache(persistence) + except Exception as e: + telemetry.set_exception(exception=e, fault_type=consts.MSAL_cache_not_retrieved_Fault_Type, + summary='Unable to retrieve MSAL cache') + raise CLIInternalError("Failed to authenticate with the cluster") token_cache._reload_if_necessary() home_account_id = response_user_objectid + "." + tenantId owned_by_home_account = {"home_account_id": home_account_id} - creds_info = token_cache.find(PersistedTokenCache.CredentialType.REFRESH_TOKEN, query=owned_by_home_account) - creds = creds_info[0]['secret'] + creds_list = token_cache.find(PersistedTokenCache.CredentialType.REFRESH_TOKEN, query=owned_by_home_account) + creds = creds_list[0]['secret'] else: token_cache_location = os.path.expanduser(os.path.join('~', msal_token_cache_spn)) - persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) - token_cache = msal_extensions.PersistedTokenCache(persistence) + try: + if operating_system == 'Windows': + persistence = msal_extensions.FilePersistenceWithDataProtection(token_cache_location) + else: + persistence = msal_extensions.FilePersistence(token_cache_location) + token_cache = msal_extensions.PersistedTokenCache(persistence) + except Exception as e: + telemetry.set_exception(exception=e, fault_type=consts.MSAL_cache_not_retrieved_Fault_Type, + summary='Unable to retrieve MSAL cache') + raise CLIInternalError("Failed to authenticate with the cluster") token_cache._reload_if_necessary() - token_cache_string = token_cache.serialize() - cache_list = json.loads(token_cache_string) - creds = cache_list[0]['client_secret'] - if creds == '': - telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, - summary='Unable to find creds of user') - raise UnclassifiedUserFault("Credentials of user not found.") - + token_cache_decrypted = token_cache.serialize() + creds_list = json.loads(token_cache_decrypted) + creds = creds_list[0]['client_secret'] + if creds == '': + telemetry.set_exception(exception='Credentials of user not found.', fault_type=consts.Creds_NotFound_Fault_Type, + summary='Unable to find creds of user while using MSAL') + raise UnclassifiedUserFault("Credentials of user not found.") if user_type != 'user': dict_file['identity']['clientSecret'] = creds else: diff --git a/src/connectedk8s/setup.py b/src/connectedk8s/setup.py index 6223f2dd686..1ef4a25820d 100644 --- a/src/connectedk8s/setup.py +++ b/src/connectedk8s/setup.py @@ -17,7 +17,7 @@ # TODO: Confirm this is the right version number you want and it matches your # HISTORY.rst entry. -VERSION = '1.2.0' +VERSION = '1.2.1' # The full list of classifiers is available at # https://pypi.python.org/pypi?%3Aaction=list_classifiers