# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # Copyright (c) 2014 Mozilla Corporation import os import random import requests import re from configlib import getConfig, OptionParser from datetime import datetime, timedelta from pymongo import MongoClient from mozdef_util.utilities.logger import logger def isFQDN(fqdn): try: # We could resolve FQDNs here, but that could tip our hand and it's # possible us investigating could trigger other alerts. # validate using the regex from https://github.com/yolothreat/utilitybelt fqdn_re = re.compile(r'(?=^.{4,255}$)(^((?!-)[a-zA-Z0-9-]{1,63}(? 1: try: headers = {'Authorization': 'Oauth {0}'.format(self.options.statuspage_api_key)} # send the data as a form post per: # https://doers.statuspage.io/api/v1/incidents/#create-realtime post_data = { 'incident[name]': 'block FQDN {}'.format(fqdn), 'incident[status]': 'resolved', 'incident[impact_override]': 'none', 'incident[body]': '{} initiated a block of FDQN {} until {}'.format( userID, fqdn, end_date.isoformat()), 'incident[component_ids][]': self.options.statuspage_sub_component_id, 'incident[components][{0}]'.format(self.options.statuspage_component_id): "operational" } response = requests.post(self.options.statuspage_url, headers=headers, data=post_data) if response.ok: logger.info('%s: notification sent to statuspage.io\n' % (fqdn)) else: logger.error('%s: statuspage.io notification failed %s\n' % (fqdn, response.json())) except Exception as e: logger.error('Error while notifying statuspage.io for %s: %s\n' % (fqdn, e)) else: logger.error('%s: is already present in the fqdnblocklist table\n' % (fqdn)) else: logger.error('%s: is not a valid fqdn\n' % (fqdn)) except Exception as e: logger.error('Error while blocking %s: %s\n' % (fqdn, e)) def onMessage(self, request, response): ''' request: http://bottlepy.org/docs/dev/api.html#the-request-object response: http://bottlepy.org/docs/dev/api.html#the-response-object ''' response.headers['X-PLUGIN'] = self.description # Refresh the whitelist each time we get a message self.options.fqdnwhitelist = self.parse_fqdn_whitelist(self.options.fqdn_whitelist_file) fqdn = None comment = None duration = None referenceID = None userid = None blockfqdn = False # loop through the fields of the form # and fill in our values try: for field in request.json: # were we checked? if self.name in field: blockfqdn = field[self.name] if 'fqdn' in field: fqdn = field['fqdn'] if 'duration' in field: duration = field['duration'] if 'comment' in field: comment = field['comment'] if 'referenceid' in field: referenceID = field['referenceid'] if 'userid' in field: userid = field['userid'] if blockfqdn and fqdn is not None: if isFQDN(fqdn): whitelisted = False for whitelist_fqdn in self.options.fqdnwhitelist: if fqdn == whitelist_fqdn: whitelisted = True logger.debug('{0} is whitelisted as part of {1}\n'.format(fqdn, whitelist_fqdn)) if not whitelisted: self.blockFQDN( fqdn, comment, duration, referenceID, userid ) logger.debug('added {0} to blocklist\n'.format(fqdn)) else: logger.debug('not adding {0} to blocklist, it was found in whitelist\n'.format(fqdn)) else: logger.error('not adding {0} to blocklist, invalid fqdn\n'.format(fqdn)) response.status = "400 invalid FQDN" response.body = "invalid FQDN" except Exception as e: logger.error('Error handling request.json %r \n' % (e)) response.status = "500" return (request, response)