def test_connection_request_is_able_to_accept_accept_header( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put(URL, data='{"foo":"bar"}', headers={"Accept": "*/*"}) request = success_requests_session.prepare_request.call_args[0][0] assert request.headers["Accept"] == "*/*"
def test_connection_request_when_no_data_does_not_include_content_type_header( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put(URL) request = success_requests_session.prepare_request.call_args[0][0] assert request.headers.get("Content-Type") is None
def test_connection_request_includes_user_agent_header( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put(URL) request = success_requests_session.prepare_request.call_args[0][0] assert request.headers["User-Agent"] is not None
def test_connection_request_when_session_returns_none_raises_py42_error( self, mock_host_resolver, mock_auth, success_requests_session): success_requests_session.send.return_value = None connection = Connection(mock_host_resolver, mock_auth, success_requests_session) with pytest.raises(Py42Error): connection.get(URL)
def test_connection_options_calls_requests_with_options( self, mock_host_resolver, mock_auth, success_requests_session ): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.options(URL) expected = MockPreparedRequest("OPTIONS", HOST_ADDRESS + URL) success_requests_session.prepare_request.assert_called_once_with(expected)
def test_connection_head_calls_requests_with_head( self, mock_host_resolver, mock_auth, success_requests_session ): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.head(URL) expected = MockPreparedRequest("HEAD", HOST_ADDRESS + URL) success_requests_session.prepare_request.assert_called_once_with(expected)
def test_connection_patch_calls_requests_with_patch( self, mock_host_resolver, mock_auth, success_requests_session ): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.patch(URL, data="testdata") expected = MockPreparedRequest("PATCH", HOST_ADDRESS + URL, "testdata") success_requests_session.prepare_request.assert_called_once_with(expected)
def test_connection_delete_calls_requests_with_delete( self, mock_host_resolver, mock_auth, success_requests_session ): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.delete(URL) expected = MockPreparedRequest("DELETE", HOST_ADDRESS + URL) success_requests_session.prepare_request.assert_called_once_with(expected)
def test_connection_get_calls_requests_with_get( self, mock_host_resolver, mock_auth, success_requests_session ): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.get(URL) expected = MockPreparedRequest("GET", HOST_ADDRESS + URL, None) success_requests_session.prepare_request.assert_called_once_with(expected)
def test_connection_request_when_not_give_accept_header_sets_accept_to_application_json( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put(URL, data='{"foo":"bar"}') request = success_requests_session.prepare_request.call_args[0][0] assert request.headers["Accept"] == "application/json"
def from_local_account(cls, host_address, username, password, totp=None): """Creates a :class:`~py42.sdk.SDKClient` object for accessing the Code42 REST APIs using the supplied credentials. This method supports only accounts created within the Code42 console or using the APIs (including py42). Username/passwords that are based on Active Directory, Okta, or other Identity providers should use the `from_jwt_provider` method. Args: host_address (str): The domain name of the Code42 instance being authenticated to, e.g. console.us.code42.com username (str): The username of the authenticating account. password (str): The password of the authenticating account. totp (callable or str, optional): The time-based one-time password of the authenticating account. Include only if the account uses Code42's two-factor authentication. Defaults to None. Returns: :class:`py42.sdk.SDKClient` """ basic_auth = None if username and password: basic_auth = HTTPBasicAuth(username, password) auth_connection = Connection.from_host_address(host_address, auth=basic_auth) bearer_auth = BearerAuth(auth_connection, totp) main_connection = Connection.from_host_address(host_address, auth=bearer_auth) return cls(main_connection, bearer_auth)
def test_connection_request_when_has_data_includes_content_type_header( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put(URL, data='{"foo":"bar"}') request = success_requests_session.prepare_request.call_args[0][0] assert request.headers["Content-Type"] == "application/json"
def test_connection_request_calls_auth_handler_clears_renews_credentials_when_response_unauthorized( self, mock_host_resolver, mock_auth, renewed_requests_session): connection = Connection(mock_host_resolver, mock_auth, renewed_requests_session) connection.get(URL) assert renewed_requests_session.send.call_count == 2 assert renewed_requests_session.prepare_request.call_count == 2 assert mock_auth.clear_credentials.call_count == 1
def test_connection_post_with_json_prepares_request_with_string_encoded_json_body( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.post(URL, json=JSON_VALUE) expected = MockPreparedRequest("POST", HOST_ADDRESS + URL, json.dumps(JSON_VALUE)) success_requests_session.prepare_request.assert_called_once_with( expected)
def test_connection_post_with_data_and_json_params_overwrites_data_with_json( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.post(URL, data=DATA_VALUE, json=JSON_VALUE) expected = MockPreparedRequest("POST", HOST_ADDRESS + URL, json.dumps(JSON_VALUE)) success_requests_session.prepare_request.assert_called_once_with( expected)
def test_connection_request_returns_utf8_response( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) response = connection.request("GET", URL, data=DATA_VALUE, json=JSON_VALUE) assert response.encoding == "utf-8"
def test_connection_request_uses_given_headers( self, mock_host_resolver, mock_auth, success_requests_session ): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put( URL, data='{"foo":"bar"}', headers={"Header1": "Foo", "Header2": "Bar"} ) request = success_requests_session.prepare_request.call_args[0][0] assert request.headers["Header1"] == "Foo" assert request.headers["Header2"] == "Bar"
def test_connection_request_raises_unauthorized_error_when_renewal_results_in_401( self, mock_host_resolver, mock_auth, unauthorized_requests_session): connection = Connection(mock_host_resolver, mock_auth, unauthorized_requests_session) with pytest.raises(Py42UnauthorizedError): connection.get(URL) assert unauthorized_requests_session.send.call_count == 2
def test_connection_post_calls_requests_with_post( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.post(URL, data=DATA_VALUE) expected = MockPreparedRequest("POST", HOST_ADDRESS + URL, data=DATA_VALUE.encode("utf-8")) success_requests_session.prepare_request.assert_called_once_with( expected)
def _init_services(main_connection, main_auth): alert_rules_key = u"FedObserver-API_URL" alerts_key = u"AlertService-API_URL" file_events_key = u"FORENSIC_SEARCH-API_URL" preservation_data_key = u"PRESERVATION-DATA-SERVICE_API-URL" employee_case_mgmt_key = u"employeecasemanagement-API_URL" kv_prefix = u"simple-key-value-store" audit_logs_key = u"AUDIT-LOG_API-URL" kv_connection = Connection.from_microservice_prefix( main_connection, kv_prefix) kv_service = KeyValueStoreService(kv_connection) alert_rules_conn = Connection.from_microservice_key(kv_service, alert_rules_key, auth=main_auth) alerts_conn = Connection.from_microservice_key(kv_service, alerts_key, auth=main_auth) file_events_conn = Connection.from_microservice_key(kv_service, file_events_key, auth=main_auth) pds_conn = Connection.from_microservice_key(kv_service, preservation_data_key, auth=main_auth) ecm_conn = Connection.from_microservice_key(kv_service, employee_case_mgmt_key, auth=main_auth) audit_logs_conn = Connection.from_microservice_key(kv_service, audit_logs_key, auth=main_auth) user_svc = UserService(main_connection) administration_svc = AdministrationService(main_connection) file_event_svc = FileEventService(file_events_conn) user_ctx = UserContext(administration_svc) user_profile_svc = DetectionListUserService(ecm_conn, user_ctx, user_svc) services = Services( administration=administration_svc, archive=ArchiveService(main_connection), devices=DeviceService(main_connection), legalhold=LegalHoldService(main_connection), orgs=OrgService(main_connection), securitydata=SecurityDataService(main_connection), users=UserService(main_connection), alertrules=AlertRulesService(alert_rules_conn, user_ctx, user_profile_svc), alerts=AlertService(alerts_conn, user_ctx), fileevents=file_event_svc, savedsearch=SavedSearchService(file_events_conn, file_event_svc), preservationdata=PreservationDataService(pds_conn), departingemployee=DepartingEmployeeService(ecm_conn, user_ctx, user_profile_svc), highriskemployee=HighRiskEmployeeService(ecm_conn, user_ctx, user_profile_svc), userprofile=user_profile_svc, auditlogs=AuditLogsService(audit_logs_conn), ) return services, user_ctx
def test_get_for_user_calls_session_get_with_expected_uri_and_params( self, mock_session): connection = Connection.from_host_address(HOST_ADDRESS, session=mock_session) loginconfig = LoginConfigurationClient(connection) loginconfig.get_for_user("*****@*****.**") expected_uri = f"https://{HOST_ADDRESS}/c42api/v3/LoginConfiguration" expected_params = {"username": "******"} mock_session.get.assert_called_once_with(expected_uri, params=expected_params)
def test_get_for_user_does_not_use_py42_connection_get_method( self, mocker, mock_session): """Because the loginConfiguration endpoint is unauthenticated, we want to make sure we don't force the Connection's C42RenewableAuth object to make any authentication requests before making the loginConfig request. """ mock_get = mocker.patch("py42.services._connection.Connection.get") connection = Connection.from_host_address(HOST_ADDRESS, session=mock_session) loginconfig = LoginConfigurationClient(connection) loginconfig.get_for_user("*****@*****.**") assert mock_get.call_count == 0 assert mock_session.get.call_count == 1
def test_connection_request_when_has_data_does_not_use_header_on_following_request_that_does_not_have_data( self, mock_host_resolver, mock_auth, success_requests_session ): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put(URL, data='{"foo":"bar"}') # Content-Type: application/json connection.get(URL) request = success_requests_session.prepare_request.call_args[0][0] assert request.headers.get("Content-Type") is None
def test_connection_request_when_given_header_as_param_does_not_persist_header( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.put(URL, data='{"foo":"bar"}', headers={"Foo": "Bar"}) connection.get(URL) request = success_requests_session.prepare_request.call_args[0][0] assert request.headers.get("Foo") is None
def get_storage_connection(self, tmp_auth): try: url = tmp_auth.get_storage_url() connection = self.get_saved_connection_for_url(url) if connection is None: with self._list_update_lock: connection = self.get_saved_connection_for_url(url) if connection is None: connection = Connection.from_host_address( url, auth=tmp_auth) self._session_cache[url.lower()] = connection except Exception as ex: message = u"Failed to create or retrieve connection, caused by: {}".format( str(ex)) raise Py42StorageSessionInitializationError(ex, message) return connection
def test_from_local_account_when_unauthorized_calls_loginConfig_and_returns_config_value_on_raised_exception_text( self, mocker, mock_session, mock_auth, unauthorized_response): login_type = "LOCAL_2FA" mock_session.send.return_value = unauthorized_response mock_session.get.return_value = create_mock_response( mocker, f'{{"loginType": "{login_type}"}}') connection = Connection.from_host_address(HOST_ADDRESS, session=mock_session) client = SDKClient(connection, mock_auth) mocker.patch("py42.sdk.SDKClient.from_local_account", return_value=client) with pytest.raises(Py42UnauthorizedError) as err: from_local_account(HOST_ADDRESS, TEST_USERNAME, TEST_PASSWORD) assert f"User LoginConfig: {login_type}" in str(err)
def from_jwt_provider(cls, host_address, jwt_provider): """Creates a :class:`~py42.sdk.SDKClient` object for accessing the Code42 REST APIs using a custom auth mechanism. User can use any authentication mechanism like that returns a JSON Web token on authentication which would then be used for all subsequent requests. Args: host_address (str): The domain name of the Code42 instance being authenticated to, e.g. console.us.code42.com jwt_provider (function): A function that accepts no parameters and on execution returns a JSON web token string. Returns: :class:`py42.sdk.SDKClient` """ custom_auth = CustomJWTAuth(jwt_provider) main_connection = Connection.from_host_address(host_address, auth=custom_auth) return cls(main_connection, custom_auth)
def test_connection_request_when_proxies_set_passes_proxies_arg_to_session_send( self, proxy_set, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, session=success_requests_session) url = "https://example.com" connection.get(url) connection.post(url) connection.options(url) connection.put(url) connection.patch(url) connection.head(url) connection.delete(url) for call in success_requests_session.send.call_args_list: assert call[1]["proxies"] == {"https": "http://localhost:9999"}
def test_connection_request_with_error_status_code_raises_http_error( self, mock_host_resolver, mock_auth, error_requests_session): connection = Connection(mock_host_resolver, mock_auth, error_requests_session) with pytest.raises(Py42InternalServerError): connection.get(URL)
def test_connection_request_calls_auth_handler_when_making_first_request( self, mock_host_resolver, mock_auth, success_requests_session): connection = Connection(mock_host_resolver, mock_auth, success_requests_session) connection.get(URL) assert success_requests_session.prepare_request.call_count == 1