Esempio n. 1
0
def _update_duplicate_chain(api: RESTConfig, label: AlertLabel, email: Email,
                            ids: types.List[str]) -> bool:
    url = "{}/alerttriagechain".format(api.url)

    payload = {
        "alert": label.value,
        "user": email,
        "identifiers": ids,
    }

    jwt_auth = None

    if api.token is not None:
        jwt_auth = JWTAuth(api.token)
        jwt_auth.set_header_format("Bearer %s")

    try:
        resp = requests.put(url, json=payload, auth=jwt_auth)
    except requests.exceptions.RequestException as ex:
        raise APIError("Failed to make request: {}".format(ex))

    error = resp.json().get("error")

    if error is not None:
        raise APIError(error)

    return True
Esempio n. 2
0
def update_alert_status(msg: UserResponseMessage, api: RESTConfig):
    """Invoke the MozDef REST API to update the status of an alert.
    """

    url = "{}/alertstatus".format(api.url)

    status = new_status(msg.response)

    payload = {
        "alert": msg.identifier,
        "status": status.value,
        "user": {
            "email": msg.user.email,
            "slack": msg.user.slack
        },
        "identityConfidence": msg.identityConfidence.value,
        "response": msg.response.value,
    }

    jwt_auth = None

    if api.token is not None:
        jwt_auth = JWTAuth(api.token)
        jwt_auth.set_header_format("Bearer %s")

    try:
        logger.debug("Sending request to REST API")
        resp = requests.post(url, json=payload, auth=jwt_auth)
    except Exception as ex:
        logger.exception("Request failed: {}".format(ex))
        return False

    return resp.status_code < 300
Esempio n. 3
0
class message(object):
    def __init__(self):
        '''
        takes an incoming alert
        and triggers the block ip rest api endpoint
        '''

        self.configfile = os.path.join(os.path.dirname(__file__),
                                       'block_ip.conf')
        self.options = None
        if os.path.exists(self.configfile):
            self.initConfiguration()
        if self.options.jwt_token is not None:
            self._restapi_jwt = JWTAuth(self.options.jwt_token)
            self._restapi_jwt.set_header_format('Bearer %s')
        else:
            self._restapi_jwt = None

        self.registration = self.options.keywords.split(" ")
        # Block for 1 day
        self.DEFAULT_BLOCK_LENGTH = "1d"
        self.priority = 1

    def initConfiguration(self):
        myparser = OptionParser()
        (self.options, args) = myparser.parse_args([])

        self.options.keywords = getConfig('alert_names', [], self.configfile)
        self.options.restapi_url = getConfig('restapi_url', '',
                                             self.configfile)
        self.options.jwt_token = getConfig('jwt_token', None, self.configfile)

    def onMessage(self, alert):
        message = alert['_source']
        post_data = [{
            'ipaddress':
            "{0}/32".format(message['details']['sourceipaddress'])
        }, {
            'duration': self.DEFAULT_BLOCK_LENGTH
        }, {
            'comment': 'Automatic Block'
        }, {
            'referenceid': ''
        }, {
            'IPBlockList': True
        }, {
            'userid': "MozDef"
        }]
        headers = {'Content-type': 'application/json'}
        resp = requests.post(url=self.options.restapi_url + "/blockip",
                             data=json.dumps(post_data),
                             auth=self._restapi_jwt,
                             headers=headers)
        if not resp.ok:
            raise Exception(
                "Received error {0} from rest api when updating alerts schedules {1}"
                .format(resp.status_code, resp.data))
        return message
Esempio n. 4
0
    def _request(self, method, endpoint, params, verify_certs):
        """Send an HTTP request to this instance"""
        auth = JWTAuth(self.secret, alg='HS512', header_format='Bearer %s')
        auth.add_field('iat', lambda req: calendar.timegm(time.gmtime()))

        endpoint_uri = '%s/api/v%d/%s' % (self.uri, self.version, endpoint)

        if method == 'GET':
            return requests.request(method,
                                    endpoint_uri,
                                    auth=auth,
                                    params=params,
                                    verify=verify_certs)
        return requests.request(method, endpoint_uri, auth=auth, json=params)
Esempio n. 5
0
    def __init__(self):
        if hasattr(current_app.conf, "CELERY_RESTAPI_JWT"
                   ) and current_app.conf.CELERY_RESTAPI_JWT != "":
            self._restapi_jwt = JWTAuth(current_app.conf.CELERY_RESTAPI_JWT)
            self._restapi_jwt.set_header_format('Bearer %s')
            get_logger(__name__).info("setting JWT value")
        else:
            self._restapi_jwt = None

        if hasattr(current_app.conf, "CELERY_RESTAPI_URL"):
            self._restapi_url = current_app.conf.CELERY_RESTAPI_URL
            get_logger(__name__).info("alert scheduler using {0}".format(
                self._restapi_url))
        else:
            raise Exception("Need to define CELERY_RESTAPI_URL")
Esempio n. 6
0
def get_user_count():
    token = get_token()
    auth = JWTAuth(token)
    url = "https://lackadaisical-tip.glitch.me/active-users"

    start = time.time()
    response = requests.get(url, auth=auth)
    logger.info("op={:4s}, status={}, url={}".format('GET',
                                                     response.status_code,
                                                     url))
    duration = time.time() - start
    respTime.set(duration)

    # json={u'activeUsers': 8596}
    result = -1
    if response.json() and 'activeUsers' in response.json():
        green.set_to_current_time()
        result = response.json().get('activeUsers', -1)
        userCount.set(result)
    else:
        red.set_to_current_time()
        errCount.inc()
    # if
    prom.push_to_gateway('localhost:9091',
                         job='api_active_users',
                         registry=registry)
    return result
Esempio n. 7
0
    def test_query(self):
        "Make sure query strings are included in the 'path' claim"
        httpretty.register_uri(httpretty.GET, 'http://example.com/', body='[]')
        secret = 's33333krit'

        auth = JWTAuth(secret)
        auth.add_field('path', requests_jwt.payload_path)
        resp = requests.get('http://example.com/',
                            params={'Hope this': 'Is signed'},
                            auth=auth)

        req = httpretty.last_request()
        auth_hdr = req.headers['Authorization']
        token = auth_hdr[auth_hdr.find('"'):].strip('"')
        claim = jwt.decode(token, secret)

        self.assertEqual(claim['path'], '/?Hope+this=Is+signed')
Esempio n. 8
0
def _retrieve_duplicate_chain(api: RESTConfig, label: AlertLabel,
                              email: Email) -> types.Optional[DuplicateChain]:
    url = "{}/alerttriagechain".format(api.url)

    payload = {
        "alert": label.value,
        "user": email,
    }

    jwt_auth = None

    if api.token is not None:
        jwt_auth = JWTAuth(api.token)
        jwt_auth.set_header_format("Bearer %s")

    try:
        resp = requests.get(url, params=payload, auth=jwt_auth)
        resp_data = resp.json()
    except json.JSONDecodeError as ex:
        raise APIError("Did not receive JSON response: {}".format(ex))
    except requests.exceptions.RequestException as ex:
        raise APIError("Failed to make request: {}".format(ex))

    error = resp_data.get("error")

    if error is not None:
        if resp.status_code != 200:
            raise APIError(error)

        return None  # No duplicate chain found

    ids = resp_data.get("identifiers", [])

    if len(ids) == 0:
        return None

    try:
        created = toUTC(resp_data["created"])
        modified = toUTC(resp_data["modified"])
    except KeyError:
        raise APIError(
            "Duplicate chain data missing created or modified field")
    except ValueError:
        raise APIError("Duplicate chain data contains unexpected timestamps")

    return DuplicateChain(ids, created, modified)
Esempio n. 9
0
    def test_body(self):
        httpretty.register_uri(httpretty.POST, 'http://example.com/',
                body='[]')
        secret = 's33333krit'

        auth = JWTAuth(secret)
        auth.add_field('body', requests_jwt.payload_body)
        resp = requests.post('http://example.com/',
                data={'Hope this': 'Is encoded'},
                auth=auth)

        req = httpretty.last_request()
        auth_hdr = req.headers['Authorization']
        token = auth_hdr[auth_hdr.find('"'):].strip('"')
        claim = jwt.decode(token, secret)

        self.assertEqual(claim['body']['hash'],
                hashlib.sha256(req.body).hexdigest())
Esempio n. 10
0
    def main(self):
        self.parse_config('get_watchlist.conf', ['api_url', 'jwt_secret', 'use_auth'])

        jwt_token = None
        if self.config.use_auth.lower() != 'false':
            jwt_token = JWTAuth(self.config.jwt_secret)
            jwt_token.set_header_format('Bearer %s')

        r = requests.get(self.config.api_url, auth=jwt_token)
        # Connect to rest api and grab response
        if r.ok:
            response = r.text
            terms_list = json.loads(response)
            for term in terms_list:
                self.watchterm = term
                self.process_alert()
        else:
            logger.error('The watchlist request failed. Status {0}.\n'.format(r))
Esempio n. 11
0
    def main(self):
        self.parse_config('get_watchlist.conf', ['api_url', 'jwt_secret', 'use_auth'])

        jwt_token = None
        if self.config.use_auth.lower() != 'false':
            jwt_token = JWTAuth(self.config.jwt_secret)
            jwt_token.set_header_format('Bearer %s')

        r = requests.get(self.config.api_url, auth=jwt_token)
        # Connect to rest api and grab response
        if r.ok:
            response = r.text
            terms_list = json.loads(response)
            for term in terms_list:
                self.watchterm = term
                self.process_alert()
        else:
            logger.error('The watchlist request failed. Status {0}.\n'.format(r))
Esempio n. 12
0
    def test_query(self):
        "Make sure query strings are included in the 'path' claim"
        httpretty.register_uri(httpretty.GET, 'http://example.com/',
                body='[]')
        secret = 's33333krit'

        auth = JWTAuth(secret)
        auth.add_field('path', requests_jwt.payload_path)
        resp = requests.get('http://example.com/',
                params={'Hope this': 'Is signed'},
                auth=auth)

        req = httpretty.last_request()
        auth_hdr = req.headers['Authorization']
        token = auth_hdr[auth_hdr.find('"'):].strip('"')
        claim = jwt.decode(token, secret)

        self.assertEqual(claim['path'], '/?Hope+this=Is+signed')
Esempio n. 13
0
    def test_json_post_body(self):
        httpretty.register_uri(httpretty.POST,
                               'http://example.com/',
                               body='[]')
        secret = 's33333krit'

        auth = JWTAuth(secret)
        auth.add_field('body', requests_jwt.payload_body)
        resp = requests.post('http://example.com/',
                             json={'some': 'data'},
                             auth=auth)

        req = httpretty.last_request()
        auth_hdr = req.headers['Authorization']
        token = auth_hdr[auth_hdr.find('"'):].strip('"')
        claim = jwt.decode(token, secret)

        self.assertEqual(claim['body']['hash'],
                         hashlib.sha256(req.body).hexdigest())
Esempio n. 14
0
    def test_auth(self):
        httpretty.register_uri(httpretty.GET, 'http://example.com/',
                body='{"app": "BadgeKit API"}')

        secret = 's3cr3tz'

        auth = JWTAuth(secret)
        auth.add_field('path', requests_jwt.payload_path)
        auth.add_field('method', requests_jwt.payload_method)
        resp = requests.get('http://example.com/', auth=auth)
        self.assertTrue(resp)

        req = httpretty.last_request()
        self.assertTrue('Authorization' in req.headers, 'JWT Authorization present')

        auth_hdr = req.headers['Authorization']
        self.assertTrue('JWT token=' in auth_hdr)
        token = auth_hdr[auth_hdr.find('"'):].strip('"')
        # Throws an exception on failure to verify
        claim = jwt.decode(token, secret)
Esempio n. 15
0
    def __init__(self):
        '''
        takes an incoming alert
        and triggers the block ip rest api endpoint
        '''

        self.configfile = os.path.join(os.path.dirname(__file__), 'block_ip.conf')
        self.options = None
        if os.path.exists(self.configfile):
            self.initConfiguration()
        if self.options.restapi_jwt_token is not None:
            self._restapi_jwt = JWTAuth(self.options.restapi_jwt_token)
            self._restapi_jwt.set_header_format('Bearer %s')
        else:
            self._restapi_jwt = None

        self.registration = self.options.alert_names.split(" ")
        # Block for 1 day
        self.DEFAULT_BLOCK_LENGTH = "1d"
        self.priority = 1
Esempio n. 16
0
    def main(self):
        self.parse_config('get_watchlist.conf', ['api_url', 'jwt_secret'])

        jwt_token = JWTAuth(self.config.jwt_secret)
        jwt_token.set_header_format('Bearer %s')

        # Connect to rest api and grab response
        r = requests.get(self.config.api_url, auth=jwt_token)
        status = r.status_code
        index = 0
        if status == 200:
            status = r.status_code
            response = r.text
            terms_list = json.loads(response)
            while index < len(terms_list):
                term = terms_list[index]
                term = '"{}"'.format(term)
                self.watchterm = term
                index += 1
                self.process_alert(term)
        else:
            logger.error('The watchlist request failed. Status {0}.\n'.format(status))
Esempio n. 17
0
def check_me():
    ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr)
    mac = os.system("arp -a | grep " + ip +
                    " | cut -c22-38 > /home/pi/mac_check.txt")
    auth = JWTAuth('YOur JWT')
    f = open("/home/pi/mac_check.txt", "r")
    out = requests.get("https://YOur_API_For_Check/" + str(mac), auth=auth)
    if str(out).find('200') != -1:
        return "MAC Free"
    else:
        os.system("cat /home/pi/mac_check.txt >> /home/pi/mac_block.txt")
        os.system(
            "sh /home/pi/scripts/block_mac.sh"
        )  # Download (https://raw.githubusercontent.com/crypto-br/RaspberryPI_Scripts/master/block_mac.sh)
        return "MAC Block"
Esempio n. 18
0
 def run(self):
     global line_data, data_ready, JwToken
     data_ready = False
     while not data_ready:
         try:
             print(JwToken)
             headers = {'Authorization': 'token {}'.format(JwToken)}
             # headers={'Authorization': 'access_token '+ JwToken}
             auth = JWTAuth(str(JwToken))
             headers = {'Authorization': 'Bearer ' + JwToken, 'content-type': 'application/json'}
             line_data = requests.get("http://ec2-13-250-42-181.ap-southeast-1.compute.amazonaws.com:8081/api/v1/rencana-produksi", headers=headers)
             data_ready = True
             print(line_data.text)
             print(line_data.status_code)
             if(str(line_data.status_code)=='200' or str(line_data.status_code)=='201'):
                 self.signal.emit(line_data.text)
             else:
                 print('Failed to retrieve data')
         except:
             print("Error in connection while Load data!")
         time.sleep(1)
Esempio n. 19
0
    def test_custom_header_text(self):
        httpretty.register_uri(httpretty.GET, 'http://example.com/', body='[]')
        secret = 's33333krit'

        auth = JWTAuth(secret)
        auth.add_field('path', requests_jwt.payload_path)
        auth.set_header_format('Bearer: "%s"')

        resp = requests.get('http://example.com/',
                            params={'Hope this': 'Is signed'},
                            auth=auth)

        req = httpretty.last_request()
        auth_hdr = req.headers['Authorization']

        self.assertTrue(auth_hdr.startswith('Bearer: "'))
Esempio n. 20
0
    def test_auth(self):
        httpretty.register_uri(httpretty.GET,
                               'http://example.com/',
                               body='{"app": "BadgeKit API"}')

        secret = 's3cr3tz'

        auth = JWTAuth(secret)
        auth.add_field('path', requests_jwt.payload_path)
        auth.add_field('method', requests_jwt.payload_method)
        resp = requests.get('http://example.com/', auth=auth)
        self.assertTrue(resp)

        req = httpretty.last_request()
        self.assertTrue('Authorization' in req.headers,
                        'JWT Authorization present')

        auth_hdr = req.headers['Authorization']
        self.assertTrue('JWT token=' in auth_hdr)
        token = auth_hdr[auth_hdr.find('"'):].strip('"')
        # Throws an exception on failure to verify
        claim = jwt.decode(token, secret)
Esempio n. 21
0
class CeleryRestClient(object):
    def __init__(self):
        if hasattr(current_app.conf, "CELERY_RESTAPI_JWT"
                   ) and current_app.conf.CELERY_RESTAPI_JWT != "":
            self._restapi_jwt = JWTAuth(current_app.conf.CELERY_RESTAPI_JWT)
            self._restapi_jwt.set_header_format('Bearer %s')
            get_logger(__name__).info("setting JWT value")
        else:
            self._restapi_jwt = None

        if hasattr(current_app.conf, "CELERY_RESTAPI_URL"):
            self._restapi_url = current_app.conf.CELERY_RESTAPI_URL
            get_logger(__name__).info("alert scheduler using {0}".format(
                self._restapi_url))
        else:
            raise Exception("Need to define CELERY_RESTAPI_URL")

    def fetch_schedule_dict(self):
        resp = requests.get(self._restapi_url + "/alertschedules",
                            auth=self._restapi_jwt)
        if not resp.ok:
            raise Exception(
                "Received error {0} from rest api when fetching alert schedules"
                .format(resp.status_code))
        api_results = json.loads(resp.text)
        return api_results

    def print_schedule(self):
        schedule = self.fetch_schedule_dict()
        get_logger(__name__).info("**** Current Alert Schedule ****")
        for alert_name, details in schedule.items():
            get_logger(__name__).info("\t{0}: {1} (enabled={2})".format(
                alert_name, details['schedule_string'], details['enabled']))

    def load_and_register_alerts(self):
        existing_alert_schedules = self.fetch_schedule_dict()
        alert_schedules = {}
        for alert_name, params in ALERTS.items():
            # Register alerts in celery
            try:
                alert_tokens = alert_name.split(".")
                alert_module_name = alert_tokens[0]
                alert_classname = alert_tokens[-1]
                alert_module = import_module(alert_module_name)
                alert_class = getattr(alert_module, alert_classname)
                current_app.register_task(alert_class())
            except ImportError as e:
                logger.exception("Error importing {0}: {1}".format(
                    alert_name, e))
                pass
            except Exception as e:
                logger.exception("Generic error registering {0}: {1}".format(
                    alert_name, e))
                pass

            full_path_name = "{0}.{1}".format(alert_module_name,
                                              alert_classname)
            alert_schedule = {
                "_id": str(ObjectId()),
                "_cls": "PeriodicTask",
                "name": full_path_name,
                "task": full_path_name,
                "enabled": True,
                "args": [],
                "kwargs": {},
            }
            if 'args' in params:
                alert_schedule['args'] = params['args']
            if 'kwargs' in params:
                alert_schedule['kwargs'] = params['kwargs']

            if isinstance(params['schedule'], timedelta):
                alert_schedule['schedule_type'] = 'interval'
                alert_schedule['interval'] = {
                    "every": params['schedule'].total_seconds(),
                    "period": "seconds"
                }
                alert_schedule['schedule_string'] = "{0} {1}".format(
                    params['schedule'].total_seconds(), "seconds")
            elif isinstance(params['schedule'], crontab):
                alert_schedule['schedule_type'] = 'crontab'
                alert_schedule['crontab'] = {
                    "minute": params['schedule']._orig_minute,
                    "hour": params['schedule']._orig_hour,
                    "day_of_week": params['schedule']._orig_day_of_week,
                    "day_of_month": params['schedule']._orig_day_of_month,
                    "month_of_year": params['schedule']._orig_month_of_year,
                }
                alert_schedule[
                    'schedule_string'] = "{0} {1} {2} {3} {4}".format(
                        params['schedule']._orig_minute,
                        params['schedule']._orig_hour,
                        params['schedule']._orig_day_of_week,
                        params['schedule']._orig_day_of_month,
                        params['schedule']._orig_month_of_year,
                    )

            if alert_name not in existing_alert_schedules:
                logger.debug("Inserting schedule for {0} into mongodb".format(
                    full_path_name))
                updated_alert_schedule = alert_schedule
            else:
                # Update schedule if it differs from file to api
                del existing_alert_schedules[alert_name][
                    existing_alert_schedules[alert_name]['schedule_type']]
                existing_alert_schedules[alert_name][
                    'schedule_type'] = alert_schedule['schedule_type']
                existing_alert_schedules[alert_name][
                    alert_schedule['schedule_type']] = alert_schedule[
                        alert_schedule['schedule_type']]
                existing_alert_schedules[alert_name][
                    'schedule_string'] = alert_schedule['schedule_string']
                updated_alert_schedule = existing_alert_schedules[alert_name]

            alert_schedules[alert_name] = updated_alert_schedule
        resp = requests.post(url=RESTAPI_URL + "/updatealertschedules",
                             data=json.dumps(alert_schedules),
                             auth=self._restapi_jwt)
        if not resp.ok:
            raise Exception(
                "Received error {0} from rest api when updating alerts schedules"
                .format(resp.status_code))
Esempio n. 22
0
class CeleryRestClient():
    def __init__(self):
        if hasattr(current_app.conf, "CELERY_RESTAPI_JWT"
                   ) and current_app.conf.CELERY_RESTAPI_JWT != "":
            self._restapi_jwt = JWTAuth(current_app.conf.CELERY_RESTAPI_JWT)
            self._restapi_jwt.set_header_format('Bearer %s')
            get_logger(__name__).info("setting JWT value")
        else:
            self._restapi_jwt = None

        if hasattr(current_app.conf, "CELERY_RESTAPI_URL"):
            self._restapi_url = current_app.conf.CELERY_RESTAPI_URL
            get_logger(__name__).info("alert scheduler using {0}".format(
                self._restapi_url))
        else:
            raise Exception("Need to define CELERY_RESTAPI_URL")

    def fetch_schedule_dict(self):
        resp = requests.get(self._restapi_url + "/alertschedules",
                            auth=self._restapi_jwt)
        if not resp.ok:
            raise Exception(
                "Received error {0} from rest api when fetching alert schedules: {1}"
                .format(resp.status_code, resp.text))
        return json.loads(resp.text)

    def sync_schedules(self, current_schedule):
        resp = requests.post(url=RESTAPI_URL + "/syncalertschedules",
                             data=json.dumps(current_schedule),
                             auth=self._restapi_jwt)
        if not resp.ok:
            raise Exception(
                "Received error {0} from rest api when updating alerts schedules {1}"
                .format(resp.status_code, resp.data))

    def update_schedules(self, current_schedule):
        resp = requests.post(url=RESTAPI_URL + "/updatealertschedules",
                             data=json.dumps(current_schedule),
                             auth=self._restapi_jwt)
        if not resp.ok:
            raise Exception(
                "Received error {0} from rest api when updating alerts schedules {1}"
                .format(resp.status_code, resp.data))

    def load_and_register_alerts(self):
        existing_alert_schedules = self.fetch_schedule_dict()
        alert_schedules = {}
        for alert_name, params in ALERTS.items():
            # Register alerts in celery
            try:
                alert_tokens = alert_name.split(".")
                alert_module_name = alert_tokens[0]
                alert_classname = alert_tokens[-1]
                alert_module = import_module(alert_module_name)
                alert_class = getattr(alert_module, alert_classname)
                current_app.register_task(alert_class())
            except ImportError as e:
                logger.exception("Error importing {0}: {1}".format(
                    alert_name, e))
                pass
            except Exception as e:
                logger.exception("Generic error registering {0}: {1}".format(
                    alert_name, e))
                pass
            alert_schedule = {
                "name": alert_name,
                "task": alert_name,
                "enabled": True,
            }
            if 'args' in params:
                alert_schedule['args'] = params['args']
            if 'kwargs' in params:
                alert_schedule['kwargs'] = params['kwargs']

            if isinstance(params['schedule'], timedelta):
                alert_schedule['schedule_type'] = 'interval'
                alert_schedule['celery_schedule'] = {
                    "every": params['schedule'].total_seconds(),
                    "period": "seconds"
                }
            elif isinstance(params['schedule'], crontab):
                alert_schedule['schedule_type'] = 'crontab'
                alert_schedule['celery_schedule'] = {
                    "minute": params['schedule']._orig_minute,
                    "hour": params['schedule']._orig_hour,
                    "day_of_week": params['schedule']._orig_day_of_week,
                    "day_of_month": params['schedule']._orig_day_of_month,
                    "month_of_year": params['schedule']._orig_month_of_year,
                }

            if alert_name not in existing_alert_schedules:
                logger.debug("Inserting schedule for {0} into mongodb".format(
                    alert_name))
                updated_alert_schedule = alert_schedule
            else:
                existing_schedule = existing_alert_schedules[alert_name]
                logger.debug(
                    "Updating existing schedule ({0}) with new information into mongodb"
                    .format(alert_name))
                existing_schedule['schedule_type'] = alert_schedule[
                    'schedule_type']
                existing_schedule['celery_schedule'] = alert_schedule[
                    'celery_schedule']
                updated_alert_schedule = existing_schedule

            alert_schedules[alert_name] = PeriodicTask(
                **updated_alert_schedule).to_dict()
        self.update_schedules(alert_schedules)