import pytest from MicrosoftApiModule import AZURE_WORLDWIDE_CLOUD import os import time users_list_mock = [ { "id": "08779ba7-f3ed-4344-b9d7-98b9911ea8a8", "displayName": "Test User", "jobTitle": "Magician", "mobilePhone": None, "mail": None, }, { "id": "670edadc-0197-45b0-90e6-ee061e25ab73", "displayName": "Test1", "jobTitle": "TESTER", "mobilePhone": "050505050", "mail": None, "@removed": {"reason": "changed"}, }, ] expected_outputs = [ { "ID": "08779ba7-f3ed-4344-b9d7-98b9911ea8a8", "DisplayName": "Test User", "JobTitle": "Magician", "MobilePhone": None, "Mail": None, }, { "ID": "670edadc-0197-45b0-90e6-ee061e25ab73", "DisplayName": "Test1", "JobTitle": "TESTER", "MobilePhone": "050505050", "Mail": None, "Status": "deleted", }, ] @pytest.fixture def client(): from MicrosoftGraphUser import MsGraphClient return MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-user", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) def test_camel_case_to_readable(): from MicrosoftGraphUser import camel_case_to_readable assert camel_case_to_readable("id") == "ID" assert camel_case_to_readable("createdDateTime") == "Created Date Time" def test_parse_outputs(): from MicrosoftGraphUser import parse_outputs _, parsed_outputs = parse_outputs(users_list_mock) assert parsed_outputs == expected_outputs def test_get_user_command_404_response(mocker): """ Given: - The get_user_command When: - The returned response is a 404 - not found error. Then: - Validate that the error is handled and that the human readable indicates an error. """ from MicrosoftApiModule import BaseClient, MicrosoftClient from MicrosoftGraphUser import MsGraphClient, get_user_command from requests.models import Response client = MsGraphClient( "tenant_id", "auth_id", "enc_key", "app_name", "base_url", "verify", "proxy", "self_deployed", "redirect_uri", "auth_code", True, azure_cloud=AZURE_WORLDWIDE_CLOUD, ) error_404 = Response() error_404._content = ( b'{"error": {"code": "Request_ResourceNotFound", "message": "Resource "NotExistingUser does not exist."}}' ) error_404.status_code = 404 mocker.patch.object(BaseClient, "_http_request", return_value=error_404) mocker.patch.object(MicrosoftClient, "get_access_token") output = get_user_command(client, {"user": "NotExistingUser"}) # client.get_user('user', 'properties') assert "User NotExistingUser was not found" in output.readable_output def test_get_user_command_url_saved_chars(mocker): """ Given: - The get_user_command When: - The returned response is a 404 - not found error. Then: - Validate that the error is handled and that the human readable indicates an error. """ from MicrosoftApiModule import BaseClient, MicrosoftClient from MicrosoftGraphUser import MsGraphClient, get_user_command user_name = "dbot^" client = MsGraphClient( "tenant_id", "auth_id", "enc_key", "app_name", "http://base_url", "verify", "proxy", "self_deployed", "redirect_uri", "auth_code", False, azure_cloud=AZURE_WORLDWIDE_CLOUD, ) http_mock = mocker.patch.object(BaseClient, "_http_request") mocker.patch.object(MicrosoftClient, "get_access_token") _ = get_user_command(client, {"user": user_name}) assert http_mock.call_args[1]["url_suffix"] == "users/dbot%5E" def test_get_unsupported_chars_in_user(): """ Given: - User with unsupported characters When: - Calling get_unsupported_chars_in_user Then: - Validate special characters were extracted """ from MicrosoftGraphUser import get_unsupported_chars_in_user invalid_chars = "%&*+/=?`{|}" invalid_user = f"demi{invalid_chars}sto" result = get_unsupported_chars_in_user(invalid_user) assert len(result.difference(set(invalid_chars))) == 0, "All invalid characters should be extracted." # Test case with None as user result = get_unsupported_chars_in_user(None) assert result == set(), "Expected an empty set when user is None." # Test case with an empty string as user result = get_unsupported_chars_in_user("") assert result == set(), "Expected an empty set when user is an empty string." def test_suppress_errors(mocker): from MicrosoftApiModule import NotFoundError from MicrosoftGraphUser import ( MsGraphClient, assign_manager_command, change_password_user_saas_command, delete_user_command, disable_user_account_command, get_direct_reports_command, get_manager_command, revoke_user_session_command, unblock_user_command, update_user_command, list_tap_policy_command, delete_tap_policy_command, create_tap_policy_command, list_fido2_method_command, list_email_method_command, list_authenticator_method_command, list_phone_method_command, list_software_oath_method_command, list_windows_hello_method_command, delete_fido2_method_command, delete_email_method_command, delete_authenticator_method_command, delete_phone_method_command, delete_software_oath_method_command, delete_windows_hello_method_command, ) TEST_SUPPRESS_ERRORS = [ { "fun": unblock_user_command, "mock_fun": "unblock_user", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": disable_user_account_command, "mock_fun": "disable_user_account_session", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": update_user_command, "mock_fun": "update_user", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789", "updated_fields": "test1=test2"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": change_password_user_saas_command, "mock_fun": "password_change_user_saas", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": delete_user_command, "mock_fun": "delete_user", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": get_direct_reports_command, "mock_fun": "get_direct_reports", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": get_manager_command, "mock_fun": "get_manager", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": assign_manager_command, "mock_fun": "assign_manager", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": assign_manager_command, "mock_fun": "assign_manager", "mock_value": NotFoundError("123456789"), "args": {"manager": "123456789"}, "expected_result": "#### Manager -> 123456789 does not exist", }, { "fun": revoke_user_session_command, "mock_fun": "revoke_user_session", "mock_value": NotFoundError("123456789"), "args": {"user": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": list_tap_policy_command, "mock_fun": "list_tap_policy", "mock_value": NotFoundError("The specified user could not be found."), "args": {"user_id": "123456789"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": delete_tap_policy_command, "mock_fun": "delete_tap_policy", "mock_value": NotFoundError("The specified user could not be found."), "args": {"user_id": "123456789", "policy_id": "987654321"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": create_tap_policy_command, "mock_fun": "create_tap_policy", "mock_value": NotFoundError("The specified user could not be found."), "args": {"user_id": "123456789", "zip_password": "12345"}, "expected_result": "#### User -> 123456789 does not exist", }, { "fun": list_authenticator_method_command, "mock_fun": "get_authenticator_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": list_fido2_method_command, "mock_fun": "get_fido2_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": list_email_method_command, "mock_fun": "get_email_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": list_phone_method_command, "mock_fun": "get_phone_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": list_software_oath_method_command, "mock_fun": "get_software_oath_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": list_windows_hello_method_command, "mock_fun": "get_windows_hello_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": delete_authenticator_method_command, "mock_fun": "delete_authenticator_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": delete_fido2_method_command, "mock_fun": "delete_fido2_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": delete_email_method_command, "mock_fun": "delete_email_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": delete_phone_method_command, "mock_fun": "delete_phone_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": delete_software_oath_method_command, "mock_fun": "delete_software_oath_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, { "fun": delete_windows_hello_method_command, "mock_fun": "delete_windows_hello_method", "mock_value": NotFoundError("A key with identifier '123' was not found for user 'test-user'"), "args": {"user": "test-user", "method_id": "123"}, "expected_result": "#### Did not find the method_id 123 for user test-user", }, ] client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) for test in TEST_SUPPRESS_ERRORS: mocker.patch.object(client, test["mock_fun"], side_effect=test["mock_value"]) results = test["fun"](client, test["args"]) assert results == test["expected_result"] USERS_LIST_MOCK = [ { "ID": "08779ba7-f3ed-4344-b9d7-98b9911ea8a8", "DisplayName": "Test User", "UserPrincipalName": None, "JobTitle": "Magician", "MobilePhone": None, "Mail": None, }, { "ID": "670edadc-0197-45b0-90e6-ee061e25ab73", "DisplayName": "Test1", "UserPrincipalName": "PrincipalTest", "JobTitle": "TESTER", "MobilePhone": "050505050", "Mail": "test@test.com", }, ] USERS_JSON_MOCK = { "ID": "6705dadc-0197-45b4-9fe6-ee061e25abf7", "DisplayName": "Test2", "UserPrincipalName": "PrincipalTest2", "JobTitle": "TESTER2", "MobilePhone": "02020202", "Mail": "test2@test2.com", } @pytest.mark.parametrize("users_mock", [(USERS_LIST_MOCK), (USERS_JSON_MOCK)]) def test_create_account_outputs(users_mock): from MicrosoftGraphUser import create_account_outputs results = create_account_outputs(users_mock) if not isinstance(users_mock, list): users_mock = [users_mock] for i in range(len(results)): assert results[i]["DisplayName"] == users_mock[i]["DisplayName"] assert results[i]["Email"]["Address"] == users_mock[i]["Mail"] assert results[i]["Username"] == users_mock[i]["UserPrincipalName"] @pytest.mark.parametrize( "user, updated_fields, updated_fields_delimiter, expected_request_params", [ # A case with a single field to update. ( "1875cf67-ebf9-4a29-b5e2-54e36591296e", "displayName=test_name1", None, { "json_data": {"displayName": "test_name1"}, "method": "PATCH", "resp_type": "text", "url_suffix": "users/1875cf67-ebf9-4a29-b5e2-54e36591296e", }, ), # A case with multiple fields to update. ( "1875cf67-ebf9-4a29-b5e2-54e36591296e", "displayName=test_name2,jobTitle=test_title,phoneNumber=123456789", None, { "json_data": {"displayName": "test_name2", "jobTitle": "test_title", "phoneNumber": "123456789"}, "method": "PATCH", "resp_type": "text", "url_suffix": "users/1875cf67-ebf9-4a29-b5e2-54e36591296e", }, ), # A case with multiple fields to update and a custom delimiter. ( "1875cf67-ebf9-4a29-b5e2-54e36591296e", "displayName=test_name3;jobTitle=test_title;phoneNumber=123456789", ";", { "json_data": {"displayName": "test_name3", "jobTitle": "test_title", "phoneNumber": "123456789"}, "method": "PATCH", "resp_type": "text", "url_suffix": "users/1875cf67-ebf9-4a29-b5e2-54e36591296e", }, ), ], ) def test_update_user_command( mocker, user: str, updated_fields: str, updated_fields_delimiter: str, expected_request_params: dict ): """ Given: - User to update with fields to update. When: - Calling update_user. Then: - Ensure the user is updated. """ from MicrosoftGraphUser import MsGraphClient, update_user_command client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) request = mocker.patch.object(client.ms_client, "http_request", return_value={}) mocker.patch.object(client, "get_user", return_value={}) args = {"user": user, "updated_fields": updated_fields} if updated_fields_delimiter is not None: args["updated_fields_delimiter"] = updated_fields_delimiter update_user_command(client=client, args=args) request.assert_called_with(**expected_request_params) @pytest.mark.parametrize(argnames="client_id", argvalues=["test_client_id", None]) def test_test_module_command_with_managed_identities(mocker, requests_mock, client_id): """ Given: - Managed Identities client id for authentication. When: - Calling test_module. Then: - Ensure the output are as expected. """ import re import demistomock as demisto from MicrosoftGraphUser import MANAGED_IDENTITIES_TOKEN_URL, Resources, main mock_token = {"access_token": "test_token", "expires_in": "86400"} get_mock = requests_mock.get(MANAGED_IDENTITIES_TOKEN_URL, json=mock_token) requests_mock.get(re.compile(f"^{Resources.graph}.*"), json={}) params = {"managed_identities_client_id": {"password": client_id}, "use_managed_identities": "True", "host": Resources.graph} mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "command", return_value="test-module") mocker.patch.object(demisto, "results", return_value=params) mocker.patch("MicrosoftApiModule.get_integration_context", return_value={}) main() assert "ok" in demisto.results.call_args[0][0] qs = get_mock.last_request.qs assert qs["resource"] == [Resources.graph] assert (client_id and qs["client_id"] == [client_id]) or "client_id" not in qs def test_generate_login_url(mocker): """ Given: - Self-deployed are true and auth code are the auth flow When: - Calling function msgraph-user-generate-login-url - Ensure the generated url are as expected. """ # prepare import demistomock as demisto import MicrosoftGraphUser from MicrosoftGraphUser import Scopes, main redirect_uri = "redirect_uri" tenant_id = "tenant_id" client_id = "client_id" mocked_params = { "redirect_uri": redirect_uri, "auth_type": "Authorization Code", "self_deployed": "True", "creds_tenant_id": {"password": tenant_id}, "creds_auth_id": {"password": client_id}, "creds_enc_key": {"password": "client_secret"}, } mocker.patch.object(demisto, "params", return_value=mocked_params) mocker.patch.object(demisto, "command", return_value="msgraph-user-generate-login-url") mocker.patch.object(MicrosoftGraphUser, "return_results") # call main() # assert expected_url = ( f"[login URL](https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize?" f"response_type=code&scope=offline_access%20{Scopes.graph}" f"&client_id={client_id}&redirect_uri={redirect_uri})" ) res = MicrosoftGraphUser.return_results.call_args[0][0].readable_output assert expected_url in res @pytest.mark.parametrize( "grant_type, self_deployed, expected_result, should_raise", [ ("authorization_code", False, "ok", False), ("authorization_code", True, "ok", True), ("client_credentials", False, "ok", False), ("client_credentials", True, "```✅ Success!```", False), ], ) def test_test_function(mocker, grant_type, self_deployed, expected_result, should_raise): """ Given: - Authentication method and self_deployed information. When: - Calling test_module. Then: - Ensure the output are as expected. """ import demistomock as demisto from MicrosoftGraphUser import MsGraphClient, test_function client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="user", verify="use_ssl", proxy="proxies", self_deployed=self_deployed, handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) client.ms_client.grant_type = grant_type mocker.patch.object(demisto, "params", return_value={"self_deployed": self_deployed}) mocker.patch.object(client.ms_client, "http_request") if should_raise: with pytest.raises(Exception) as exc: test_function(client, {}) assert "Please enable the integration" in str(exc) else: result = test_function(client, {}) assert result == expected_result def test_create_zip_with_password(): """ Tests the creation of a password-protected ZIP file containing a Temporary Access Pass (TAP) password. Validates that the correct TAP password is stored in the ZIP file, and cleans up any files created during the test. Given: - A generated TAP password, a password for protected-zip file, file names. When: - Running the generate_password_protected_zip function. Then: 1. Generates a password protected zip file, that will include the password of the new TAP. 2. Verifies that the returned 'File' field matches the expected ZIP file name - TAPPolicyInfo.zip. 3. Confirms that the 'ContentsFormat' field in the result is 'text'. 3. Opens the zip file using the given password by the user. 4. Validates the password inside 'TAPPolicyPass.txt' matches the generated TAP password. 5. Clean all the encrypted files created during the process. """ from pyzipper import AESZipFile, ZIP_DEFLATED, WZ_AES from MicrosoftGraphUser import generate_password_protected_zip def clean_up_files(created_time): cwd = os.getcwd() for filename in os.listdir(cwd): file_path = os.path.join(cwd, filename) if os.path.isfile(file_path): file_creation_time = os.path.getctime(file_path) if file_creation_time > created_time: try: os.remove(file_path) except Exception as e: pytest.fail(f"Error removing {file_path}: {e}") generated_tap_password = "test_password_123" zip_password = "kldsjflk453lksdf" zip_file_name = os.path.join(os.getcwd(), "TAPPolicyInfo.zip") txt_file_name = "TAPPolicyPass.txt" start_time = time.time() zip_res = generate_password_protected_zip("TAPPolicyInfo.zip", zip_password, generated_tap_password) assert zip_res["File"] == "TAPPolicyInfo.zip" assert zip_res["ContentsFormat"] == "text" try: with AESZipFile(zip_file_name, mode="r", compression=ZIP_DEFLATED, encryption=WZ_AES) as zf: zf.pwd = bytes(zip_password, "utf-8") zip_content = zf.read(txt_file_name) assert zip_content.decode("utf-8") == generated_tap_password except Exception as e: pytest.fail(f"Unexpected error during ZIP file handling: {e}") finally: clean_up_files(start_time) def test_create_tap_policy_command_failure_on_empty_response(mocker): """ Tests the behavior of the create_tap_policy_command function when an empty response is returned from the Microsoft Graph API for creating a TAP policy. Verifies that the command correctly handles the failure and outputs an appropriate error message. Given: - A mock client instance for the Microsoft Graph API. When: - Running the create_tap_policy_command. Then: 1. Verify that the human readable output is as expected. 2. verify that the call count for the mocker was 1 """ from MicrosoftGraphUser import MsGraphClient, create_tap_policy_command client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_id": "123456789", "zip_password": "12345"} mock_create_tap_policy = mocker.patch.object(client, "create_tap_policy", return_value=None) result = create_tap_policy_command(client, args) assert result.readable_output == "Failed to create TAP policy for user: 123456789." assert mock_create_tap_policy.call_count == 1 def test_delete_tap_policy_command_success(mocker): """ Tests the behavior of the delete_tap_policy_command function. Validates that the human readable is as expected and the command returns CommandResults object. Given: - A mock client instance for the Microsoft Graph API. When: - Running the delete_tap_policy_command. Then: 1. Verify that the human readable output is as expected. """ from MicrosoftGraphUser import MsGraphClient, delete_tap_policy_command client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_id": "123456789", "policy_id": "987654321"} mocker.patch.object(client, "delete_tap_policy", return_value=None) result = delete_tap_policy_command(client, args) expected_output = "Temporary Access Pass Authentication methods policy 987654321 was successfully deleted." assert result.readable_output == expected_output def test_list_tap_policy_command_success(mocker): """ Tests the successful execution of the list_tap_policy_command function in the MicrosoftGraphUser module. Validates that the function correctly retrieves and formats the Temporary Access Pass (TAP) policy data. Given: - A mock client instance for the Microsoft Graph API. When: - Running the list_tap_policy_command function with the mock client and arguments. Then: 1. Mocks the list_tap_policy API call to return predefined TAP policy data. 2. Mocks the parse_outputs function to simulate parsed readable and output data. 3. Asserts that the output prefix is correctly set to 'MSGraphUser.TAPPolicy'. 4. Confirms that the output key field is 'ID' and the correct TAP policy ID is returned. 5. Ensures that the readable output contains the correct policy information and user ID. """ from MicrosoftGraphUser import MsGraphClient, list_tap_policy_command client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_id": "123456789"} mock_tap_data = [ { "id": "987654321", "startDateTime": "2025-04-28T12:00:00Z", "lifetimeInMinutes": 60, "isUsableOnce": True, "isUsable": True, "methodUsabilityReason": "Enabled", "TemporaryAccessPass": "test123", } ] mocker.patch.object(client, "list_tap_policy", return_value=mock_tap_data) result = list_tap_policy_command(client, args) assert result.outputs_prefix == "MSGraphUser.TAPPolicy" assert result.outputs_key_field == "ID" # Just check the readable output contains expected information assert "Policy ID" in result.readable_output assert "TAP Policy for User ID 123456789" in result.readable_output def test_create_tap_policy_command_success(mocker): """ Tests the successful execution of the create_tap_policy_command function in the MicrosoftGraphUser module. Validates that the function correctly creates a Temporary Access Pass (TAP) policy and returns the expected results. Given: - A mock client instance for the Microsoft Graph API. When: - Running the create_tap_policy_command function with the mock client and arguments. Then: 1. Mocks the create_tap_policy API call to return predefined API response for the TAP policy creation. 2. Mocks the create_zip_with_password function. 3. Mocks the parse_outputs function to simulate parsed output data. 4. Confirms that the readable output contains the expected success message for the TAP policy creation. 5. Ensures that the output prefix is set to 'MSGraphUser.TAPPolicy' and the key field is 'ID'. 6. Verifies that the correct TAP policy ID is included in the output. """ from MicrosoftGraphUser import MsGraphClient, create_tap_policy_command client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = { "user_id": "123456789", "zip_password": "securepass123", "lifetime_in_minutes": "60", "is_usable_once": "true", "start_time": "2025-04-29T10:00:00Z", } mock_api_response = { "id": "987654321", "startDateTime": "2025-04-29T10:00:00.000Z", "lifetimeInMinutes": 60, "isUsableOnce": True, "isUsable": True, "methodUsabilityReason": "Enabled", "temporaryAccessPass": "Generated-P@ssword1!", } mocker.patch.object(client, "create_tap_policy", return_value=mock_api_response) mocker.patch("MicrosoftGraphUser.create_zip_with_password") result = create_tap_policy_command(client, args) expected_output = "Temporary Access Pass Authentication methods policy for user: 123456789 was successfully created." assert result.readable_output == expected_output assert result.outputs_prefix == "MSGraphUser.TAPPolicy" assert result.outputs_key_field == "ID" # Just check the readable output contains expected information @pytest.mark.parametrize( "args", [{"password": "aa", "nonsensitive_password": "aa"}, {"password": "aa"}, {"nonsensitive_password": "aa"}] ) def test_get_password_valid(args): """ Given - arguments for the script When - running the script on a password locked file Then - ensure that only one of the arguments 'password' or 'nonsensitive_password' is given or if they are identical. """ from MicrosoftGraphUser import validate_input_password assert validate_input_password(args) == "aa" def test_get_password_invalid(): """ Given - arguments for the script When - running the script on a password locked file Then - ensure that only one of the arguments 'password' or 'nonsensitive_password' is given or if they are identical. """ from MicrosoftGraphUser import validate_input_password, DemistoException with pytest.raises(DemistoException) as e: validate_input_password({"password": "aa", "nonsensitive_password": "bb"}) assert ( "Conflicting passwords provided. The 'password' and 'nonsensitive_password' arguments must have the same value, or use only one of them." # noqa: E501 in str(e.value) # noqa: E501 ) def test_change_password_user_on_premise_command_initiation(mocker): """ Tests the initiation phase of the change_password_user_on_premise_command function. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and password When: - Running the change_password_user_on_premise_command for the first time (initiation phase) Then: - Verify that the password method ID is fetched correctly - Verify that the password reset is initiated with the correct parameters - Verify that the function returns a PollResult with the correct arguments for the next run """ from MicrosoftGraphUser import MsGraphClient, change_password_user_on_premise_command from CommonServerPython import CommandResults # Create a mock client client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-user", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) # Mock the fetch_password_method_id method mock_password_method_id = "password-method-id-123" mocker.patch.object(client, "fetch_password_method_id", return_value=mock_password_method_id) # Mock the password_change_user_on_premise method mock_polling_url = "https://graph.microsoft.com/v1.0/users/test-user/operations/123" mocker.patch.object(client, "password_change_user_on_premise", return_value=mock_polling_url) # Mock demisto.debug to avoid errors mocker.patch("demistomock.debug") # Create arguments for the command args = {"user": "test-user", "password": "Test@Password123"} # Call the function result = change_password_user_on_premise_command(args, client) # Verify the result assert isinstance(result, CommandResults) assert "Password reset initiated for **test-user**" in result.readable_output def test_change_password_user_on_premise_command_polling_success(mocker): """ Tests the polling phase of the change_password_user_on_premise_command function when the operation succeeds. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and polling_url When: - Running the change_password_user_on_premise_command for a subsequent time (polling phase) - The operation status is "succeeded" Then: - Verify that the polling URL is checked correctly - Verify that the function returns a PollResult with the correct results """ from MicrosoftGraphUser import MsGraphClient, change_password_user_on_premise_command from CommonServerPython import CommandResults # Create a mock client client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-user", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) # Mock the http_request method to return a success status mock_polling_url = "https://graph.microsoft.com/v1.0/users/test-user/operations/123" mock_status_response = {"status": "succeeded"} mocker.patch.object(client.ms_client, "http_request", return_value=mock_status_response) # Mock demisto.debug to avoid errors mocker.patch("demistomock.debug") # Create arguments for the command args = {"user": "test-user", "polling_url": mock_polling_url} # Call the function result = change_password_user_on_premise_command(args, client) # Verify the result assert isinstance(result, CommandResults) assert "Password reset **succeeded** for user **test-user**" in result.readable_output assert result.outputs_prefix == "MSGraphUser.PasswordResetOperation" def test_change_password_user_on_premise_command_polling_failed(mocker): """ Tests the polling phase of the change_password_user_on_premise_command function when the operation fails. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and polling_url When: - Running the change_password_user_on_premise_command for a subsequent time (polling phase) - The operation status is "failed" Then: - Verify that the polling URL is checked correctly - Verify that the function raises a DemistoException with the correct error message """ import pytest from MicrosoftGraphUser import MsGraphClient, change_password_user_on_premise_command, DemistoException # Create a mock client client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-user", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) # Mock the http_request method to return a failed status mock_polling_url = "https://graph.microsoft.com/v1.0/users/test-user/operations/123" mock_status_response = {"status": "failed", "error": {"message": "Password does not meet complexity requirements"}} mocker.patch.object(client.ms_client, "http_request", return_value=mock_status_response) # Mock demisto.debug to avoid errors mocker.patch("demistomock.debug") # Create arguments for the command args = {"user": "test-user", "polling_url": mock_polling_url} # Call the function and verify it raises the expected exception with pytest.raises(DemistoException) as e: change_password_user_on_premise_command(args, client) assert "Password reset **failed** for user **test-user**" in str(e.value) assert "Password does not meet complexity requirements" in str(e.value) def test_change_password_user_on_premise_command_polling_running(mocker): """ Tests the polling phase of the change_password_user_on_premise_command function when the operation is still running. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and polling_url When: - Running the change_password_user_on_premise_command for a subsequent time (polling phase) - The operation status is "running" Then: - Verify that the polling URL is checked correctly - Verify that the function returns a PollResult indicating to continue polling """ from MicrosoftGraphUser import MsGraphClient, change_password_user_on_premise_command from CommonServerPython import CommandResults # Create a mock client client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-user", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) # Mock the http_request method to return a running status mock_polling_url = "https://graph.microsoft.com/v1.0/users/test-user/operations/123" mock_status_response = {"status": "running"} mocker.patch.object(client.ms_client, "http_request", return_value=mock_status_response) # Mock demisto.debug to avoid errors mocker.patch("demistomock.debug") # Create arguments for the command args = {"user": "test-user", "polling_url": mock_polling_url} # Call the function result = change_password_user_on_premise_command(args, client) # Verify the result # The function might return a CommandResults directly instead of a PollResult # Let's check the readable output instead assert isinstance(result, CommandResults) assert "Password reset status for **test-user** is **running**" in result.readable_output def test_change_password_user_on_premise_command_initiation_error(mocker): """ Tests the initiation phase of the change_password_user_on_premise_command function when an error occurs. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and password When: - Running the change_password_user_on_premise_command for the first time (initiation phase) - An error occurs during the initiation Then: - Verify that the function raises a DemistoException with the correct error message """ import pytest from MicrosoftGraphUser import MsGraphClient, change_password_user_on_premise_command, DemistoException # Create a mock client client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-user", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) # Mock the fetch_password_method_id method to raise an exception error_message = "Failed to fetch password method ID" mocker.patch.object(client, "fetch_password_method_id", side_effect=DemistoException(error_message)) # Mock demisto.debug to avoid errors mocker.patch("demistomock.debug") # Create arguments for the command args = {"user": "test-user", "password": "Test@Password123"} # Call the function and verify it raises the expected exception with pytest.raises(DemistoException) as e: change_password_user_on_premise_command(args, client) # The error message from the function is just the original exception message assert error_message in str(e.value) def test_get_groups_command(mocker): """ Given: - The get_groups_command When: - The returned response is a list of groups. Then: - Validate that the outputs and human readable are as expected. """ from MicrosoftGraphUser import MsGraphClient, get_groups_command client = MsGraphClient( "tenant_id", "auth_id", "enc_key", "app_name", "base_url", "verify", "proxy", "self_deployed", "redirect_uri", "auth_code", True, azure_cloud=AZURE_WORLDWIDE_CLOUD, ) mock_group_data = {"value": [{"id": "group-id-1", "displayName": "Group 1", "description": "Description 1"}]} mocker.patch.object(client, "get_groups", return_value=mock_group_data) args = {"user": "test-user"} result = get_groups_command(client, args) assert result.outputs_prefix == "MSGraphUserGroups" assert result.outputs_key_field == "ID" assert result.outputs["ID"] == "test-user" assert result.outputs["Groups"][0]["ID"] == "group-id-1" assert "test-user group data" in result.readable_output def test_get_auth_methods_command(mocker): """ Given: - The get_auth_methods_command When: - The returned response is a list of auth methods. Then: - Validate that the outputs and human readable are as expected. """ from MicrosoftGraphUser import MsGraphClient, get_auth_methods_command client = MsGraphClient( "tenant_id", "auth_id", "enc_key", "app_name", "base_url", "verify", "proxy", "self_deployed", "redirect_uri", "auth_code", True, azure_cloud=AZURE_WORLDWIDE_CLOUD, ) mock_auth_data = [{"id": "auth-id-1", "displayName": "Auth Method 1"}] mocker.patch.object(client, "get_auth_methods", return_value=mock_auth_data) args = {"user": "test-user"} result = get_auth_methods_command(client, args) assert result.outputs_prefix == "MSGraphUserAuthMethods" assert result.outputs_key_field == "ID" assert result.outputs["ID"] == "test-user" assert result.outputs["Methods"][0]["ID"] == "auth-id-1" assert "test-user - auth methods" in result.readable_output def test_map_auth_method_fields_to_readable_single_dict(): """ Tests the map_auth_method_fields_to_readable function with a single dictionary. Given: - A single dictionary with authentication method data - A field mapping dictionary When: - Calling map_auth_method_fields_to_readable Then: - Verify that the fields are correctly mapped to custom headers - Verify that unmapped fields remain unchanged """ from MicrosoftGraphUser import map_auth_method_fields_to_readable input_data = { "ID": "method-id-123", "Display Name": "Test Device", "Key Strength": "normal", "Created Date Time": "2025-01-01T00:00:00Z", } field_mapping = {"ID": "Windows Hello Method ID", "Key Strength": "Method Key Strength"} result = map_auth_method_fields_to_readable(input_data, field_mapping) assert result["Windows Hello Method ID"] == "method-id-123" assert result["Display Name"] == "Test Device" # Unmapped field stays the same assert result["Method Key Strength"] == "normal" assert result["Created Date Time"] == "2025-01-01T00:00:00Z" # Unmapped field stays the same def test_map_auth_method_fields_to_readable_list(): """ Tests the map_auth_method_fields_to_readable function with a list of dictionaries. Given: - A list of dictionaries with authentication method data - A field mapping dictionary When: - Calling map_auth_method_fields_to_readable Then: - Verify that all items in the list are correctly mapped - Verify that the function returns a list """ from MicrosoftGraphUser import map_auth_method_fields_to_readable input_data = [ {"ID": "fido2-id-1", "Display Name": "Security Key 1", "Aa Guid": "guid-123"}, {"ID": "fido2-id-2", "Display Name": "Security Key 2", "Aa Guid": "guid-456"}, ] field_mapping = { "ID": "Authentication method ID", "Display Name": "The display name of the key", "Aa Guid": "Authenticator Attestation GUID", } result = map_auth_method_fields_to_readable(input_data, field_mapping) assert isinstance(result, list) assert len(result) == 2 assert result[0]["Authentication method ID"] == "fido2-id-1" assert result[0]["The display name of the key"] == "Security Key 1" assert result[0]["Authenticator Attestation GUID"] == "guid-123" assert result[1]["Authentication method ID"] == "fido2-id-2" assert result[1]["The display name of the key"] == "Security Key 2" assert result[1]["Authenticator Attestation GUID"] == "guid-456" def test_map_auth_method_fields_to_readable_empty_mapping(): """ Tests the map_auth_method_fields_to_readable function with an empty field mapping. Given: - A dictionary with authentication method data - An empty field mapping dictionary When: - Calling map_auth_method_fields_to_readable Then: - Verify that all fields remain unchanged """ from MicrosoftGraphUser import map_auth_method_fields_to_readable input_data = {"ID": "method-id-123", "Display Name": "Test Device", "Phone Number": "+1234567890"} field_mapping = {} result = map_auth_method_fields_to_readable(input_data, field_mapping) assert result["ID"] == "method-id-123" assert result["Display Name"] == "Test Device" assert result["Phone Number"] == "+1234567890" def test_map_auth_method_fields_to_readable_partial_mapping(): """ Tests the map_auth_method_fields_to_readable function with partial field mapping. Given: - A dictionary with multiple fields - A field mapping that only maps some of the fields When: - Calling map_auth_method_fields_to_readable Then: - Verify that mapped fields are renamed - Verify that unmapped fields keep their original names """ from MicrosoftGraphUser import map_auth_method_fields_to_readable input_data = {"ID": "phone-id-123", "Phone Number": "+1234567890", "Phone Type": "mobile", "Sms Sign In State": "ready"} field_mapping = {"ID": "Phone ID", "Sms Sign In State": "Sms SignIn State"} result = map_auth_method_fields_to_readable(input_data, field_mapping) assert result["Phone ID"] == "phone-id-123" assert result["Phone Number"] == "+1234567890" # Unmapped assert result["Phone Type"] == "mobile" # Unmapped assert result["Sms SignIn State"] == "ready" def test_list_fido2_method_command_list_all(mocker, client): """ Tests the list_fido2_method_command function when listing all FIDO2 methods for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_fido2_method_command without a method_id Then: - Verify that the function returns the correct FIDO2 methods - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_fido2_method_command args = {"user": "test-user", "limit": "50"} mock_fido2_data = [ { "id": "fido2-method-id-1", "displayName": "Security Key 1", "createdDateTime": "2025-01-01T00:00:00Z", "aaGuid": "guid-123", "model": "YubiKey 5", "attestationLevel": "attested", } ] mocker.patch.object(client, "list_fido2_methods", return_value=mock_fido2_data) result = list_fido2_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.FIDO2Method" assert result.outputs_key_field == "ID" assert "FIDO2 Authentication Methods for User test-user" in result.readable_output def test_list_fido2_method_command_get_specific(mocker, client): """ Tests the list_fido2_method_command function when retrieving a specific FIDO2 method. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the list_fido2_method_command with a method_id Then: - Verify that the function returns the correct FIDO2 method - Verify that the output contains the method_id in the title """ from MicrosoftGraphUser import list_fido2_method_command args = {"user": "test-user", "method_id": "fido2-method-id-1"} mock_fido2_data = { "id": "fido2-method-id-1", "displayName": "Security Key 1", "createdDateTime": "2025-01-01T00:00:00Z", "aaGuid": "guid-123", } mocker.patch.object(client, "get_fido2_method", return_value=mock_fido2_data) result = list_fido2_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.FIDO2Method" assert "FIDO2 Authentication Method fido2-method-id-1 for User test-user" in result.readable_output def test_delete_fido2_method_command(mocker, client): """ Tests the delete_fido2_method_command function. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the delete_fido2_method_command Then: - Verify that the function returns the correct success message """ from MicrosoftGraphUser import delete_fido2_method_command args = {"user": "test-user", "method_id": "fido2-method-id-1"} mocker.patch.object(client, "delete_fido2_method", return_value=None) result = delete_fido2_method_command(client, args) assert "FIDO2 Security Key Authentication Method fido2-method-id-1 has been successfully deleted" in result.readable_output def test_list_email_method_command_list_all(mocker, client): """ Tests the list_email_method_command function when listing all email methods for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_email_method_command without a method_id Then: - Verify that the function returns the correct email methods - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_email_method_command args = {"user": "test-user"} mock_email_data = [ { "id": "email-method-id-1", "emailAddress": "test@example.com", } ] mocker.patch.object(client, "list_email_methods", return_value=mock_email_data) result = list_email_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.EmailAuthMethod" assert result.outputs_key_field == "ID" assert "Email Authentication Methods for User test-user" in result.readable_output def test_list_email_method_command_get_specific(mocker, client): """ Tests the list_email_method_command function when retrieving a specific email method. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the list_email_method_command with a method_id Then: - Verify that the function returns the correct email method - Verify that the output contains the method_id in the title """ from MicrosoftGraphUser import list_email_method_command args = {"user": "test-user", "method_id": "email-method-id-1"} mock_email_data = { "id": "email-method-id-1", "emailAddress": "test@example.com", } mocker.patch.object(client, "get_email_method", return_value=mock_email_data) result = list_email_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.EmailAuthMethod" assert "Email Authentication Method email-method-id-1 for User test-user" in result.readable_output def test_delete_email_method_command(mocker, client): """ Tests the delete_email_method_command function. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the delete_email_method_command Then: - Verify that the function returns the correct success message """ from MicrosoftGraphUser import delete_email_method_command args = {"user": "test-user", "method_id": "email-method-id-1"} mocker.patch.object(client, "delete_email_method", return_value=None) result = delete_email_method_command(client, args) assert "Email Authentication Method object email-method-id-1 has been successfully deleted" in result.readable_output def test_list_authenticator_method_command_list_all(mocker, client): """ Tests the list_authenticator_method_command function when listing all authenticator methods for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_authenticator_method_command without a method_id Then: - Verify that the function returns the correct authenticator methods - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_authenticator_method_command args = {"user": "test-user", "limit": "50"} mock_authenticator_data = [ { "id": "auth-method-id-1", "displayName": "iPhone 12", "phoneAppVersion": "6.5.0", "createdDateTime": "2025-01-01T00:00:00Z", } ] mocker.patch.object(client, "list_authenticator_methods", return_value=(mock_authenticator_data, None)) result = list_authenticator_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.UserAuthMethod" assert result.outputs_key_field == "ID" assert "Microsoft Authenticator Authentication Methods for User test-user" in result.readable_output def test_list_authenticator_method_command_get_specific(mocker, client): """ Tests the list_authenticator_method_command function when retrieving a specific authenticator method. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the list_authenticator_method_command with a method_id Then: - Verify that the function returns the correct authenticator method - Verify that the output contains the method_id in the title """ from MicrosoftGraphUser import list_authenticator_method_command args = {"user": "test-user", "method_id": "auth-method-id-1"} mock_authenticator_data = { "id": "auth-method-id-1", "displayName": "iPhone 12", "phoneAppVersion": "6.5.0", } mocker.patch.object(client, "get_authenticator_method", return_value=mock_authenticator_data) result = list_authenticator_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.UserAuthMethod" assert "Microsoft Authenticator Authentication Method auth-method-id-1 for User test-user" in result.readable_output def test_delete_authenticator_method_command(mocker, client): """ Tests the delete_authenticator_method_command function. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the delete_authenticator_method_command Then: - Verify that the function returns the correct success message """ from MicrosoftGraphUser import delete_authenticator_method_command args = {"user": "test-user", "method_id": "auth-method-id-1"} mocker.patch.object(client, "delete_authenticator_method", return_value=None) result = delete_authenticator_method_command(client, args) assert "Microsoft Authenticator authentication method auth-method-id-1 was successfully deleted" in result.readable_output def test_list_phone_method_command_list_all(mocker, client): """ Tests the list_phone_method_command function when listing all phone methods for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_phone_method_command without a method_id Then: - Verify that the function returns the correct phone methods - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_phone_method_command args = {"user": "test-user"} mock_phone_data = [ { "id": "phone-method-id-1", "phoneNumber": "+1234567890", "phoneType": "mobile", "smsSignInState": "ready", } ] mocker.patch.object(client, "list_phone_methods", return_value=(mock_phone_data, None)) result = list_phone_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.PhoneAuthMethod" assert result.outputs_key_field == "Id" assert "Phone Authentication Methods for User test-user" in result.readable_output def test_list_phone_method_command_get_specific(mocker, client): """ Tests the list_phone_method_command function when retrieving a specific phone method. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the list_phone_method_command with a method_id Then: - Verify that the function returns the correct phone method - Verify that the output contains the method_id in the title """ from MicrosoftGraphUser import list_phone_method_command args = {"user": "test-user", "method_id": "phone-method-id-1"} mock_phone_data = { "id": "phone-method-id-1", "phoneNumber": "+1234567890", "phoneType": "mobile", "smsSignInState": "ready", } mocker.patch.object(client, "get_phone_method", return_value=mock_phone_data) result = list_phone_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.PhoneAuthMethod" assert "Phone Authentication Method phone-method-id-1 for User test-user" in result.readable_output def test_delete_phone_method_command(mocker, client): """ Tests the delete_phone_method_command function. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the delete_phone_method_command Then: - Verify that the function returns the correct success message """ from MicrosoftGraphUser import delete_phone_method_command args = {"user": "test-user", "method_id": "phone-method-id-1"} mocker.patch.object(client, "delete_phone_method", return_value=None) result = delete_phone_method_command(client, args) assert "phone authentication method object id phone-method-id-1 has been successfully deleted" in result.readable_output def test_list_software_oath_method_command_list_all(mocker, client): """ Tests the list_software_oath_method_command function when listing all software OATH methods for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_software_oath_method_command without a method_id Then: - Verify that the function returns the correct software OATH methods - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_software_oath_method_command args = {"user": "test-user"} mock_software_oath_data = [ { "id": "software-oath-method-id-1", } ] mocker.patch.object(client, "list_software_oath_methods", return_value=mock_software_oath_data) result = list_software_oath_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.SoftOathAuthMethod" assert result.outputs_key_field == "ID" assert "Software OATH Authentication Methods for User test-user" in result.readable_output def test_list_software_oath_method_command_get_specific(mocker, client): """ Tests the list_software_oath_method_command function when retrieving a specific software OATH method. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the list_software_oath_method_command with a method_id Then: - Verify that the function returns the correct software OATH method - Verify that the output contains the method_id in the title """ from MicrosoftGraphUser import list_software_oath_method_command args = {"user": "test-user", "method_id": "software-oath-method-id-1"} mock_software_oath_data = { "id": "software-oath-method-id-1", } mocker.patch.object(client, "get_software_oath_method", return_value=mock_software_oath_data) result = list_software_oath_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.SoftOathAuthMethod" assert "Software OATH Authentication Method software-oath-method-id-1 for User test-user" in result.readable_output def test_delete_software_oath_method_command(mocker, client): """ Tests the delete_software_oath_method_command function. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the delete_software_oath_method_command Then: - Verify that the function returns the correct success message """ from MicrosoftGraphUser import delete_software_oath_method_command args = {"user": "test-user", "method_id": "software-oath-method-id-1"} mocker.patch.object(client, "delete_software_oath_method", return_value=None) result = delete_software_oath_method_command(client, args) assert ( "Software OATH token authentication method object id software-oath-method-id-1 has been successfully deleted" in result.readable_output ) def test_list_windows_hello_method_command_list_all(mocker, client): """ Tests the list_windows_hello_method_command function when listing all Windows Hello methods for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_windows_hello_method_command without a method_id Then: - Verify that the function returns the correct Windows Hello methods - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_windows_hello_method_command args = {"user": "test-user"} mock_windows_hello_data = [ { "id": "windows-hello-method-id-1", "displayName": "Work Laptop", "keyStrength": "normal", "createdDateTime": "2025-01-01T00:00:00Z", } ] mocker.patch.object(client, "list_windows_hello_methods", return_value=mock_windows_hello_data) result = list_windows_hello_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.WindowsHelloAuthMethod" assert result.outputs_key_field == "ID" assert "Windows Hello for Business Authentication Methods for User test-user" in result.readable_output def test_list_windows_hello_method_command_get_specific(mocker, client): """ Tests the list_windows_hello_method_command function when retrieving a specific Windows Hello method. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the list_windows_hello_method_command with a method_id Then: - Verify that the function returns the correct Windows Hello method - Verify that the output contains the method_id in the title """ from MicrosoftGraphUser import list_windows_hello_method_command args = {"user": "test-user", "method_id": "windows-hello-method-id-1"} mock_windows_hello_data = { "id": "windows-hello-method-id-1", "displayName": "Work Laptop", "keyStrength": "normal", } mocker.patch.object(client, "get_windows_hello_method", return_value=mock_windows_hello_data) result = list_windows_hello_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.WindowsHelloAuthMethod" assert ( "Windows Hello for Business Authentication Method windows-hello-method-id-1 for User test-user" in result.readable_output ) def test_delete_windows_hello_method_command(mocker, client): """ Tests the delete_windows_hello_method_command function. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the delete_windows_hello_method_command Then: - Verify that the function returns the correct success message """ from MicrosoftGraphUser import delete_windows_hello_method_command args = {"user": "test-user", "method_id": "windows-hello-method-id-1"} mocker.patch.object(client, "delete_windows_hello_method", return_value=None) result = delete_windows_hello_method_command(client, args) assert ( "Windows Hello For Business Authentication Method object id windows-hello-method-id-1 has been successfully deleted" in result.readable_output ) def test_list_owned_device_command_list_all(mocker, client): """ Tests the list_owned_device_command function when listing all owned devices for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_owned_device_command without filters Then: - Verify that the function returns the correct owned devices - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_owned_device_command args = {"user": "test-user", "limit": "50"} mock_device_data = [ { "id": "device-id-1", "deviceId": "azure-device-id-1", "displayName": "Work Laptop", "accountEnabled": True, "operatingSystem": "Windows", "operatingSystemVersion": "10.0.19045", "trustType": "AzureAd", } ] mocker.patch.object(client, "list_owned_devices", return_value=(mock_device_data, None)) result = list_owned_device_command(client, args) assert result.outputs_prefix == "MSGraphUser" assert result.outputs_key_field == "ID" assert "Owned Devices for User test-user" in result.readable_output def test_list_owned_device_command_with_pagination(mocker, client): """ Tests the list_owned_device_command function with pagination. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and next_page When: - Running the list_owned_device_command with a next_page URL Then: - Verify that the function returns the correct owned devices - Verify that the next page URL is included in the output """ from MicrosoftGraphUser import list_owned_device_command args = {"user": "test-user", "limit": "2"} mock_device_data = [ { "id": "device-id-1", "deviceId": "azure-device-id-1", "displayName": "Work Laptop", }, { "id": "device-id-2", "deviceId": "azure-device-id-2", "displayName": "Personal Phone", }, ] next_page_url = "https://graph.microsoft.com/v1.0/users/test-user/ownedDevices?$skiptoken=abc123" mocker.patch.object(client, "list_owned_devices", return_value=(mock_device_data, next_page_url)) result = list_owned_device_command(client, args) assert result.outputs_prefix == "MSGraphUser" assert "To get further results, enter this to the next_page argument" in result.readable_output assert next_page_url in result.readable_output def test_list_owned_device_command_no_devices(mocker, client): """ Tests the list_owned_device_command function when no devices are found. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_owned_device_command and no devices are returned Then: - Verify that the function returns an appropriate message """ from MicrosoftGraphUser import list_owned_device_command args = {"user": "test-user"} mocker.patch.object(client, "list_owned_devices", return_value=([], None)) result = list_owned_device_command(client, args) assert "No owned devices found for user test-user" in result.readable_output def test_list_owned_device_command_with_filter(mocker, client): """ Tests the list_owned_device_command function with a filter. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and filter When: - Running the list_owned_device_command with a filter Then: - Verify that the function returns the correct filtered devices """ from MicrosoftGraphUser import list_owned_device_command args = {"user": "test-user", "filter": "operatingSystem eq 'Windows'", "limit": "50"} mock_device_data = [ { "id": "device-id-1", "deviceId": "azure-device-id-1", "displayName": "Work Laptop", "operatingSystem": "Windows", } ] mocker.patch.object(client, "list_owned_devices", return_value=(mock_device_data, None)) result = list_owned_device_command(client, args) assert result.outputs_prefix == "MSGraphUser" assert "Owned Devices for User test-user" in result.readable_output def test_list_temp_access_pass_method_command_list_all(mocker, client): """ Tests the list_temp_access_pass_method_command function when listing all TAP methods for a user. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user When: - Running the list_temp_access_pass_method_command without a method_id Then: - Verify that the function returns the correct TAP methods - Verify that the output prefix and key field are correct """ from MicrosoftGraphUser import list_temp_access_pass_method_command args = {"user": "test-user"} mock_tap_data = [ { "id": "tap-method-id-1", "isUsable": True, } ] mocker.patch.object(client, "list_tap_policy", return_value=mock_tap_data) result = list_temp_access_pass_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.TempAccessPassAuthMethod" assert result.outputs_key_field == "ID" assert "Temporary Access Pass Methods for User test-user" in result.readable_output def test_list_temp_access_pass_method_command_get_specific(mocker, client): """ Tests the list_temp_access_pass_method_command function when retrieving a specific TAP method. Given: - A mock client instance for the Microsoft Graph API - Arguments for the command including user and method_id When: - Running the list_temp_access_pass_method_command with a method_id Then: - Verify that the function returns the correct TAP method - Verify that the output contains the method_id in the title """ from MicrosoftGraphUser import list_temp_access_pass_method_command args = {"user": "test-user", "method_id": "tap-method-id-1"} mock_tap_data = { "id": "tap-method-id-1", "isUsable": True, } mocker.patch.object(client, "get_temp_access_pass_method", return_value=mock_tap_data) result = list_temp_access_pass_method_command(client, args) assert result.outputs_prefix == "MSGraphUser.TempAccessPassAuthMethod" assert "WTemporary Access Pass Method tap-method-id-1 for User test-user" in result.readable_output def test_request_mfa_command(mocker): """ Given: - A user email and access token. When: - Running request_mfa_command. Then: - Ensure the command calls push_mfa_notification and returns the result. """ from MicrosoftGraphUser import MsGraphClient, request_mfa_command client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_mail": "test@test.com", "access_token": "token", "timeout": "30"} expected_output = "Status: User Approved MFA Request" mocker.patch.object(client, "push_mfa_notification", return_value=expected_output) result = request_mfa_command(client, args) assert result.readable_output == expected_output client.push_mfa_notification.assert_called_once_with("test@test.com", 30, "token") def test_request_mfa_command_declined(mocker): """ Given: - A user email and access token. When: - Running request_mfa_command. Then: - Ensure the command calls push_mfa_notification and returns the result. """ from MicrosoftGraphUser import MsGraphClient, request_mfa_command, DemistoException client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_mail": "test@test.com", "access_token": "token", "timeout": "30"} expected_output = "Status: User Denied Request" mocker.patch.object(client, "push_mfa_notification", side_effect=DemistoException(expected_output)) with pytest.raises(DemistoException) as e: request_mfa_command(client, args) assert expected_output in str(e.value) client.push_mfa_notification.assert_called_once_with("test@test.com", 30, "token") def test_request_mfa_command_timeout(mocker): """ Given: - A user email and access token. When: - Running request_mfa_command. Then: - Ensure the command calls push_mfa_notification and returns the result. """ from MicrosoftGraphUser import MsGraphClient, request_mfa_command, DemistoException client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_mail": "test@test.com", "access_token": "token", "timeout": "30"} expected_output = "Status: MFA Request Timed Out" mocker.patch.object(client, "push_mfa_notification", side_effect=DemistoException(expected_output)) with pytest.raises(DemistoException) as e: request_mfa_command(client, args) assert expected_output in str(e.value) client.push_mfa_notification.assert_called_once_with("test@test.com", 30, "token") def test_request_mfa_command_failed(mocker): """ Given: - A user email and access token. When: - Running request_mfa_command. Then: - Ensure the command calls push_mfa_notification and returns the result. """ from MicrosoftGraphUser import MsGraphClient, request_mfa_command, DemistoException client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_mail": "test@test.com", "access_token": "token", "timeout": "30"} expected_output = "Status: MFA Request Failed - No specific message" mocker.patch.object(client, "push_mfa_notification", side_effect=DemistoException(expected_output)) with pytest.raises(DemistoException) as e: request_mfa_command(client, args) assert expected_output in str(e.value) client.push_mfa_notification.assert_called_once_with("test@test.com", 30, "token") def test_request_mfa_command_parsing_error(mocker): """ Given: - A user email and access token. When: - Running request_mfa_command. Then: - Ensure the command calls push_mfa_notification and returns the result. """ from MicrosoftGraphUser import MsGraphClient, request_mfa_command, DemistoException client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user_mail": "test@test.com", "access_token": "token", "timeout": "30"} expected_output = "Error: Could not parse MFA response." mocker.patch.object(client, "push_mfa_notification", side_effect=DemistoException(expected_output)) with pytest.raises(DemistoException) as e: request_mfa_command(client, args) assert expected_output in str(e.value) client.push_mfa_notification.assert_called_once_with("test@test.com", 30, "token") def test_get_default_auth_methods_command(mocker): """ Given: - A user. When: - Running get_default_auth_methods_command. Then: - Ensure the command calls get_sign_in_preferences and returns the correct outputs. """ from MicrosoftGraphUser import MsGraphClient, get_default_auth_methods_command client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) args = {"user": "test@test.com"} mock_preferences = { "userPreferredMethodForSecondaryAuthentication": "push", "systemPreferredAuthenticationMethod": "sms", "isSystemPreferredAuthenticationMethodEnabled": True, } mocker.patch.object(client, "get_sign_in_preferences", return_value=mock_preferences) result = get_default_auth_methods_command(client, args) assert result.outputs["MSGraphUser.AuthMethod(val.User === obj.User)"]["DefaultMethod"] == "push" assert result.outputs["MSGraphUser.AuthMethod(val.User === obj.User)"]["User"] == "test@test.com" assert "Default Auth Method:** push" in result.readable_output def test_create_client_secret_command(mocker): """ Given: - allow_secret_generators param. When: - Running create_client_secret_command. Then: - Ensure the command calls request_mfa_app_secret when allowed, and raises error when not. """ from MicrosoftGraphUser import MsGraphClient, create_client_secret_command, DemistoException client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) # Case 1: Not allowed params = {"allow_secret_generators": "False"} with pytest.raises(DemistoException) as e: create_client_secret_command(client, {}, params) assert "Allow secret generators commands execution" in str(e.value) # Case 2: Allowed params = {"allow_secret_generators": "True"} mock_secret = {"secretText": "secret_value", "startDateTime": "2023-01-01T00:00:00Z", "endDateTime": "2025-01-01T00:00:00Z"} mocker.patch.object(client, "request_mfa_app_secret", return_value=mock_secret) result = create_client_secret_command(client, {}, params) assert result.outputs["MFAClientSecret"] == "secret_value" assert result.outputs["ValidFrom"] == "2023-01-01T00:00:00Z" def test_create_access_token_command(mocker): """ Given: - allow_secret_generators param and client secret. When: - Running create_access_token_command. Then: - Ensure the command calls get_mfa_app_client_token when allowed, and raises error when not. """ from MicrosoftGraphUser import MsGraphClient, create_access_token_command, DemistoException client = MsGraphClient( base_url="https://graph.microsoft.com/v1.0", tenant_id="tenant-id", auth_id="auth_and_token_url", enc_key="enc_key", app_name="ms-graph-groups", verify="use_ssl", proxy="proxies", self_deployed="self_deployed", handle_error=True, auth_code="", redirect_uri="", azure_cloud=AZURE_WORLDWIDE_CLOUD, ) # Case 1: Not allowed params = {"allow_secret_generators": "False"} with pytest.raises(DemistoException) as e: create_access_token_command(client, {}, params) assert "Allow secret generators commands execution" in str(e.value) # Case 2: Allowed params = {"allow_secret_generators": "True"} args = {"client_secret": "secret"} mock_token = {"AccessToken": "access_token_value", "ValidUntil": "2023-01-01T01:00:00Z"} mocker.patch.object(client, "get_mfa_app_client_token", return_value=mock_token) result = create_access_token_command(client, args, params) assert result.outputs["AccessToken"] == "access_token_value" assert result.outputs["ValidUntil"] == "2023-01-01T01:00:00Z"