2016-11-23 13:16:30 +01:00
|
|
|
import os
|
|
|
|
import zmq
|
|
|
|
import sys
|
|
|
|
import json
|
|
|
|
import pymisp
|
|
|
|
from pyaml import yaml
|
2020-05-07 02:28:04 +02:00
|
|
|
from yaml import Loader
|
2016-12-28 11:51:43 +01:00
|
|
|
from cabby import create_client
|
2017-08-18 11:52:42 +02:00
|
|
|
from misp_stix_converter.converters import lint_roller
|
2016-12-28 11:51:43 +01:00
|
|
|
import logging
|
2016-11-23 13:16:30 +01:00
|
|
|
|
2016-12-28 11:51:43 +01:00
|
|
|
# Set up logger
|
|
|
|
log = logging.getLogger(__name__)
|
2019-02-18 12:28:44 +01:00
|
|
|
formatter = logging.Formatter(
|
|
|
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
2017-12-28 13:21:26 +01:00
|
|
|
ch = logging.FileHandler("push.log")
|
|
|
|
ch.setFormatter(formatter)
|
|
|
|
log.addHandler(ch)
|
|
|
|
log.setLevel(logging.DEBUG)
|
2016-12-28 11:51:43 +01:00
|
|
|
|
2017-12-28 13:21:26 +01:00
|
|
|
log.info("Starting...")
|
2016-12-28 11:51:43 +01:00
|
|
|
# Try to load in config
|
|
|
|
if "OPENTAXII_CONFIG" in os.environ:
|
2020-05-07 02:28:04 +02:00
|
|
|
config = yaml.load(open(os.environ["OPENTAXII_CONFIG"], "r"), Loader=Loader)
|
2016-11-23 13:16:30 +01:00
|
|
|
else:
|
2019-02-18 12:28:44 +01:00
|
|
|
print("OPENTAXII CONFIG NOT EXPORTED")
|
|
|
|
sys.exit()
|
2016-11-23 13:16:30 +01:00
|
|
|
|
2016-12-28 11:51:43 +01:00
|
|
|
# Set up our ZMQ socket to recieve MISP JSON on publish
|
2016-11-23 13:16:30 +01:00
|
|
|
context = zmq.Context()
|
|
|
|
socket = context.socket(zmq.SUB)
|
|
|
|
|
2016-12-28 11:51:43 +01:00
|
|
|
log.info("Subscribing to tcp://{}:{}".format(
|
2016-11-23 13:16:30 +01:00
|
|
|
config["zmq"]["host"],
|
|
|
|
config["zmq"]["port"]
|
|
|
|
))
|
|
|
|
|
2016-12-28 11:51:43 +01:00
|
|
|
# Connect to the socket
|
2016-11-23 13:16:30 +01:00
|
|
|
socket.connect("tcp://{}:{}".format(
|
|
|
|
config["zmq"]["host"],
|
|
|
|
config["zmq"]["port"]
|
|
|
|
))
|
2016-12-28 11:51:43 +01:00
|
|
|
# Set the option to subscribe
|
2016-11-23 13:16:30 +01:00
|
|
|
socket.setsockopt_string(zmq.SUBSCRIBE, '')
|
|
|
|
|
2016-12-28 11:51:43 +01:00
|
|
|
# Connct to TAXII as well
|
2019-02-18 12:28:44 +01:00
|
|
|
cli = create_client(
|
|
|
|
discovery_path="{}://{}/services/discovery".format(
|
|
|
|
config.get("protocol", "http"),
|
|
|
|
config["domain"])
|
|
|
|
)
|
|
|
|
|
|
|
|
cli.set_auth(username=config["taxii"]["auth"]["username"],
|
|
|
|
password=config["taxii"]["auth"]["password"])
|
|
|
|
|
2017-08-18 11:56:19 +02:00
|
|
|
if not config.get("verify_ssl", True):
|
|
|
|
cli.verify_ssl = False
|
2016-12-28 11:51:43 +01:00
|
|
|
|
2016-11-23 13:16:30 +01:00
|
|
|
while True:
|
2016-12-28 11:51:43 +01:00
|
|
|
# Wait for something to come in on the ZMQ socket
|
2019-02-18 12:28:44 +01:00
|
|
|
log.info("Waiting...")
|
2017-06-01 16:12:54 +02:00
|
|
|
message = socket.recv().decode("utf-8")
|
2016-12-28 11:51:43 +01:00
|
|
|
log.info("Recieved a message!")
|
2017-06-01 16:12:54 +02:00
|
|
|
topic = message.split(' ', 1)[0]
|
|
|
|
|
|
|
|
if topic != 'misp_json':
|
2019-02-18 12:28:44 +01:00
|
|
|
log.info("Ignoring " + topic + "...")
|
|
|
|
continue
|
2017-06-01 16:12:54 +02:00
|
|
|
|
|
|
|
# Process the JSON payload
|
2016-12-28 11:51:43 +01:00
|
|
|
log.debug("Processing...")
|
2017-06-01 16:12:54 +02:00
|
|
|
payload = message[len(topic)+1:]
|
2016-12-28 11:51:43 +01:00
|
|
|
|
|
|
|
# Load the message JSON
|
2017-06-01 16:12:54 +02:00
|
|
|
msg = json.loads(payload)
|
2016-12-28 11:51:43 +01:00
|
|
|
|
|
|
|
log.debug(msg)
|
|
|
|
|
|
|
|
# Load it as a misp object for easy conversion to STIX
|
2016-11-23 13:16:30 +01:00
|
|
|
ev = pymisp.mispevent.MISPEvent()
|
|
|
|
ev.load(msg)
|
2016-12-28 11:51:43 +01:00
|
|
|
|
|
|
|
# Convert to STIX
|
|
|
|
pkg = pymisp.tools.stix.make_stix_package(ev)
|
|
|
|
log.debug("Loaded successfully!")
|
|
|
|
# Push the package to TAXII
|
2017-08-18 11:52:42 +02:00
|
|
|
for version in config.get("stix_versions", ["1.1.1"]):
|
2019-02-18 12:28:44 +01:00
|
|
|
# Convert to that version
|
2017-08-18 11:52:42 +02:00
|
|
|
objs = lint_roller.lintRoll(pkg)
|
|
|
|
for i in objs:
|
|
|
|
# Set the object's version
|
|
|
|
if hasattr(i, "version"):
|
|
|
|
i.version = version
|
2016-12-28 11:51:43 +01:00
|
|
|
|
2017-08-18 12:13:37 +02:00
|
|
|
# Set the top-level
|
|
|
|
pkg.version = version
|
|
|
|
|
2017-08-18 11:52:42 +02:00
|
|
|
try:
|
2019-02-18 12:28:44 +01:00
|
|
|
binding = "urn:stix.mitre.org:xml:{}".format(version)
|
|
|
|
uri = "{}://{}/services/inbox".format(
|
|
|
|
config.get("protocol", "http"),
|
|
|
|
config["domain"])
|
|
|
|
log.info("Using binding %s", binding)
|
|
|
|
|
|
|
|
cli.push(content=pkg.to_xml().decode("utf-8"),
|
|
|
|
content_binding=binding,
|
|
|
|
uri=uri,
|
|
|
|
collection_names=config["taxii"].get(
|
|
|
|
"collections", ["collection"]))
|
|
|
|
|
|
|
|
log.info("Pushed! (%s)", version)
|
|
|
|
|
2017-08-18 11:52:42 +02:00
|
|
|
except Exception as ex:
|
2017-12-28 13:21:26 +01:00
|
|
|
logging.fatal("COULD NOT PUSH")
|
|
|
|
logging.exception(ex)
|