def get_qsessions() -> dict: """ Get session ids of currently queued RTR sessions """ endpoint_url = '/real-time-response/queries/sessions/v1' if helpers.is_expiring(BATCH_LIFE_TIME, BATCH_REQ_TIME): refresh_rtr_session() params = {'sort': 'created_at|desc', 'filter': 'commands_queued:1'} response = http_request('GET', endpoint_url, params=params) return response
def delete_rtr_session() -> dict: """ Retrieves a script given its ID :return: Response JSON which contains errors (if exist) and retrieved resource """ endpoint_url = '/real-time-response/entities/sessions/v1' if helpers.is_expiring(BATCH_LIFE_TIME, BATCH_REQ_TIME): refresh_rtr_session() params = {'session_id': BATCH_ID} response = http_request('DELETE', endpoint_url, params=params) return response
def delete_qsession(session_id: str) -> dict: """ Delete a queued RTR session by session ID :param session_id: Session ID of session to delete """ endpoint_url = '/real-time-response/entities/sessions/v1' if helpers.is_expiring(BATCH_LIFE_TIME, BATCH_REQ_TIME): refresh_rtr_session() params = {'session_id': session_id} response = http_request('DELETE', endpoint_url, params=params) return response
def get_qsessions_metadata(session_ids: list) -> dict: """ Get metadata of currently queued RTR sessions by session IDs :param session_ids: List of session ids to retrieve metadata for """ endpoint_url = '/real-time-response/entities/queued-sessions/GET/v1' if helpers.is_expiring(BATCH_LIFE_TIME, BATCH_REQ_TIME): refresh_rtr_session() body = json.dumps({'ids': session_ids}) response = http_request('POST', endpoint_url, data=body) return response
def delete_qsession_command(session_id: str, cloud_request_id: str) -> dict: """ Delete a queued RTR session command by session ID and cloud request ID :param session_id: :param cloud_request_id: """ endpoint_url = '/real-time-response/entities/queued-sessions/command/v1' if helpers.is_expiring(BATCH_LIFE_TIME, BATCH_REQ_TIME): refresh_rtr_session() params = {'session_id': session_id, 'cloud_request_id': cloud_request_id} response = http_request('DELETE', endpoint_url, params=params) return response
def run_batch_cmd(command_type: str, full_command: str) -> dict: """ Batch executes a RTR active-responder command across the hosts mapped to the given batch id :param command_type: Command type we are going to execute, for example: ls or cd. :param full_command: Full command string for the command. """ endpoint_url = '/real-time-response/combined/batch-command/v1' if helpers.is_expiring(BATCH_LIFE_TIME, BATCH_REQ_TIME): refresh_rtr_session() params = {'timeout_duration': '2m'} body = json.dumps({ 'base_command': command_type, 'batch_id': BATCH_ID, 'command_string': full_command }) response = http_request('POST', endpoint_url, params=params, data=body) return response
def get_token(new_token: bool = False) -> str: """ Retrieves the token from the server if it's expired and updates the global HEADERS to include it :param new_token: If set to True will generate a new token regardless of time passed :return: Token """ global HEADERS, TOKEN auth_token = TOKEN if new_token: auth_token = get_token_request() else: if helpers.is_expiring(TOKEN_LIFE_TIME, TOKEN_REQ_TIME): auth_token = get_token_request() HEADERS['Authorization'] = 'Bearer {}'.format(auth_token) TOKEN = auth_token with open(TOKEN_PATH, 'w') as outfile: outfile.write(auth_token) return auth_token
def http_request(method: str, url_suffix: str, params: dict = None, data: dict = None, headers: dict = HEADERS, files: dict = None, safe: bool = False, get_token_flag: bool = True) -> dict: """ A wrapper for requests lib to send our requests and handle requests and responses better. :param method: HTTP method for the request. :param url_suffix: The suffix of the URL (endpoint) :param params: The URL params to be passed. :param data: The body data of the request. :param headers: Request headers :param files: The files data of the request :param safe: If set to true will return None in case of http error :param get_token_flag: If set to True will call get_token() :return: Returns the http request response json """ response = "" if get_token_flag: token = get_token() headers['Authorization'] = 'Bearer {}'.format(token) url = SERVER + url_suffix try: response = requests.request(method, url, verify=USE_SSL, params=params, data=data, headers=headers, files=files) except requests.exceptions.RequestException: print( 'Error in connection to the server. Please make sure you entered the URL correctly.' ) try: resp_json = response.json() # print(url_suffix, response.status_code) # debug if response.status_code not in {200, 201, 202}: reason = response.reason resources = resp_json.get('resources', {}) if resources and type(resources) is dict: for host_id, resource in resources.items(): errors = resource.get('errors', []) if errors: error_message = errors[0].get('message') reason += f'\nHost ID {host_id} - {error_message}' elif resp_json.get('errors'): errors = resp_json.get('errors', []) for error in errors: reason += f"\n{error.get('message')}" err_msg = 'Error in API call to CrowdStrike Falcon: code: {code} - reason: {reason}'.format( code=response.status_code, reason=reason) # try to create a new token if response.status_code in (401, 403): if helpers.is_expiring(TOKEN_LIFE_TIME, TOKEN_REQ_TIME): get_token(new_token=True) return http_request(method, url_suffix, params, data, HEADERS, files, safe, get_token_flag=False) elif safe: return None print(err_msg) return resp_json except ValueError as exception: if url_suffix == '/real-time-response/entities/sessions/v1' and method == 'DELETE': # empty json when success pass else: raise ValueError( f'Failed to parse json object from response: {exception} - {response.content}' )