def subscription_service(request): """Handles TAXII Subscription Service requests.""" logger = logging.getLogger("TAXIIApplication.taxii.views.subscription_service") logger.debug('Entering subscription service') resp = handlers.validate_taxii_request(request) if resp: return resp # if validation failed, return the response try: taxii_message = tm_version.get_message_from_xml(request.body) except Exception as ex: logger.debug('Unable to parse inbound message: %s', str(ex)) m = tm.StatusMessage(tm.generate_message_id(), '0', status_type=tm.ST_BAD_MESSAGE, message='Message received could not be parsed') return handlers.create_taxii_response(m, use_https=request.is_secure()) logger.debug('Message received TAXII message with id [%s] and type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) if taxii_message.message_type != tm_version.MSG_MANAGE_FEED_SUBSCRIPTION_REQUEST: logger.info('TAXII message with id [%s] was not Subscription Managment request [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) m = tm_version.StatusMessage(tm.generate_message_id(), taxii_message.message_id, status_type=tm.ST_FAILURE, message='Message sent to feed managment service did not have a feed_managmen_request message type') return handlers.create_taxii_response(m, use_https=request.is_secure()) resp = handlers.feed_subscription_get_content(request, taxii_message) logger.debug("We send the response to the client") return resp
def inbox_service(request, inbox_name): """Handles TAXII Inbox Service requests.""" logger = logging.getLogger('yeti.taxii_services.views.inbox_service') logger.debug('Entering Inbox service') resp = handlers.validate_taxii_request(request) if resp: return resp # if validation failed, return the response try: taxii_message = tm11.get_message_from_xml(request.body) except Exception as ex: logger.debug('Unable to parse inbound message: %s', ex.message) m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_BAD_MESSAGE, message='Message received could not be parsed') return handlers.create_taxii_response(m, use_https=request.is_secure()) logger.debug('Inbox [%s] received TAXII message with id [%s] and type [%s]', make_safe(inbox_name), make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) if taxii_message.message_type != tm11.MSG_INBOX_MESSAGE: logger.info('TAXII message with id [%s] was not Inbox type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_FAILURE, message='Message sent to Inbox service did not have an inbox Message type') return handlers.create_taxii_response(m, use_https=request.is_secure()) resp = handlers.inbox_add_content(request, inbox_name, taxii_message) return resp
def poll_service(request): """Handles TAXII Poll Service requests.""" logger = logging.getLogger("yeti.taxii_services.views.poll_service") logger.debug('Entering poll service') resp = handlers.validate_taxii_request(request) if resp: return resp # if validation failed, return the response try: taxii_message = tm11.get_message_from_xml(request.body) except tm11.UnsupportedQueryException as e: logger.debug('Unsupported query found in TAXII Message') m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_UNSUPPORTED_QUERY, message='The message used an unsupported query format') return handlers.create_taxii_response(m, use_https=request.is_secure()) except Exception as ex: logger.debug('Unable to parse inbound message: %s', ex.message) m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_BAD_MESSAGE, message='Message received could not be parsed') return handlers.create_taxii_response(m, use_https=request.is_secure()) logger.debug('Poll service received TAXII message with id [%s] and type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) if taxii_message.message_type != tm11.MSG_POLL_REQUEST: logger.info('TAXII message with id [%s] was not Poll request [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_FAILURE, message='Message sent to Poll service did not have a poll request message type') return handlers.create_taxii_response(m, use_https=request.is_secure()) resp = handlers.poll_get_content(request, taxii_message) return resp
def poll_get_content(request, taxii_message): """Returns a Poll response for a given Poll Request Message""" logger = logging.getLogger('taxii_services.utils.handlers.poll_get_content') logger.debug('Polling data from data collection [%s] - begin_ts: %s, end_ts: %s', make_safe(taxii_message.collection_name), taxii_message.exclusive_begin_timestamp_label, taxii_message.inclusive_end_timestamp_label) try: data_collection = DataCollection.objects.get(name=taxii_message.collection_name) except: logger.debug('Attempting to poll unknown data collection [%s]', make_safe(taxii_message.collection_name)) m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_NOT_FOUND, message='Data collection does not exist [%s]' % (make_safe(taxii_message.collection_name))) return create_taxii_response(m, use_https=request.is_secure()) # build query for poll results query_params = {} if taxii_message.exclusive_begin_timestamp_label: query_params['timestamp_label__gt'] = taxii_message.exclusive_begin_timestamp_label current_datetime = datetime.datetime.now(tzutc()) if taxii_message.inclusive_end_timestamp_label and (taxii_message.inclusive_end_timestamp_label < current_datetime): query_params['timestamp_label__lte'] = taxii_message.inclusive_end_timestamp_label else: query_params['timestamp_label__lte'] = current_datetime if taxii_message.poll_parameters.content_bindings: query_params['content_binding__in'] = taxii_message.content_bindings content_blocks = data_collection.content_blocks.filter(**query_params).order_by('timestamp_label') logger.debug('Returned [%d] content blocks from data collection [%s]', len(content_blocks), make_safe(data_collection.name)) # TAXII Poll Requests have exclusive begin timestamp label fields, while Poll Responses # have *inclusive* begin timestamp label fields. To satisfy this, we add one millisecond # to the Poll Request's begin timestamp label. # # This will be addressed in future versions of TAXII inclusive_begin_ts = None if taxii_message.exclusive_begin_timestamp_label: inclusive_begin_ts = taxii_message.exclusive_begin_timestamp_label + datetime.timedelta(milliseconds=1) # build poll response poll_response_message = tm11.PollResponse(tm11.generate_message_id(), taxii_message.message_id, collection_name=data_collection.name, exclusive_begin_timestamp_label=inclusive_begin_ts, inclusive_end_timestamp_label=query_params['timestamp_label__lte'], record_count=tm11.RecordCount(len(content_blocks), False)) if taxii_message.poll_parameters.response_type == tm11.RT_FULL: for content_block in content_blocks: cb = tm11.ContentBlock(tm11.ContentBinding(content_block.content_binding.binding_id), content_block.content, content_block.timestamp_label) if content_block.padding: cb.padding = content_block.padding poll_response_message.content_blocks.append(cb) return create_taxii_response(poll_response_message, use_https=request.is_secure())
def inbox_add_content(request, inbox_name, taxii_message): """Adds content to inbox and associated data collections""" logger = logging.getLogger('taxii_services.utils.handlers.inbox_add_content') logger.debug('Adding content to inbox [%s]', make_safe(inbox_name)) if len(taxii_message.destination_collection_names) > 0: logger.debug('Client specified a Destination Collection Name, which is not supported by YETI.') m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_DESTINATION_COLLECTION_ERROR, message='Destination Collection Names are not allowed') return create_taxii_response(m, use_https=request.is_secure()) try: inbox = Inbox.objects.get(name=inbox_name) except: logger.debug('Attempting to push content to unknown inbox [%s]', make_safe(inbox_name)) m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_NOT_FOUND, message='Inbox does not exist [%s]' % (make_safe(inbox_name))) return create_taxii_response(m, use_https=request.is_secure()) logger.debug('TAXII message [%s] contains [%d] content blocks', make_safe(taxii_message.message_id), len(taxii_message.content_blocks)) for content_block in taxii_message.content_blocks: try: content_binding_id = ContentBindingId.objects.get(binding_id=content_block.content_binding) except: logger.debug('TAXII message [%s] contained unrecognized content binding [%s]', make_safe(taxii_message.message_id), make_safe(content_block.content_binding)) continue # cannot proceed - move on to the next content block if content_binding_id not in inbox.supported_content_bindings.all(): logger.debug('Inbox [%s] does not accept content with binding id [%s]', make_safe(inbox_name), make_safe(content_block.content_binding)) else: c = ContentBlock() c.message_id = taxii_message.message_id c.content_binding = content_binding_id c.content = content_block.content if content_block.padding: c.padding = content_block.padding if request.user.is_authenticated(): c.submitted_by = request.user c.save() inbox.content_blocks.add(c) # add content block to inbox for data_collection in inbox.data_collections.all(): if content_binding_id in data_collection.supported_content_bindings.all(): data_collection.content_blocks.add(c) data_collection.save() else: logger.debug('Inbox [%s] received data using content binding [%s] - ' 'associated data collection [%s] does not support this binding.', make_safe(inbox_name), make_safe(content_block.content_binding), make_safe(data_collection.name)) inbox.save() m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type = tm11.ST_SUCCESS) return create_taxii_response(m, use_https=request.is_secure())
def log(self, event): # converts from conpot log format to STIX compatible xml stix_package = self.stix_transformer.transform(event) # wrapping the stix message in a TAXII envelope content_block = ContentBlock(libtaxii.CB_STIX_XML_11, stix_package.encode('utf-8')) inbox_message = InboxMessage(message_id=generate_message_id(), content_blocks=[content_block]) inbox_xml = inbox_message.to_xml() # the actual call to the TAXII web service response = self.client.callTaxiiService2(self.host, self.inbox_path, libtaxii.VID_TAXII_XML_11, inbox_xml, self.port) response_message = libtaxii.get_message_from_http_response( response, '0') if response_message.status_type != libtaxii.messages.ST_SUCCESS: logger.error( 'Error while transmitting message to TAXII server: {0}'.format( response_message.message)) return False else: return True
def main(): parser = scripts.get_base_parser("Poll Fulfillment Client", path="/services/query_example/") parser.add_argument("--collection", dest="collection", default="default_queryable", help="Data Collection that this Fulfillment request applies to. Defaults to 'default_queryable'.") parser.add_argument("--result_id", dest="result_id", required=True, help="The result_id being requested.") parser.add_argument("--result_part_number", dest="result_part_number", default=1, help="The part number being requested. Defaults to '1'.") args = parser.parse_args() poll_fulf_req = tm11.PollFulfillmentRequest(message_id=tm11.generate_message_id(), collection_name=args.collection, result_id=args.result_id, result_part_number=args.result_part_number) print "Request:\n" if args.xml_output is False: print poll_fulf_req.to_text() else: print poll_fulf_req.to_xml(pretty_print=True) client = scripts.create_client(args) resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, poll_fulf_req.to_xml(pretty_print=True), args.port) r = t.get_message_from_http_response(resp, '0') print "Response:\n" if args.xml_output is False: print r.to_text() else: print r.to_xml(pretty_print=True)
def main(): parser = argparse.ArgumentParser(description="Inbox Client") parser.add_argument("--host", dest="host", default="localhost", help="Host where the Inbox Service is hosted. Defaults to localhost.") parser.add_argument("--port", dest="port", default="8080", help="Port where the Inbox Service is hosted. Defaults to 8080.") parser.add_argument("--path", dest="path", default="/services/inbox/default/", help="Path where the Inbox Service is hosted. Defaults to /services/inbox/default/.") parser.add_argument("--content-binding", dest="content_binding", default=t.CB_STIX_XML_10, help="Content binding of the Content Block to send. Defaults to %s" % t.CB_STIX_XML_10 ) parser.add_argument("--content-file", dest="content_file", default=stix_watchlist, help="Content of the Content Block to send. Defaults to a STIX watchlist.") args = parser.parse_args() if args.content_file is stix_watchlist: c = StringIO.StringIO(stix_watchlist) else: c = open(args.content_file, 'r') cb = tm11.ContentBlock(tm11.ContentBinding(args.content_binding), c.read()) c.close() inbox_message = tm11.InboxMessage(message_id = tm11.generate_message_id(), content_blocks=[cb]) inbox_xml = inbox_message.to_xml() print "Inbox Message: \r\n", inbox_xml client = tc.HttpClient() client.setProxy('noproxy') resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, inbox_xml, args.port) response_message = t.get_message_from_http_response(resp, '0') print "Response Message: \r\n", response_message.to_xml()
def create_request_message(self, args): poll_fulf_req = tm11.PollFulfillmentRequest( message_id=tm11.generate_message_id(), collection_name=args.collection, result_id=args.result_id, result_part_number=args.result_part_number) return poll_fulf_req
def push(s, collection, content, path="/"): msg_id=tm11.generate_message_id() content = tm11.ContentBlock(tm11.ContentBinding(t.CB_STIX_XML_11), content) # Create inbox request req = tm11.InboxMessage(message_id=msg_id, destination_collection_names=[collection], content_blocks=[content]) # Convert to XML for request body req_xml = req.to_xml() # Create HTTP client client = tc.HttpClient() client.setProxy('noproxy') # Call TAXII service, using the body resp = client.callTaxiiService2(s.host, path, t.VID_TAXII_XML_11, req_xml, s.port) # Get response resp = t.get_message_from_http_response(resp, '0') if resp.status_type != tm11.ST_SUCCESS: print("%s: %s" % (resp.status_type, resp.message))
def main(): parser = scripts.get_base_parser("Inbox Client", path="/services/inbox/default/") parser.add_argument("--content-binding", dest="content_binding", default=t.CB_STIX_XML_11, help="Content binding of the Content Block to send. Defaults to %s" % t.CB_STIX_XML_11 ) parser.add_argument("--subtype", dest="subtype", default=None, help="The subtype of the Content Binding. Defaults to None") parser.add_argument("--content-file", dest="content_file", default=stix_watchlist, help="Content of the Content Block to send. Defaults to a STIX watchlist.") args = parser.parse_args() if args.content_file is stix_watchlist: c = StringIO.StringIO(stix_watchlist) else: c = open(args.content_file, 'r') cb = tm11.ContentBlock(tm11.ContentBinding(args.content_binding), c.read()) c.close() if args.subtype is not None: cb.subtypes.append(args.subtype) inbox_message = tm11.InboxMessage(message_id = tm11.generate_message_id(), content_blocks=[cb]) inbox_xml = inbox_message.to_xml(pretty_print=True) print "Inbox Message: \r\n", inbox_xml client = scripts.create_client(args) resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, inbox_xml, args.port) response_message = t.get_message_from_http_response(resp, '0') print "Response Message: \r\n", response_message.to_xml(pretty_print=True)
def create_request_message(self, args): try: if args.begin_ts: begin_ts = dateutil.parser.parse(args.begin_ts) if not begin_ts.tzinfo: raise ValueError else: begin_ts = None if args.end_ts: end_ts = dateutil.parser.parse(args.end_ts) if not end_ts.tzinfo: raise ValueError else: end_ts = None except ValueError: print("Unable to parse timestamp value. Timestamp should include both date and time " \ "information along with a timezone or UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). " \ "Aborting poll.") sys.exit() create_kwargs = {'message_id': tm11.generate_message_id(), 'collection_name': args.collection, 'exclusive_begin_timestamp_label': begin_ts, 'inclusive_end_timestamp_label': end_ts} if args.subscription_id: create_kwargs['subscription_id'] = args.subscription_id else: create_kwargs['poll_parameters'] = tm11.PollRequest.PollParameters() poll_req = tm11.PollRequest(**create_kwargs) return poll_req
def create_fulfillment_request(collection, result_id, part_number): return PollFulfillmentRequest( message_id=generate_message_id(), collection_name=collection, result_id=result_id, result_part_number=part_number, )
def create_request_message(self, args): try: if args.begin_ts: begin_ts = dateutil.parser.parse(args.begin_ts) if not begin_ts.tzinfo: raise ValueError else: begin_ts = None if args.end_ts: end_ts = dateutil.parser.parse(args.end_ts) if not end_ts.tzinfo: raise ValueError else: end_ts = None except ValueError: print("Unable to parse timestamp value. Timestamp should include both date and time " \ "information along with a timezone or UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). " \ "Aborting poll.") sys.exit() create_kwargs = { 'message_id': tm11.generate_message_id(), 'collection_name': args.collection, 'exclusive_begin_timestamp_label': begin_ts, 'inclusive_end_timestamp_label': end_ts } if args.subscription_id: create_kwargs['subscription_id'] = args.subscription_id else: create_kwargs['poll_parameters'] = tm11.PollRequest.PollParameters( ) poll_req = tm11.PollRequest(**create_kwargs) return poll_req
def handle_manage_collection_subscription_request(s, msg): print(msg.to_xml(True)) # Create poll response. msg_id=tm11.generate_message_id() cn=msg.collection_name resp_id=msg.message_id action=msg.action query=msg.subscription_parameters.query subs_id=msg.subscription_id inbox=msg.push_parameters.inbox_address if query: print(query.to_xml()) if action == tm11.ACT_SUBSCRIBE: subs_id = s.subscribe(collection=cn, query=query, inbox=inbox) si = tm11.ManageCollectionSubscriptionResponse.SubscriptionInstance( subscription_id=subs_id, status=tm11.SS_ACTIVE ) resp = tm11.ManageCollectionSubscriptionResponse( message_id=msg_id, collection_name=cn, in_response_to=resp_id, subscription_instances=[si] ) # Send response s.respond(resp.to_xml())
def _get_inbox_message(self, cb): return tm11.InboxMessage( message_id=tm11.generate_message_id(), destination_collection_names=[self._collection_name], subscription_information=self._subscription_information, content_blocks=[cb], )
def envio_informacion(data_feed, host, path, port): #Given the host, port and path of a TAXII client we sent the data_feed to that client. logger = logging.getLogger('TAXIIApplication.rest.tasks.envio_informacion') logger.debug('Get the subscription methods') logger.debug('The parameters are: ') logger.debug('Host: ' + host) logger.debug('Path: ' + path) logger.debug('Port: ' + str(port)) logger.debug('Data Feed name:' + data_feed.name) content_blocks = data_feed.content_blocks content = [] for content_block in content_blocks.all(): cb = tm11.ContentBlock(tm11.ContentBinding(content_block.content_binding.binding_id), content_block.content) content.append(cb) subInfo = tm11.InboxMessage.SubscriptionInformation(collection_name = data_feed.title + ' ' + ORGANIZATION_NAME, subscription_id = 1) inbox_message = tm11.InboxMessage(message_id = tm11.generate_message_id(), content_blocks=content, subscription_information = subInfo) inbox_xml = inbox_message.to_xml() logger.debug('The message to be sent is: '+ inbox_xml) client = tc.HttpClient() client.setProxy('noproxy') resp = client.callTaxiiService2(host, path, t.VID_TAXII_XML_10, inbox_xml, port) response_message = t.get_message_from_http_response(resp, '0') logger.debug('The response message was: ' + response_message.to_xml())
def push_11(taxii_client, stix_file_doc): if stix_file_doc.version.startswith('2'): try: content = stix_file_doc.get_slide_12() except Exception as e: traceback.print_exc() raise e else: with open(stix_file_doc.origin_path, 'r', encoding='utf-8') as fp: content = fp.read() auth_credentials_dict, cert_fd, key_fd = _get_auth_credentials_dict( taxii_client) taxii_client._client.set_auth_credentials(auth_credentials_dict) try: subscription_information = tm11.SubscriptionInformation( collection_name=taxii_client._collection_name, subscription_id='subscripiton_id') cb = tm11.ContentBlock(const.CB_STIX_XML_11, content) im = tm11.InboxMessage( message_id=tm11.generate_message_id(), destination_collection_names=[taxii_client._collection_name], subscription_information=subscription_information, content_blocks=[cb]) http_resp = taxii_client._client.call_taxii_service2( taxii_client._address, taxii_client._path, const.VID_TAXII_XML_11, im.to_xml(), port=taxii_client._port) taxii_message = libtaxii.get_message_from_http_response( http_resp, im.message_id) if taxii_message.status_type != 'SUCCESS': raise Exception('taxii_message.status_type is not SUCCESS') return 'Success !!' except Exception as e: traceback.print_exc() raise e finally: if cert_fd is not None: try: os.close(cert_fd) except Exception: pass if key_fd is not None: try: os.close(key_fd) except Exception: pass if 'cert_file' in auth_credentials_dict: try: os.remove(auth_credentials_dict['cert_file']) except Exception: pass if 'key_file' in auth_credentials_dict: try: os.remove(auth_credentials_dict['key_file']) except Exception: pass
def get_discovery_service( self, taxii_message: DiscoveryRequest) -> DiscoveryResponse: """ Handle discovery request. Args: taxii_message: The discovery request message. Returns: The discovery response. """ if taxii_message.message_type != MSG_DISCOVERY_REQUEST: raise ValueError('Invalid message, invalid Message Type') discovery_service_url = self.get_url() discovery_response = DiscoveryResponse(generate_message_id(), taxii_message.message_id) for instance in self.service_instances: instance_type = instance['type'] instance_path = instance['path'] taxii_service_instance = ServiceInstance( instance_type, 'urn:taxii.mitre.org:services:1.1', 'urn:taxii.mitre.org:protocol:http:1.0', f'{discovery_service_url}/{instance_path}', ['urn:taxii.mitre.org:message:xml:1.1'], available=True) discovery_response.service_instances.append(taxii_service_instance) return discovery_response
def get_collections( self, taxii_message: CollectionInformationRequest ) -> CollectionInformationResponse: """ Handle collection management request. Args: taxii_message: The collection request message. Returns: The collection management response. """ taxii_feeds = list(self.collections.keys()) url = self.get_url() if taxii_message.message_type != MSG_COLLECTION_INFORMATION_REQUEST: raise ValueError('Invalid message, invalid Message Type') collection_info_response = CollectionInformationResponse( generate_message_id(), taxii_message.message_id) for feed in taxii_feeds: collection_info = CollectionInformation( feed, f'{feed} Data Feed', ['urn:stix.mitre.org:xml:1.1.1'], True) polling_instance = PollingServiceInstance( 'urn:taxii.mitre.org:protocol:http:1.0', f'{url}/taxii-poll-service', ['urn:taxii.mitre.org:message:xml:1.1']) collection_info.polling_service_instances.append(polling_instance) collection_info_response.collection_informations.append( collection_info) return collection_info_response
def inner(request, *args, **kwargs): if not taxii_services.settings.AUTH_REQUIRED: return func(request, *args, **kwargs) elif request.user.is_authenticated(): return func(request, *args, **kwargs) m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm.ST_UNAUTHORIZED, message='You are not authorized to access this URL.') return handlers.create_taxii_response(m)
def handle_discovery_request(s, msg): # Create poll response. resp = tm11.DiscoveryResponse(message_id=tm11.generate_message_id(), in_response_to=msg.message_id) # Send response s.respond(resp.to_xml())
def poll_11(self): auth_credentials_dict = self._get_auth_credentials_dict() self._client.set_auth_credentials(auth_credentials_dict) try: poll_parameters = tm11.PollParameters() poll_request = tm11.PollRequest( message_id=tm11.generate_message_id(), collection_name=self._collection_name, exclusive_begin_timestamp_label=self._start, inclusive_end_timestamp_label=self._end, poll_parameters=poll_parameters, ) last_requested = datetime.datetime.now(pytz.utc) http_resp = self._client.call_taxii_service2( self._address, self._path, const.VID_TAXII_XML_11, poll_request.to_xml(), port=self._port) taxii_message = libtaxii.get_message_from_http_response( http_resp, poll_request.message_id) try: if taxii_message.content_blocks is None: return 0 except AttributeError: return 0 count = 0 for cb in taxii_message.content_blocks: _, stix_file_path = tempfile.mkstemp(suffix='.xml') with open(stix_file_path, 'wb+') as fp: fp.write(cb.content) try: from ctirs.core.stix.regist import regist if self._community is not None: regist(stix_file_path, self._community, self._via) count += 1 except BaseException: traceback.print_exc() self._taxii.last_requested = last_requested self._taxii.save() return count finally: if 'cert_file' in auth_credentials_dict: try: os.remove(auth_credentials_dict['cert_file']) except Exception: pass if 'key_file' in auth_credentials_dict: try: os.remove(auth_credentials_dict['key_file']) except Exception: pass
def test_status_message_03(self): sm03 = tm11.StatusMessage( message_id = 'SM03', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_DESTINATION_COLLECTION_ERROR, #Required status_detail = {'ACCEPTABLE_DESTINATION': ['Collection1','Collection2']}, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm03)
def handle_collection_information_request(s, msg): # Create poll response. msg_id=tm11.generate_message_id() resp = tm11.CollectionInformationResponse(message_id=msg_id, in_response_to=msg.message_id) # Send response s.respond(resp.to_xml())
def test_status_message_04(self): sm04 = tm11.StatusMessage( message_id = 'SM04', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_INVALID_RESPONSE_PART, #Required status_detail = {'MAX_PART_NUMBER': 4}, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm04)
def test_status_message_06(self): sm06 = tm11.StatusMessage( message_id = 'SM06', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_PENDING, #Required status_detail = {'ESTIMATED_WAIT': 900, 'RESULT_ID': 'Result1', 'WILL_PUSH': False}, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm06)
def test_status_message_07(self): sm07 = tm11.StatusMessage( message_id = 'SM07', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_RETRY, #Required status_detail = {'ESTIMATED_WAIT': 900}, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm07)
def test_status_message_08(self): sm08 = tm11.StatusMessage( message_id = 'SM08', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_UNSUPPORTED_MESSAGE_BINDING, #Required status_detail = {'SUPPORTED_BINDING': [t.VID_TAXII_XML_10, t.VID_TAXII_XML_11]}, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm08)
def test_status_message_09(self): sm09 = tm11.StatusMessage( message_id = 'SM09', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_UNSUPPORTED_CONTENT_BINDING, #Required status_detail = {'SUPPORTED_CONTENT': ['%s>%s,%s' % (tm11.ContentBinding, 'subtype1','subtype2'), t.CB_STIX_XML_101]}, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm09)
def test_status_message_02(self): sm02 = tm11.StatusMessage( message_id = 'SM02', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_SUCCESS, #Required status_detail = None, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm02)
def test_status_message_05(self): sm05 = tm11.StatusMessage( message_id = 'SM05', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_NOT_FOUND, #Required status_detail = {'ITEM': 'Collection1'}, #Required/optional depending on Status Type. See spec for details message = None# Optional ) round_trip_message(sm05)
def validate_taxii_headers(request, request_message_id): """ Validates TAXII headers. It returns a response containing a TAXII status message if the headers were not valid. It returns None if the headers are valid. """ # Make sure the required headers are present missing_required_headers = set(DICT_REQUIRED_TAXII_HTTP_HEADERS).difference(set(request.META)) if missing_required_headers: required_headers = ', '.join(DICT_REVERSE_DJANGO_NORMALIZATION[x] for x in missing_required_headers) msg = "Required headers not present: [%s]" % (required_headers) m = tm11.StatusMessage(tm11.generate_message_id(), request_message_id, status_type=tm11.ST_FAILURE, message=msg) return create_taxii_response(m, use_https=request.is_secure()) #For headers that exist, make sure the values are supported for header in DICT_TAXII_HTTP_HEADER_VALUES: if header not in request.META: continue header_value = request.META[header] supported_values = DICT_TAXII_HTTP_HEADER_VALUES[header] if header_value not in supported_values: msg = 'The value of %s is not supported. Supported values are %s' % (DICT_REVERSE_DJANGO_NORMALIZATION[header], supported_values) m = tm11.StatusMessage(tm11.generate_message_id(), request_message_id, status_type=tm11.ST_FAILURE, message=msg) return create_taxii_response(m, use_https=request.is_secure()) # Check to make sure the specified protocol matches the protocol used if request.META[DJANGO_HTTP_HEADER_X_TAXII_PROTOCOL] == t.VID_TAXII_HTTPS_10: header_proto = 'HTTPS' elif request.META[DJANGO_HTTP_HEADER_X_TAXII_PROTOCOL] == t.VID_TAXII_HTTP_10: header_proto = 'HTTP' else: header_proto = 'unknown' request_proto = 'HTTPS' if request.is_secure() else 'HTTP' # Did the request come over HTTP or HTTPS? if header_proto != request_proto: msg = 'Protocol value incorrect. TAXII header specified %s but was sent over %s' % (header_proto, request_proto) m = tm11.StatusMessage(tm11.generate_message_id(), request_message_id, status_type=tm11.ST_FAILURE, message=msg) return create_taxii_response(m, use_https=request.is_secure()) # At this point, the header values are known to be good. return None
def poll_11(self): #request xml作成 poll_parameters = tm11.PollParameters() poll_request = tm11.PollRequest( message_id=tm11.generate_message_id(), collection_name=self._collection_name, exclusive_begin_timestamp_label=self._start, inclusive_end_timestamp_label=self._end, poll_parameters=poll_parameters, ) last_requested = datetime.datetime.now(pytz.utc) #from xml.dom.minidom import parseString #print( parseString(poll_request.to_xml()).toprettyxml(encoding='utf-8')) #request http_resp = self._client.call_taxii_service2( self._address, self._path, const.VID_TAXII_XML_11, poll_request.to_xml(), port=self._port) #taxii_message抽出 taxii_message = libtaxii.get_message_from_http_response(http_resp, poll_request.message_id) #content_blocks が None or 存在しない場合は登録ししない try: if taxii_message.content_blocks is None: return 0 except AttributeError: return 0 #content_blocksごとに登録処理 count = 0 for cb in taxii_message.content_blocks: #stixファイルを一時ファイルに出力 _,stix_file_path = tempfile.mkstemp(suffix='.xml') with open(stix_file_path,'wb+') as fp: #cb.contentがstixの中身 fp.write(cb.content) #登録 try: from ctirs.core.stix.regist import regist if self._community is not None: regist(stix_file_path,self._community,self._via) count += 1 except: #taxiiの場合は途中で失敗しても処理を継続する traceback.print_exc() #last_requested更新 self._taxii.last_requested = last_requested self._taxii.save() return count
def test_status_message_01(self): sm01 = tm11.StatusMessage( message_id = 'SM01', #Required in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to status_type = tm11.ST_SUCCESS, #Required status_detail = {'custom_status_detail_name': 'Custom status detail value', 'Custom_detail_2': ['this one has', 'multiple values']}, #Required depending on Status Type. See spec for details message = 'This is a test message'#Optional ) round_trip_message(sm01)
def process_exception(self, request, exception): logger = logging.getLogger('yeti.taxii_services.middleware.ProcessExceptionMiddleware.process_exception') logger.exception('Server error occured') if request.path.startswith('/services'): logger.debug('Returning ST_FAILURE message') m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_FAILURE, message='An internal server error occurred') return handlers.create_taxii_response(m, handlers.HTTP_STATUS_OK, use_https=request.is_secure()) resp = HttpResponseServerError() resp.body = 'A server error occurred' return resp
def test_nonexistent_service_url(self): """ Sends an Inbox Message to an invalid URL. Should get back a 404. """ # TODO: Why do we actually need a payload to return a 404? Shouldn't an # empty message to a non-existent URL also return a 404? inbox_msg = tm11.InboxMessage(tm11.generate_message_id()) path = '/Services/PathThatShouldNotWork/' response = self.post(path, inbox_msg.to_xml()) self.assertEqual(404, response.status_code)
def main(): parser = scripts.get_base_parser("Discovery Client", path="/services/discovery/") args = parser.parse_args() discovery_req = tm11.DiscoveryRequest(message_id=tm11.generate_message_id()) discovery_req_xml = discovery_req.to_xml(pretty_print=True) print "Discovery Request: \r\n", discovery_req_xml client = scripts.create_client(args) resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, discovery_req_xml, args.port) response_message = t.get_message_from_http_response(resp, '0') print "Response Message: \r\n", response_message.to_xml(pretty_print=True)
def taxii_inbox(config, dest, stix_package=None, src=None, crits_id=None): """inbox a stix package via taxii""" if src and crits_id: # check whether this has already been ingested sync_state = config["db"].get_object_id(src, dest, crits_id=crits_id) if sync_state and sync_state.get("crits_id", None): if config["daemon"]["debug"]: config["logger"].debug( log.log_messages["object_already_ingested"].format( src_type="crits", src_id=crits_id, src=src, dest_type="edge", dest=dest, dest_id=sync_state["edge_id"], ) ) return True if stix_package: stixroot = lxml.etree.fromstring(stix_package.to_xml()) client = tc.HttpClient() client.setUseHttps(config["edge"]["sites"][dest]["taxii"]["ssl"]) client.setAuthType(client.AUTH_BASIC) client.setAuthCredentials( { "username": config["edge"]["sites"][dest]["taxii"]["user"], "password": config["edge"]["sites"][dest]["taxii"]["pass"], } ) message = tm11.InboxMessage(message_id=tm11.generate_message_id()) content_block = tm11.ContentBlock(content_binding=t.CB_STIX_XML_11, content=stixroot) if config["edge"]["sites"][dest]["taxii"]["collection"] != "system.Default": message.destination_collection_names = [config["edge"]["sites"][dest]["taxii"]["collection"]] message.content_blocks.append(content_block) if config["daemon"]["debug"]: config["logger"].debug(log.log_messages["open_session"].format(type_="taxii", host=dest)) taxii_response = client.callTaxiiService2( config["edge"]["sites"][dest]["host"], config["edge"]["sites"][dest]["taxii"]["path"], t.VID_TAXII_XML_11, message.to_xml(), port=config["edge"]["sites"][dest]["taxii"]["port"], ) if taxii_response.code != 200 or taxii_response.msg != "OK": success = False config["logger"].error( log.log_messages["inbox_error"].format(type_="taxii", host=dest, msg=taxii_response.msg) ) else: success = True if config["daemon"]["debug"]: config["logger"].debug(log.log_messages["inbox_success"].format(type_="taxii", host=dest)) return success
def taxii_inbox(config, dest, stix_package=None, src=None, crits_id=None): '''inbox a stix package via taxii''' if src and crits_id: # check whether this has already been ingested sync_state = config['db'].get_object_id(src, dest, crits_id=crits_id) if sync_state and sync_state.get('crits_id', None): if config['daemon']['debug']: config['logger'].debug( log.log_messages['object_already_ingested'].format( src_type='crits', src_id=crits_id, src=src, dest_type='edge', dest=dest, dest_id=sync_state['edge_id'])) return(True) if stix_package: stixroot = lxml.etree.fromstring(stix_package.to_xml()) client = tc.HttpClient() client.setUseHttps(config['edge']['sites'][dest]['taxii']['ssl']) client.setAuthType(client.AUTH_BASIC) client.setAuthCredentials( {'username': config['edge']['sites'][dest]['taxii']['user'], 'password': config['edge']['sites'][dest]['taxii']['pass']}) message = tm11.InboxMessage(message_id=tm11.generate_message_id()) content_block = tm11.ContentBlock(content_binding=t.CB_STIX_XML_11, content=stixroot) if config['edge']['sites'][dest]['taxii']['collection'] != \ 'system.Default': message.destination_collection_names = \ [config['edge']['sites'][dest]['taxii']['collection']] message.content_blocks.append(content_block) if config['daemon']['debug']: config['logger'].debug( log.log_messages[ 'open_session'].format(type_='taxii', host=dest)) taxii_response = client.callTaxiiService2( config['edge']['sites'][dest]['host'], config['edge']['sites'][dest]['taxii']['path'], t.VID_TAXII_XML_11, message.to_xml(), port=config['edge']['sites'][dest]['taxii']['port']) if taxii_response.code != 200 or taxii_response.msg != 'OK': success = False config['logger'].error( log.log_messages[ 'inbox_error'].format(type_='taxii', host=dest, msg=taxii_response.msg)) else: success = True if config['daemon']['debug']: config['logger'].debug( log.log_messages['inbox_success'].format(type_='taxii', host=dest)) return(success)
def taxii_inbox(config, dest, stix_package=None, src=None, crits_id=None): '''inbox a stix package via taxii''' if src and crits_id: # check whether this has already been ingested sync_state = config['db'].get_object_id(src, dest, crits_id=crits_id) if sync_state and sync_state.get('crits_id', None): if config['daemon']['debug']: config['logger'].debug( log_.log_messages['object_already_ingested'].format( src_type='crits', src_id=crits_id, src=src, dest_type='edge', dest=dest, dest_id=sync_state['edge_id'])) return(True) if stix_package: stixroot = lxml.etree.fromstring(stix_package.to_xml()) client = tc.HttpClient() client.setUseHttps(config['edge']['sites'][dest]['taxii']['ssl']) client.setAuthType(client.AUTH_BASIC) client.setAuthCredentials( {'username': config['edge']['sites'][dest]['taxii']['user'], 'password': config['edge']['sites'][dest]['taxii']['pass']}) message = tm11.InboxMessage(message_id=tm11.generate_message_id()) content_block = tm11.ContentBlock(content_binding=t.CB_STIX_XML_11, content=stixroot) if config['edge']['sites'][dest]['taxii']['collection'] != \ 'system.Default': message.destination_collection_names = \ [config['edge']['sites'][dest]['taxii']['collection']] message.content_blocks.append(content_block) if config['daemon']['debug']: config['logger'].debug( log_.log_messages[ 'open_session'].format(type_='taxii', host=dest)) taxii_response = client.callTaxiiService2( config['edge']['sites'][dest]['host'], config['edge']['sites'][dest]['taxii']['path'], t.VID_TAXII_XML_11, message.to_xml(), port=config['edge']['sites'][dest]['taxii']['port']) if taxii_response.code != 200 or taxii_response.msg != 'OK': success = False config['logger'].error( log_.log_messages[ 'inbox_error'].format(type_='taxii', host=dest, msg=taxii_response.msg)) else: success = True if config['daemon']['debug']: config['logger'].debug( log_.log_messages['inbox_success'].format(type_='taxii', host=dest)) return(success)
def validate_taxii_request(request): """Validates the broader request parameters and request type for a TAXII exchange""" logger = logging.getLogger("taxii_services.utils.handlers.validate_taxii_request") logger.debug('Attempting to validate request') if request.method != 'POST': logger.info('Request was not POST - returning error') m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_FAILURE, message='Request must be POST') return create_taxii_response(m, use_https=request.is_secure()) header_validation_resp = validate_taxii_headers(request, '0') # TODO: What to use for request message id? if header_validation_resp: # If response is not None an validation of the TAXII headers failed logger.info('TAXII header validation failed for reason [%s]', make_safe(header_validation_resp.message)) return header_validation_resp if len(request.body) == 0: m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_FAILURE, message='No POST data') logger.info('Request had a body length of 0. Returning error.') return create_taxii_response(m, use_https=request.is_secure()) logger.debug('Request was valid') return None
def push_11(self, stix_file_doc): self.debug_print('>>> push_11: enter') # stix_file_doc の versionが 2.0 ならスライド if stix_file_doc.version == '2.0': try: content = stix_file_doc.get_slide_1_x() except Exception as e: traceback.print_exc() raise e else: with open(stix_file_doc.origin_path, 'r', encoding='utf-8') as fp: content = fp.read() # Subscription Information xml作成 subscription_information = tm11.SubscriptionInformation( collection_name=self._collection_name, subscription_id='subscripiton_id') cb = tm11.ContentBlock(const.CB_STIX_XML_11, content) im = tm11.InboxMessage( message_id=tm11.generate_message_id(), destination_collection_names=[self._collection_name], subscription_information=subscription_information, content_blocks=[cb]) try: # push self._address = '10.0.3.100' # self.debug_print('>>> push_11: self._address:%s' %(self._address)) # self.debug_print('>>> push_11: self._path:%s' %(self._path)) # self.debug_print('>>> push_11: self._port:%d' %(self._port)) # self.debug_print('>>> push_11: self._collection_name:%s' %(self._collection_name)) # self.debug_print('>>> push_11: verify_server:%s' %(str(self._client.verify_server))) # self.debug_print('>>> push_11: use_https:%s' %(str(self._client.use_https))) http_resp = self._client.call_taxii_service2( self._address, self._path, const.VID_TAXII_XML_11, im.to_xml(), port=self._port) taxii_message = libtaxii.get_message_from_http_response( http_resp, im.message_id) if taxii_message.status_type != 'SUCCESS': self.debug_print('taxii_message.status_type is not SUCCESS') self.debug_print(taxii_message.to_xml(pretty_print=True)) raise Exception('taxii_message.status_type is not SUCCESS') except Exception as e: traceback.print_exc() self.debug_print(e) raise e
def discovery_service(request): """Handles TAXII Discovery Service requests""" logger = logging.getLogger('yeti.taxii_services.views.discovery_service') logger.debug('Entering discovery service') resp = handlers.validate_taxii_request(request) if resp: return resp # if validation fails, return the response try: taxii_message = tm11.get_message_from_xml(request.body) except Exception as ex: logger.debug('Unable to parse inbound message: %s', ex.message) m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_BAD_MESSAGE, message='Message received could not be parsed') return handlers.create_taxii_response(m, use_https=request.is_secure()) logger.debug('Discovery service received TAXII message with id [%s] and type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) if taxii_message.message_type != tm11.MSG_DISCOVERY_REQUEST: logger.info('TAXII message with id [%s] was not Discovery request [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type)) m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_FAILURE, message='Message sent to discovery service did not have a discovery request message type') return handlers.create_taxii_response(m, use_https=request.is_secure()) resp = handlers.discovery_get_services(request, taxii_message) return resp
def gen_post(self, msg_type, xml): content_block = tm11.ContentBlock(tm11.ContentBinding(Client.BINDING_STIX), xml) if msg_type.lower() == 'inbox': post = tm11.InboxMessage(tm11.generate_message_id()) post.content_blocks.append(content_block) post.message = Client.CLIENT_MSG if self.subscription: post.subscription_id = self.subscription if self.collection: post.destination_collection_names.append(self.collection) return post
def main(): parser = argparse.ArgumentParser(description="Poll Client") parser.add_argument("--host", dest="host", default="localhost", help="Host where the Poll Service is hosted. Defaults to localhost.") parser.add_argument("--port", dest="port", default="8080", help="Port where the Poll Service is hosted. Defaults to 8080.") parser.add_argument("--path", dest="path", default="/services/poll/", help="Path where the Poll Service is hosted. Defaults to /services/poll/.") parser.add_argument("--feed", dest="feed", default="default", help="Data Feed to poll. Defaults to 'default'.") parser.add_argument("--begin_timestamp", dest="begin_ts", default=None, help="The begin timestamp (format: YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm) for the poll request. Defaults to None.") parser.add_argument("--end_timestamp", dest="end_ts", default=None, help="The end timestamp (format: YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm) for the poll request. Defaults to None.") parser.add_argument("--content-binding", dest="content_binding", default= t.CB_STIX_XML_10, help="Content binding of the Content Block to send. Defaults to %s" % t.CB_STIX_XML_10 ) args = parser.parse_args() try: if args.begin_ts: begin_ts = dateutil.parser.parse(args.begin_ts) if not begin_ts.tzinfo: raise ValueError else: begin_ts = None if args.end_ts: end_ts = dateutil.parser.parse(args.end_ts) if not end_ts.tzinfo: raise ValueError else: end_ts = None except ValueError: print "Unable to parse timestamp value. Timestamp should include both date and time information along with a timezone or UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). Aborting poll." sys.exit() poll_req = tm11.PollRequest(message_id=tm11.generate_message_id(), collection_name = args.feed, exclusive_begin_timestamp_label=begin_ts, inclusive_end_timestamp_label=end_ts, subscription_id='1') poll_req_xml = poll_req.to_xml() print "Poll Request: \r\n", poll_req_xml client = tc.HttpClient() resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_10, poll_req_xml, args.port) response_message = t.get_message_from_http_response(resp, '0') print "Response Message: \r\n", response_message.to_xml() message = tm11.get_message_from_xml(response_message.to_xml()) response_message.
def create_request_message(self, args): if args.content_file is self.stix_watchlist: data = self.stix_watchlist else: with open(args.content_file, 'r') as f: data = f.read() cb = tm11.ContentBlock(tm11.ContentBinding(args.content_binding), data) if args.subtype is not None: cb.content_binding.subtype_ids.append(args.subtype) inbox_message = tm11.InboxMessage(message_id=tm11.generate_message_id(), content_blocks=[cb]) if args.dcn: inbox_message.destination_collection_names.append(args.dcn) return inbox_message
def handle_inbox_message(s, msg): # Process each content block for cb in msg.content_blocks: content = cb.content for collection in msg.destination_collection_names: s.received(content, collection) resp = tm11.StatusMessage(message_id=tm11.generate_message_id(), in_response_to=msg.message_id, status_type=tm11.ST_SUCCESS) # Respond s.respond(resp.to_xml())
def indicators(self, collection_name, starttime=(datetime.now(tzutc()) - timedelta(hours=1)), endtime=datetime.now(tzutc()), subscription_id=None): delivery_params = tm11.DeliveryParameters(VID_TAXII_HTTP_10, self.remote, VID_TAXII_XML_11) """ poll_params = tm11.PollParameters(response_type=RT_COUNT_ONLY, #content_bindings=[tm11.ContentBinding(CB_STIX_XML_11)], delivery_parameters=delivery_params ) """ poll_params = tm11.PollRequest.PollParameters() poll_req = tm11.PollRequest(message_id=tm11.generate_message_id(), collection_name=collection_name, exclusive_begin_timestamp_label=starttime, inclusive_end_timestamp_label=endtime, poll_parameters=poll_params, subscription_id=subscription_id) logger.debug('TAXII collection poll request: {}'.format( poll_req.to_xml(pretty_print=True))) poll_req_xml = poll_req.to_xml() http_resp = self.client.call_taxii_service2(self.up.hostname, self.up.path, VID_TAXII_XML_11, poll_req_xml, self.up.port) taxii_message = t.get_message_from_http_response( http_resp, poll_req.message_id) logger.debug('TAXII collection poll response: {}'.format( taxii_message.to_xml(pretty_print=True))) if taxii_message.message_type == MSG_STATUS_MESSAGE: if taxii_message.status_type == ST_SUCCESS: logger.info( 'TAXII polled successfully but returned no results') return [] raise RuntimeError('TAXII polling failed: {} - {}'.format( taxii_message.status_type, taxii_message.message)) return self._parse_taxii_content(taxii_message.content_blocks)
def poll(s, path="/", collection="default", query=None, begin_ts=None, end_ts=None): if query != None: query=s.create_query(query) poll_params=tm11.PollRequest.PollParameters(query=query) else: poll_params=tm11.PollRequest.PollParameters() # Create poll request poll_req = tm11.PollRequest(message_id=tm11.generate_message_id(), collection_name=collection, exclusive_begin_timestamp_label=begin_ts, inclusive_end_timestamp_label=end_ts, poll_parameters=poll_params) # Convert to XML for request body poll_req_xml = poll_req.to_xml(True) # Create HTTP client client = tc.HttpClient() client.setProxy('noproxy') # Call TAXII service, using the body resp = client.callTaxiiService2(s.host, path, t.VID_TAXII_XML_11, poll_req_xml, s.port) # Get response resp = t.get_message_from_http_response(resp, '0') pkgs = [] # Process each content block for cb in resp.content_blocks: content = cb.content # Parse the payload, should be a STIX document. package = STIXPackage.from_xml(StringIO.StringIO(content)) pkgs.append(package) return resp.inclusive_end_timestamp_label, pkgs
def create_poll_request(collection, subscription_id=None, begin_timestamp=None, end_timestamp=None): """Create a poll request message using supplied parameters.""" request_kwargs = dict( message_id=generate_message_id(), collection_name=collection, exclusive_begin_timestamp_label=begin_timestamp, inclusive_end_timestamp_label=end_timestamp, ) if subscription_id: request_kwargs['subscription_id'] = subscription_id else: request_kwargs['poll_parameters'] = PollRequest.PollParameters() return PollRequest(**request_kwargs)
def perform_discovery(path="/"): # Create discovery request req = tm11.DiscoveryRequest(message_id=tm11.generate_message_id()) # Convert to XML for request body req_xml = req.to_xml() # Create HTTP client client = tc.HttpClient() client.setProxy('noproxy') # Call TAXII service, using the body resp = client.callTaxiiService2(host, path, t.VID_TAXII_XML_11, req_xml, port) # Get response resp = t.get_message_from_http_response(resp, '0') print(resp.to_xml())
def subscribe(s, path="/", collection="default", query=None, inbox="http://localhost:8888"): if query != None: query = s.create_query(query) else: query = None params = tm11.SubscriptionParameters(query=query) deliv = tm11.PushParameters( inbox_protocol=t.VID_TAXII_HTTP_10, inbox_address=inbox, delivery_message_binding=t.VID_TAXII_XML_11) # Create request msg_id=tm11.generate_message_id() req = tm11.ManageCollectionSubscriptionRequest( message_id=msg_id, collection_name=collection, action=tm11.ACT_SUBSCRIBE, subscription_parameters=params, push_parameters=deliv ) # Convert to XML for request body req_xml = req.to_xml() # Create HTTP client client = tc.HttpClient() client.setProxy('noproxy') # Call TAXII service, using the body resp = client.callTaxiiService2(s.host, path, t.VID_TAXII_XML_11, req_xml, s.port) # Get response resp = t.get_message_from_http_response(resp, '0') print(resp.to_xml())
def create_poll_request(self): """Create a poll request message using supplied parameters.""" try: if self._begin_ts: begin_ts = dateutil.parser.parse(self._begin_ts) if not begin_ts.tzinfo: raise ValueError else: begin_ts = None if self._end_ts: end_ts = dateutil.parser.parse(self._end_ts) if not end_ts.tzinfo: raise ValueError else: end_ts = None except ValueError: self._logger.error( "Unable to parse timestamp value. Timestamp should include " + "both date and time information along with a timezone or " + "UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). " + "Aborting poll.") sys.exit() request_kwargs = { 'message_id': generate_message_id(), 'collection_name': self._collection, 'exclusive_begin_timestamp_label': begin_ts, 'inclusive_end_timestamp_label': end_ts, } if self._subscription_id: request_kwargs['subscription_id'] = self._subscription_id else: request_kwargs['poll_parameters'] = PollRequest.PollParameters() return PollRequest(**request_kwargs)
def perform_manage_collection_subscription(path="/", act="status", collection="default"): if act == "subscribe": action = tm11.ACT_SUBSCRIBE elif act == "unsubscribe": action = tm11.ACT_UNSUBSCRIBE elif act == "pause": action = tm11.ACT_PAUSE elif act == "resume": action = tm11.ACT_RESUME elif act == "status": action = tm11.ACT_STATUS else: print("Need a subscription action I recognise") sys.exit(1) # Create request msg_id=tm11.generate_message_id() req = tm11.ManageCollectionSubscriptionRequest(message_id=msg_id, collection_name=collection, action=action) # Convert to XML for request body req_xml = req.to_xml() # Create HTTP client client = tc.HttpClient() client.setProxy('noproxy') # Call TAXII service, using the body resp = client.callTaxiiService2(host, path, t.VID_TAXII_XML_11, req_xml, port) # Get response resp = t.get_message_from_http_response(resp, '0') print(resp.to_xml())
def do_POST(s): # Get the HTTP bdoy varLen = int(s.headers['Content-Length']) data = s.rfile.read(varLen) # Parse body as TAXII message. msg = tm11.get_message_from_xml(data) # If it's a poll request, handle it. if type(msg) == tm11.PollRequest: s.handle_poll_request(msg) return if type(msg) == tm11.InboxMessage: s.handle_inbox_message(msg) return if type(msg) == tm11.DiscoveryRequest: s.handle_discovery_request(msg) return if type(msg) == tm11.CollectionInformationRequest: s.handle_collection_information_request(msg) return if type(msg) == tm11.ManageCollectionSubscriptionRequest: s.handle_manage_collection_subscription_request(msg) return # Sorry, I only handle inbox and poll requests. resp = tm11.StatusMessage(message_id=tm11.generate_message_id(), in_response_to=msg.message_id, status_type=tm11.ST_FAILURE, message="Your request type not supported.") s.respond(resp.to_xml())
def handle_poll_request(s, msg): collection = msg.collection_name query = msg.poll_parameters.query begin = msg.exclusive_begin_timestamp_label end = msg.inclusive_end_timestamp_label # Start constructing the content block list cbs = [] def handle(content, file): print("Adding %s..." % file) # Create content block. cb = tm11.ContentBlock(tm11.ContentBinding(t.CB_STIX_XML_11), content) # Append content block to list. cbs.append(cb) print("Building response...") latest = s.get_matching(collection, begin, end, query, handle) print("Done") # Create poll response. resp = tm11.PollResponse(message_id=tm11.generate_message_id(), in_response_to=msg.message_id, collection_name=msg.collection_name, inclusive_end_timestamp_label=latest, content_blocks=cbs, more=False) # Send response s.respond(resp.to_xml())
def _poll_taxii_11(self, args): '''Poll a TAXII 1.1 feed and return a generator over the content blocks found. Arguments: args - A dictionary of arguments. ''' app = args.get('app') cert_file = args.get('cert_file') key_file = args.get('key_file') username = args.get('username') password = args.get('password') if app and cert_file and key_file: cert_file_path = make_splunkhome_path( ["etc", "apps", app, "auth", cert_file]) key_file_path = make_splunkhome_path( ["etc", "apps", app, "auth", key_file]) if not (os.path.exists(cert_file_path) and os.path.exists(key_file_path)): logger.info( "Certificate not found - falling back to AUTH_BASIC.") cert_file_path = key_file_path = None else: logger.info( "Certificate information incomplete - falling back to AUTH_BASIC." ) cert_file_path = key_file_path = None client = tc.HttpClient() client.set_use_https(args.get('use_ssl')) # Add proxy parameters if present. if 'proxy' in args: client.set_proxy(args['proxy']) if cert_file_path and key_file_path and username: logger.info("Auth Type: AUTH_CERT_BASIC") client.set_auth_type(tc.HttpClient.AUTH_CERT_BASIC) client.set_auth_credentials({ 'username': username, 'password': password, 'cert_file': cert_file_path, 'key_file': key_file_path }) elif cert_file_path and key_file_path: logger.info("Auth Type: AUTH_CERT") client.set_auth_type(tc.HttpClient.AUTH_CERT) client.set_auth_credentials({ 'cert_file': cert_file_path, 'key_file': key_file_path }) else: logger.info("Auth Type: AUTH_BASIC") client.set_auth_type(tc.HttpClient.AUTH_BASIC) client.set_auth_credentials({ 'username': username, 'password': password }) poll_request = tm11.PollRequest( tm11.generate_message_id(), collection_name=args.get('collection'), exclusive_begin_timestamp_label=args.get('earliest'), #inclusive_end_timestamp_label=args.get('latest'), poll_parameters=tm11.PollParameters()) poll_xml = poll_request.to_xml() http_resp = client.call_taxii_service2(args.get('url'), args.get('service'), tm11.VID_TAXII_XML_11, poll_xml, port=args.get('port')) taxii_message = libtaxii.get_message_from_http_response( http_resp, poll_request.message_id) if http_resp.getcode() == 200: if hasattr(taxii_message, 'content_blocks'): return taxii_message.to_xml() else: raise TaxiiHandlerException( 'Exception when polling TAXII feed (no content returned): %s' % self._clean_taxii_message(taxii_message)) else: raise TaxiiHandlerException( 'Exception when polling TAXII feed: %s' % self._clean_taxii_message(taxii_message))