import pytest from pytest_mock import MockerFixture import demistomock as demisto from URLSSLVerification import arg_to_list_with_regex, mark_http_as_suspicious, main, verify_ssl_certificate import requests from requests.exceptions import SSLError @pytest.mark.parametrize("arg, expected_result", [("false", False), ("true", True), (None, True)]) def test_is_http_should_be_suspicious(arg, expected_result): assert mark_http_as_suspicious(arg) == expected_result @pytest.mark.parametrize( "arg, expected_result", [ (None, []), (["some_url"], ["some_url"]), ('["some_url"]', ["some_url"]), ("https://some_url.com", ["https://some_url.com"]), ], ) def test_arg_to_list_with_regex(arg, expected_result): assert arg_to_list_with_regex(arg) == expected_result def create_response(url, status_code=200, history=[]): resp = requests.Response() resp.status_code = status_code resp.url = url resp.history = history return resp def fake_requests_get(url, timeout=1, allow_redirects=True, verify=True): """ This helper function simulates HTTP requests with no real URL. It fabricates response objects that include status codes, URL redirection history, and header-like information. Args: url (str): The target URL. timeout (int or float, optional): Maximum time in seconds to wait for the response. allow_redirects (bool, optional): Whether to follow redirects. Defaults to True. verify (bool, optional): Whether to enforce SSL certificate verification. Defaults to True. Raises: SSLError: If SSL certificate verification fails. Returns: requests.Response: A simulated HTTP response including status, final URL, and redirect history. """ if url == "https_no_certificate": raise SSLError("SSL certificate error") elif url == "http" or url == "https_certificate": return create_response(url=url) elif url == "http_to_https_certificate": first_response = create_response(url="http_to_https_certificate", status_code=301) if allow_redirects: return create_response(url="https_certificate", history=[first_response]) else: return first_response elif url == "http_to_http": first_response = create_response(url="http_to_http", status_code=301) if allow_redirects: return create_response(url="http", history=[first_response]) else: return first_response raise requests.exceptions.RequestException @pytest.mark.parametrize( "arg, expected_results", [ # Set_http_as_suspicious = True ({"url": "http", "set_http_as_suspicious": "true"}, [{"Verified": False, "Score": 2, "Indicator": "http"}]), ( {"url": "https_certificate", "set_http_as_suspicious": "true"}, [{"Verified": True, "Score": 0, "Indicator": "https_certificate"}], ), # Set_http_as_suspicious = False ( {"url": "http_to_https_certificate", "set_http_as_suspicious": "false"}, [{"Verified": True, "Score": 0, "Indicator": "http_to_https_certificate"}], ), ({"url": "http", "set_http_as_suspicious": "false"}, [{"Verified": False, "Score": 2, "Indicator": "http"}]), ( {"url": "https_certificate", "set_http_as_suspicious": "false"}, [{"Verified": True, "Score": 0, "Indicator": "https_certificate"}], ), ( {"url": "https_no_certificate", "set_http_as_suspicious": "false"}, [{"Verified": False, "Score": 2, "Indicator": "https_no_certificate"}], ), ( {"url": "http_to_http", "set_http_as_suspicious": "false"}, [{"Verified": False, "Score": 2, "Indicator": "http_to_http"}], ), ( {"url": "invalid_url", "set_http_as_suspicious": "false"}, [{"Verified": False, "Score": 2, "Indicator": "invalid_url"}], ), # Test Multiple url ( {"url": ["invalid_url", "http_to_http", "http_to_https_certificate"], "set_http_as_suspicious": "false"}, [ {"Verified": False, "Score": 2, "Indicator": "invalid_url"}, {"Verified": False, "Score": 2, "Indicator": "http_to_http"}, {"Verified": True, "Score": 0, "Indicator": "http_to_https_certificate"}, ], ), ], ) def test_main(arg, expected_results, mocker: MockerFixture): """ Given: Requests.get work as mentioned above. When: main function is called. Then: The function should return the appropriate message. """ # Mock demisto.args() mocker.patch.object( demisto, "args", return_value=arg, ) # Mock return_results mock_return_results = mocker.patch("URLSSLVerification.return_results") mocker.patch("URLSSLVerification.requests.get", side_effect=fake_requests_get) # Call the main function main() # Assert that return_results was called with the correct arguments mock_return_results.assert_called_once() result = mock_return_results.call_args[0][0] for url in result.outputs["URL"]: assert url["Verified"] == [ret["Verified"] for ret in expected_results if ret["Indicator"] == url["Data"]][0] for d_bot in result.outputs["DBotScore"]: assert d_bot["Score"] == [ret["Score"] for ret in expected_results if ret["Indicator"] == d_bot["Indicator"]][0] @pytest.mark.parametrize( "url, description_result", [ ("https_no_certificate", "SSL Certificate verification failed"), ("invalid_url", "Failed to establish a new connection with the URL"), ], ) def test_verify_ssl_certificate(url, description_result, mocker: MockerFixture): """ Given: Requests.get work as mentioned above. When: verify_ssl_certificate is called. Then: The function should return the appropriate message. """ mocker.patch("URLSSLVerification.requests.get", side_effect=fake_requests_get) result = verify_ssl_certificate(url) assert result assert result["Description"] == description_result