diff --git a/requirements.txt b/requirements.txt index 8794f15f..936111a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ coverage==5.4 deepmerge==1.1.0 flake8==3.8.4 idna==2.10 -importlib-metadata==3.6.0 +importlib-metadata==6.5.0 isort jsonschema==4.17.3 lxml==4.9.3 diff --git a/src/core/zowe/core_for_zowe_sdk/credential_manager.py b/src/core/zowe/core_for_zowe_sdk/credential_manager.py index b4f5133a..2665251c 100644 --- a/src/core/zowe/core_for_zowe_sdk/credential_manager.py +++ b/src/core/zowe/core_for_zowe_sdk/credential_manager.py @@ -79,14 +79,14 @@ def _retrieve_credential(service_name: str) -> Optional[str]: if encoded_credential is None and sys.platform == "win32": # Retrieve the secure value with an index index = 1 - temp_value = keyring.get_password(f"{service_name}-{index}", f"{constants['ZoweAccountName']}-{index}") + temp_value = keyring.get_password(service_name, f"{constants['ZoweAccountName']}-{index}") while temp_value is not None: if encoded_credential is None: encoded_credential = temp_value else: encoded_credential += temp_value index += 1 - temp_value = keyring.get_password(f"{service_name}-{index}", f"{constants['ZoweAccountName']}-{index}") + temp_value = keyring.get_password(service_name, f"{constants['ZoweAccountName']}-{index}") return encoded_credential @@ -106,10 +106,7 @@ def delete_credential(service_name: str, account_name: str) -> None: None """ - try: - keyring.delete_password(service_name, account_name) - except keyring.errors.PasswordDeleteError: - pass + keyring.delete_password(service_name, account_name) # Handling multiple credentials stored when the operating system is Windows if sys.platform == "win32": @@ -117,9 +114,7 @@ def delete_credential(service_name: str, account_name: str) -> None: while True: field_name = f"{account_name}-{index}" service_name = f"{service_name}-{index}" - try: - keyring.delete_password(service_name, field_name) - except keyring.errors.PasswordDeleteError: + if not keyring.delete_password(service_name, field_name): break index += 1 @@ -153,7 +148,7 @@ def save_secure_props() -> None: # Set the individual chunks as separate keyring entries for index, chunk in enumerate(chunks, start=1): field_name = f"{constants['ZoweAccountName']}-{index}" - keyring.set_password(f"{service_name}-{index}", field_name, chunk) + keyring.set_password(service_name, field_name, chunk) else: # Credential length is within the maximum limit or not on win32, set it as a single keyring entry diff --git a/tests/unit/test_zowe_core.py b/tests/unit/test_zowe_core.py index 32db351a..2e504c8b 100644 --- a/tests/unit/test_zowe_core.py +++ b/tests/unit/test_zowe_core.py @@ -448,9 +448,9 @@ def test_delete_credential(self, delete_pass_func): def side_effect(*args, **kwargs): if side_effect.counter < 2: side_effect.counter += 1 - raise keyring.errors.PasswordDeleteError + return False else: - return None + return True side_effect.counter = 0 @@ -474,23 +474,21 @@ def test_retrieve_credential(self, get_pass_func): Test the _retrieve_credential method for retrieving credentials from keyring. """ credential_manager = CredentialManager() - service_name = f"{constants['ZoweServiceName']}/{constants['ZoweAccountName']}" # Scenario 1: Retrieve password directly - expected_password1 = "password".encode("utf-16le").decode() - expected_password1 = expected_password1[:-1] + expected_password1 = "password" retrieve_credential1 = credential_manager._retrieve_credential(constants["ZoweServiceName"]) self.assertEqual(retrieve_credential1, expected_password1) - get_pass_func.assert_called_with(service_name, constants["ZoweAccountName"]) + get_pass_func.assert_called_with(constants["ZoweServiceName"], constants["ZoweAccountName"]) # Scenario 2: Retrieve password in parts - expected_password2 = "part1part2".encode("utf-16le").decode() + expected_password2 = "part1part2" retrieve_credential2 = credential_manager._retrieve_credential(constants["ZoweServiceName"]) retrieve_credential2 = retrieve_credential2[:-1] self.assertEqual(retrieve_credential2, expected_password2) - get_pass_func.assert_any_call(service_name, constants["ZoweAccountName"]) - get_pass_func.assert_any_call(f"{service_name}-1", f"{constants['ZoweAccountName']}-1") - get_pass_func.assert_any_call(f"{service_name}-2", f"{constants['ZoweAccountName']}-2") + get_pass_func.assert_any_call(constants["ZoweServiceName"], constants["ZoweAccountName"]) + get_pass_func.assert_any_call(constants["ZoweServiceName"], f"{constants['ZoweAccountName']}-1") + get_pass_func.assert_any_call(constants["ZoweServiceName"], f"{constants['ZoweAccountName']}-2") @mock.patch("sys.platform", "win32") @mock.patch("zowe.secrets_for_zowe_sdk.keyring.get_password", side_effect=[None, None]) @@ -498,10 +496,9 @@ def test_retrieve_credential_encoding_errors(self, get_pass_func): """ Test the _retrieve_credential method for handling encoding errors and None values. """ - service_name = f"{constants['ZoweServiceName']}/{constants['ZoweAccountName']}" result = CredentialManager._retrieve_credential(constants["ZoweServiceName"]) self.assertIsNone(result) - get_pass_func.assert_called_with(f"{service_name}-1", f"{constants['ZoweAccountName']}-1") + get_pass_func.assert_called_with(constants["ZoweServiceName"], f"{constants['ZoweAccountName']}-1") @mock.patch("sys.platform", "win32") @mock.patch("zowe.secrets_for_zowe_sdk.keyring.set_password") @@ -512,8 +509,6 @@ def test_save_secure_props_normal_credential(self, delete_pass_func, retrieve_cr Test the save_secure_props method for saving credentials to keyring. """ - # Set up mock values and expected results - service_name = constants["ZoweServiceName"] + "/" + constants["ZoweAccountName"] # Setup - copy profile to fake filesystem created by pyfakefs cwd_up_dir_path = os.path.dirname(CWD) cwd_up_file_path = os.path.join(cwd_up_dir_path, "zowe.config.json") @@ -534,15 +529,13 @@ def test_save_secure_props_normal_credential(self, delete_pass_func, retrieve_cr # delete the existing credential delete_pass_func.return_value = None # Verify the keyring function call - set_pass_func.assert_called_once_with(service_name, constants["ZoweAccountName"], encoded_credential) + set_pass_func.assert_called_once_with(constants["ZoweServiceName"], constants["ZoweAccountName"], encoded_credential) @mock.patch("sys.platform", "win32") @mock.patch("zowe.core_for_zowe_sdk.CredentialManager._retrieve_credential") @mock.patch("zowe.secrets_for_zowe_sdk.keyring.set_password") @mock.patch("zowe.core_for_zowe_sdk.CredentialManager.delete_credential") def test_save_secure_props_exceed_limit(self, delete_pass_func, set_pass_func, retrieve_cred_func): - # Set up mock values and expected results - service_name = constants["ZoweServiceName"] + "/" + constants["ZoweAccountName"] # Setup - copy profile to fake filesystem created by pyfakefs cwd_up_dir_path = os.path.dirname(CWD) cwd_up_file_path = os.path.join(cwd_up_dir_path, "zowe.config.json") @@ -573,9 +566,7 @@ def test_save_secure_props_exceed_limit(self, delete_pass_func, set_pass_func, r ] for index, chunk in enumerate(chunks, start=1): field_name = f"{constants['ZoweAccountName']}-{index}" - service_names = f"{service_name}-{index}" - password = (chunk + "\0" * (len(chunk) % 2)).encode().decode("utf-16le") - expected_calls.append(mock.call(service_names, field_name, password)) + expected_calls.append(mock.call(constants["ZoweServiceName"], field_name, chunk)) set_pass_func.assert_has_calls(expected_calls) @mock.patch("zowe.secrets_for_zowe_sdk.keyring.get_password", side_effect=keyring_get_password)