class CbThreatConnectConnector(object): def __init__(self, access_id="", secret_key="", default_org="", base_url="", out_file="tc.json", sources="", ioc_types="", custom_ioc_key="", feed_url="", cb_server_token="", cb_server_url="https://127.0.0.1", cb_server_ssl_verify=False, ioc_min=None, niceness=None, debug=False, log_file=None, max_iocs=5000): logger.info("ThreatConnect Base URL: {0}".format(base_url)) self.tcapi = ThreatConnect(api_aid=access_id, api_sec=secret_key, api_url=base_url, api_org=default_org) self.sources = sources self.ioc_min = ioc_min self.ioc_types = ioc_types logger.info("Configured IOC Types are : {0}".format(self.ioc_types)) logger.info("Configured IOC Min is : {0}".format(self.ioc_min)) self.custom_ioc_key = custom_ioc_key self.max_iocs = max_iocs if self.sources[0] == "*": owners = self.tcapi.owners() try: # retrieve the Owners owners.retrieve() except RuntimeError as e: logger.error(traceback.format_exc()) sys.exit(1) # iterate through the Owners self.sources = [owner.name for owner in owners] logger.info("Sources = {0}".format(self.sources)) self.niceness = niceness if self.niceness is not None: os.nice(self.niceness) self.debug = debug if self.debug: logger.setLevel(logging.DEBUG) self.log_file = log_file self.out_file = out_file self.feed = None self.cb = CbResponseAPI(url=cb_server_url, token=cb_server_token, ssl_verify=cb_server_ssl_verify) self.feed_url = feed_url def stop(self): self.stopEvent.set() def getDebugMode(self): return self._debug def setDebugMode(self, debugOn): self._debug = debugOn if self._debug == True: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) debug = property(getDebugMode, setDebugMode) def _PollThreatConnect(self): self.generate_feed_from_threatconnect() self.createFeed() last = None while (True): if self.stopEvent.isSet(): logger.info( "Threatconnect Connector was signalled to stop...stopping") return else: #poll threat connect if the time delta has passed since the last time we did now = datetime.now() delta = now - last if last is not None else self.interval last = now if delta >= self.interval: self.generate_feed_from_threatconnect() else: time.sleep(self.interval.seconds + 1) logger.debug("Done sleeping...") def RunForever(self): logger.info("ThreatConnect agent starting...") threading.Thread(target=self._PollThreatConnect).start() def createFeed(self): if self.feed is not None: self.feed.upload(self.cb, self.feed_url) def generate_feed_from_threatconnect(self): first = True reports = [] feedinfo = { 'name': 'threatconnect', 'display_name': "ThreatConnect", 'provider_url': "http://www.threatconnect.com", 'summary': "Sends threat intelligence from Threatconnect platform to Carbon Black Response", 'tech_data': "There are no requirements to share any data with Carbon Black to use this feed.", 'icon': 'threatconnect-logo.png', 'category': "Connectors", } feedinfo = CbFeedInfo(**feedinfo) self.feed = CbFeed(feedinfo, reports) created_feed = self.feed.dump(validate=False, indent=0) with open(self.out_file, 'w') as fp: fp.write(created_feed) fp.seek(0) offset = len(created_feed) - 1 # create an Indicators object for source in self.sources: for t in self.ioc_types: indicators = self.tcapi.indicators() filter1 = indicators.add_filter() # filter1.add_owner(source) filter1.add_pf_type(t, FilterOperator.EQ) if self.ioc_min is not None: filter1.add_pf_rating(self.ioc_min, FilterOperator.GE) try: # retrieve Indicators indicators.retrieve() except RuntimeError as e: print('Error: {0}'.format(e)) logger.info("Number of indicators:{0}".format( len(indicators))) for index, indicator in enumerate(indicators): if index > self.max_iocs: logger.info("Max number of IOCs reached") break # print (indicator.type) score = indicator.rating * 20 if indicator.rating is not None else 0 # int(row.get('rating', 0)) * 20 # Many entries are missing a description so I placed this here to default them # to the IOC value in the absence of a description. title = indicator.description if indicator.description is not None else "{0}-{1}".format( source, indicator.id) # row.get('description', None) # if not title: # title = row.get('summary') fields = { 'iocs': {}, 'id': str(indicator.id), 'link': indicator.weblink, 'title': title, 'score': int(score), 'timestamp': int( datetime.strptime( indicator.date_added, "%Y-%m-%dT%H:%M:%SZ").timestamp()), } # The next few lines are designed to insert the Cb supported IOCs into the record. logger.debug("Indacator is {0}".format(indicator)) if indicator.type == "File": fields['iocs'] = { k: [indicator.indicator[k]] for k in indicator.indicator if indicator.indicator[k] is not None } elif indicator.type == "Address": fields['iocs']['ipv4'] = [indicator.indicator] elif indicator.type == "Host": fields['iocs']['dns'] = [indicator.indicator] else: squery = urllib.parse.urlencode({ "cb.urlver": "1", "q": indicator.indicator[self.custom_ioc_key] }) fields['iocs']['query'] = [{ 'index_type': 'modules', 'search_query': squery }] report = CbReport(**fields) try: report.dump(validate=True) except: logger.info("This query is not valid: {0}".format( indicator.indicator[self.custom_ioc_key])) continue # APPEND EACH NEW REPORT ONTO THE LIST IN THE JSON FEED # THIS METHOD IS VERY LONG LIVED # THIS METHOD CALL WILL LAST FOR # HOURS -> DAYS IN LARGE ORGS reports.append(report) self.feed = CbFeed(feedinfo, reports) fp.write(self.feed.dump(validate=False, indent=0))
from threatconnect import ThreatConnect config = ConfigParser.RawConfigParser() config.read('./tc.conf') try: api_access_id = config.get('threatconnect', 'api_access_id') api_secret_key = config.get('threatconnect', 'api_secret_key') api_default_org = config.get('threatconnect', 'api_default_org') api_base_url = config.get('threatconnect', 'api_base_url') except ConfigParser.NoOptionError: print('Could not read configuration file.') sys.exit(1) tc = ThreatConnect(api_access_id, api_secret_key, api_default_org, api_base_url) owners = tc.owners() try: # retrieve the Owners owners.retrieve() except RuntimeError as e: print('Error: {0}'.format(e)) sys.exit(1) def getOwnerNames(): namelist = [] for owner in owners: namelist.append(owner.name) return namelist
import ConfigParser from threatconnect import ThreatConnect config = ConfigParser.RawConfigParser() config.read(config_file) try: api_access_id = config.get('threatconnect', 'api_access_id') api_secret_key = config.get('threatconnect', 'api_secret_key') api_default_org = config.get('threatconnect', 'api_default_org') api_base_url = config.get('threatconnect', 'api_base_url') except ConfigParser.NoOptionError: print('Could not read configuration file.') sys.exit(1) tc = ThreatConnect(api_access_id, api_secret_key, api_default_org, api_base_url) owners = tc.owners() try: owners.retrieve() except RunTimeErrors as e: print('Error: {0}'.format(e)) sys.exit(1) for owner in owners: print(owner.id) print(owner.name) print(owner.type)