def update_key(key): if not request.json: raise ApiError('nothing to change', 400) if not current_app.config['AUTH_REQUIRED']: key = ApiKey.find_by_id(key) elif Scope.admin in g.scopes or Scope.admin_keys in g.scopes: key = ApiKey.find_by_id(key) else: key = ApiKey.find_by_id(key, user=g.login) if not key: raise ApiError('not found', 404) update = request.json update['customer'] = assign_customer(wanted=update.get('customer'), permission=Scope.admin_keys) for want_scope in update.get('scopes', []): if not Permission.is_in_scope(want_scope, have_scopes=g.scopes): raise ApiError("Requested scope '{}' not in existing scopes: {}".format( want_scope, ','.join(g.scopes)), 403) admin_audit_trail.send(current_app._get_current_object(), event='apikey-updated', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=key.id, type='apikey', request=request) if key.update(**request.json): return jsonify(status='ok') else: raise ApiError('failed to update API key', 500)
def receive(): try: incomingAlert = Alert.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except RateLimit as e: return jsonify(status='error', message=str(e), id=incomingAlert.id), 429 except BlackoutPeriod as e: return jsonify(status='ok', message=str(e), id=incomingAlert.id), 202 except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send(current_app._get_current_object(), event='alert-received', message=alert.text, user=g.user, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update of received alert failed', 500)
def custom(webhook): try: incomingAlert = custom_webhooks.webhooks[webhook].incoming( query_string=request.args, payload=request.get_json() or request.get_data(as_text=True) or request.form) except KeyError as e: raise ApiError( "Webhook '%s' not found. Did you mean to use POST instead of GET?" % webhook, 404) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update via %s webhook failed' % webhook, 500)
def prometheus(): alerts = [] if request.json and 'alerts' in request.json: external_url = request.json.get('externalURL', None) for alert in request.json['alerts']: try: incomingAlert = parse_prometheus(alert, external_url) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer( wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) alerts.append(alert) else: raise ApiError('no alerts in Prometheus notification payload', 400) if len(alerts) == 1: return jsonify(status='ok', id=alerts[0].id, alert=alerts[0].serialize), 201 else: return jsonify(status='ok', ids=[alert.id for alert in alerts]), 201
def create_key(): try: key = ApiKey.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) if Scope.admin in g.scopes or Scope.admin_keys in g.scopes: key.user = key.user or g.login else: key.user = g.login key.customer = assign_customer(wanted=key.customer, permission=Scope.admin_keys) if not key.user: raise ApiError("An API key must be associated with a 'user'. Retry with user credentials.", 400) for want_scope in key.scopes: if not Permission.is_in_scope(want_scope, have_scopes=g.scopes): raise ApiError("Requested scope '{}' not in existing scopes: {}".format( want_scope, ','.join(g.scopes)), 403) try: key = key.create() except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send(current_app._get_current_object(), event='apikey-created', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=key.id, type='apikey', request=request) if key: return jsonify(status='ok', key=key.key, data=key.serialize), 201 else: raise ApiError('create API key failed', 500)
def newrelic(): try: incomingAlert = parse_newrelic(request.json) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) text = 'newrelic alert received via webhook' write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.user, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update of New Relic alert failed', 500)
def create_key(): try: key = ApiKey.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) if 'admin' in g.scopes or 'admin:keys' in g.scopes: key.user = key.user or g.user else: key.user = g.user key.customer = assign_customer(wanted=key.customer, permission='admin:keys') if not key.user: raise ApiError( "An API key must be associated with a 'user'. Retry with user credentials.", 400) for want_scope in key.scopes: if not Permission.is_in_scope(want_scope, g.scopes): raise ApiError( "Requested scope '{}' not in existing scopes: {}".format( want_scope, ','.join(g.scopes)), 403) try: key = key.create() except Exception as e: raise ApiError(str(e), 500) if key: return jsonify(status='ok', key=key.key, data=key.serialize), 201 else: raise ApiError('create API key failed', 500)
def custom(webhook): if webhook not in custom_webhooks.webhooks: raise ApiError("Custom webhook '%s' not found." % webhook, 404) try: rv = custom_webhooks.webhooks[webhook].incoming( query_string=request.args, payload=request.get_json() or request.get_data(as_text=True) or request.form) except Exception as e: raise ApiError(str(e), 400) if isinstance(rv, Alert): rv = [rv] if isinstance(rv, list): alerts = [] for alert in rv: alert.customer = assign_customer(wanted=alert.customer) add_remote_ip(request, alert) try: alert = process_alert(alert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) text = 'alert received via {} webhook'.format(webhook) write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) alerts.append(alert) if len(alerts) == 1: return jsonify(status='ok', id=alerts[0].id, alert=alerts[0].serialize), 201 else: return jsonify(status='ok', ids=[alert.id for alert in alerts]), 201 else: text = 'request received via {} webhook'.format(webhook) write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=None, type='user-defined', request=request) return rv
def create_blackout(): try: blackout = Blackout.parse(request.json) except Exception as e: raise ApiError(str(e), 400) if 'admin' in g.scopes or 'admin:blackouts' in g.scopes: blackout.user = blackout.user or g.user else: blackout.user = g.user blackout.customer = assign_customer(wanted=blackout.customer, permission='admin:blackouts') try: blackout = blackout.create() except Exception as e: raise ApiError(str(e), 500) if blackout: return jsonify(status="ok", id=blackout.id, blackout=blackout.serialize), 201, { 'Location': absolute_url('/blackout/' + blackout.id) } else: raise ApiError("insert blackout failed", 500)
def create_blackout(): try: blackout = Blackout.parse(request.json) except Exception as e: raise ApiError(str(e), 400) if Scope.admin in g.scopes or Scope.admin_blackouts in g.scopes: blackout.user = blackout.user or g.login else: blackout.user = g.login blackout.customer = assign_customer(wanted=blackout.customer, permission=Scope.admin_blackouts) try: blackout = blackout.create() except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send(current_app._get_current_object(), event='blackout-created', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=blackout.id, type='blackout', request=request) if blackout: return jsonify(status='ok', id=blackout.id, blackout=blackout.serialize), 201, {'Location': absolute_url('/blackout/' + blackout.id)} else: raise ApiError('insert blackout failed', 500)
def update_blackout(blackout_id): if not request.json: raise ApiError('nothing to change', 400) if not current_app.config['AUTH_REQUIRED']: blackout = Blackout.find_by_id(blackout_id) elif Scope.admin in g.scopes or Scope.admin_blackouts in g.scopes: blackout = Blackout.find_by_id(blackout_id) else: blackout = Blackout.find_by_id(blackout_id, g.customers) if not blackout: raise ApiError('not found', 404) update = request.json update['user'] = g.login update['customer'] = assign_customer(wanted=update.get('customer'), permission=Scope.admin_blackouts) write_audit_trail.send(current_app._get_current_object(), event='blackout-updated', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=blackout.id, type='blackout', request=request) updated = blackout.update(**update) if updated: return jsonify(status='ok', blackout=updated.serialize) else: raise ApiError('failed to update blackout', 500)
def graylog(): try: incomingAlert = parse_graylog(request.json) except ValueError as e: raise ApiError(str(e), 400) if request.args.get('event', None): incomingAlert.event = request.args.get('event') if request.args.get('event_type', None): incomingAlert.event_type = request.args.get('event_type') if request.args.get('environment', None): incomingAlert.environment = request.args.get('environment') if request.args.get('service', None): incomingAlert.service = request.args.get('service').split(",") if request.args.get('severity', None): incomingAlert.severity = request.args.get('severity') incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status="ok", id=alert.id, alert=alert.serialize), 201 else: raise ApiError("insert or update of graylog check failed", 500)
def receive(): try: incomingAlert = Alert.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except RateLimit as e: return jsonify(status="error", message=str(e), id=incomingAlert.id), 429 except BlackoutPeriod as e: return jsonify(status="ok", message=str(e), id=incomingAlert.id), 202 except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status="ok", id=alert.id, alert=alert.serialize), 201 else: raise ApiError("insert or update of received alert failed", 500)
def create_heartbeat(): try: heartbeat = Heartbeat.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) heartbeat.customer = assign_customer(wanted=heartbeat.customer, permission=Scope.admin_heartbeats) try: heartbeat = heartbeat.create() except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send(current_app._get_current_object(), event='heartbeat-created', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=heartbeat.id, type='heartbeat', request=request) if heartbeat: return jsonify(status='ok', id=heartbeat.id, heartbeat=heartbeat.serialize), 201 else: raise ApiError('insert or update of received heartbeat failed', 500)
def custom(webhook): if webhook not in custom_webhooks.webhooks: raise ApiError("Custom webhook '%s' not found." % webhook, 404) try: rv = custom_webhooks.webhooks[webhook].incoming( query_string=request.args, payload=request.get_json() or request.get_data(as_text=True) or request.form ) except Exception as e: raise ApiError(str(e), 400) if isinstance(rv, Alert): rv = [rv] if isinstance(rv, list): alerts = [] for alert in rv: alert.customer = assign_customer(wanted=alert.customer) def audit_trail_alert(event: str): write_audit_trail.send(current_app._get_current_object(), event=event, message=alert.text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) try: alert = process_alert(alert) except RejectException as e: audit_trail_alert(event='alert-rejected') raise ApiError(str(e), 403) except RateLimit as e: audit_trail_alert(event='alert-rate-limited') return jsonify(status='error', message=str(e), id=alert.id), 429 except HeartbeatReceived as e: audit_trail_alert(event='alert-heartbeat') return jsonify(status='ok', message=str(e), id=alert.id), 202 except BlackoutPeriod as e: audit_trail_alert(event='alert-blackout') return jsonify(status='ok', message=str(e), id=alert.id), 202 except Exception as e: raise ApiError(str(e), 500) text = 'alert received via {} webhook'.format(webhook) write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) alerts.append(alert) if len(alerts) == 1: return jsonify(status='ok', id=alerts[0].id, alert=alerts[0].serialize), 201 else: return jsonify(status='ok', ids=[alert.id for alert in alerts]), 201 else: text = 'request received via {} webhook'.format(webhook) write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=None, type='user-defined', request=request) return rv
def receive(): try: alert = Alert.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) alert.customer = assign_customer(wanted=alert.customer) def audit_trail_alert(event: str): write_audit_trail.send(current_app._get_current_object(), event=event, message=alert.text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) try: alert = process_alert(alert) except RejectException as e: audit_trail_alert(event='alert-rejected') raise ApiError(str(e), 403) except RateLimit as e: audit_trail_alert(event='alert-rate-limited') return jsonify(status='error', message=str(e), id=alert.id), 429 except HeartbeatReceived as heartbeat: audit_trail_alert(event='alert-heartbeat') return jsonify(status='ok', message=str(heartbeat), id=heartbeat.id), 202 except BlackoutPeriod as e: audit_trail_alert(event='alert-blackout') return jsonify(status='ok', message=str(e), id=alert.id), 202 except ForwardingLoop as e: return jsonify(status='ok', message=str(e)), 202 except AlertaException as e: raise ApiError(e.message, code=e.code, errors=e.errors) except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send(current_app._get_current_object(), event='alert-received', message=alert.text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update of received alert failed', 500)
def grafana(): alerts = [] data = request.json if data and data['state'] == 'alerting': for match in data.get('evalMatches', []): try: incomingAlert = parse_grafana(data, match, request.args) except ValueError as e: return jsonify(status='error', message=str(e)), 400 incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: return jsonify(status='error', message=str(e)), 403 except Exception as e: return jsonify(status='error', message=str(e)), 500 alerts.append(alert) elif data and data['state'] == 'ok' and data.get('ruleId', None): try: query = qb.from_dict({'attributes.ruleId': str(data['ruleId'])}) existingAlerts = Alert.find_all(query) except Exception as e: raise ApiError(str(e), 500) for updateAlert in existingAlerts: updateAlert.severity = 'normal' updateAlert.status = 'closed' try: alert = process_alert(updateAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) alerts.append(alert) else: raise ApiError('no alerts in Grafana notification payload', 400) for alert in alerts: text = 'grafana alert received via webhook' write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.user, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) if len(alerts) == 1: return jsonify(status='ok', id=alerts[0].id, alert=alerts[0].serialize), 201 else: return jsonify(status='ok', ids=[alert.id for alert in alerts]), 201
def custom(webhook): try: response = custom_webhooks.webhooks[webhook].incoming( query_string=request.args, payload=request.get_json() or request.get_data(as_text=True) or request.form) except KeyError as e: raise ApiError( "Webhook '%s' not found. Did you mean to use POST instead of GET?" % webhook, 404) except ValueError as e: raise ApiError(str(e), 400) if isinstance(response, Alert): response.customer = assign_customer(wanted=response.customer) add_remote_ip(request, response) try: alert = process_alert(response) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) text = '{} alert received via custom webhook'.format(webhook) write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.user, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update via %s webhook failed' % webhook, 500) else: text = '{} request received via custom webhook'.format(webhook) write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.user, customers=g.customers, scopes=g.scopes, resource_id=None, type='user-defined', request=request) return jsonify(**response)
def grafana(): alerts = [] data = request.json if data and data['state'] == 'alerting': for match in data.get('evalMatches', []): try: incomingAlert = parse_grafana(data, match, request.args) except ValueError as e: return jsonify(status="error", message=str(e)), 400 incomingAlert.customer = assign_customer( wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: return jsonify(status="error", message=str(e)), 403 except Exception as e: return jsonify(status="error", message=str(e)), 500 alerts.append(alert) elif data and data['state'] == 'ok' and data.get('ruleId', None): try: query = qb.from_dict({'attributes.ruleId': str(data['ruleId'])}) existingAlerts = Alert.find_all(query) except Exception as e: raise ApiError(str(e), 500) for updateAlert in existingAlerts: updateAlert.severity = 'normal' updateAlert.status = 'closed' try: alert = process_alert(updateAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) alerts.append(alert) else: raise ApiError("no alerts in Grafana notification payload", 400) if len(alerts) == 1: return jsonify(status="ok", id=alerts[0].id, alert=alerts[0].serialize), 201 else: return jsonify(status="ok", ids=[alert.id for alert in alerts]), 201
def create_heartbeat(): try: heartbeat = Heartbeat.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) heartbeat.customer = assign_customer(wanted=heartbeat.customer, permission='admin:heartbeats') try: heartbeat = heartbeat.create() except Exception as e: raise ApiError(str(e), 500) if heartbeat: return jsonify(status="ok", id=heartbeat.id, heartbeat=heartbeat.serialize), 201 else: raise ApiError("insert or update of received heartbeat failed", 500)
def create_key(): try: key = ApiKey.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) if Scope.admin in g.scopes or Scope.admin_keys in g.scopes: key.user = key.user or g.login else: key.user = g.login key.customer = assign_customer(wanted=key.customer, permission=Scope.admin_keys) if not key.user: raise ApiError( "An API key must be associated with a 'user'. Retry with user credentials.", 400) for want_scope in key.scopes: if not Permission.is_in_scope(want_scope, have_scopes=g.scopes): raise ApiError( "Requested scope '{}' not in existing scopes: {}".format( want_scope, ','.join(g.scopes)), 403) try: key = key.create() except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send(current_app._get_current_object(), event='apikey-created', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=key.id, type='apikey', request=request) if key: return jsonify(status='ok', key=key.key, data=key.serialize), 201 else: raise ApiError('create API key failed', 500)
def create_twilio_rule(): try: twilio_rule = TwilioRule.parse(request.json) except Exception as e: raise ApiError(str(e), 400) if Scope.admin in g.scopes or Scope.admin_twilio_rules in g.scopes: twilio_rule.user = twilio_rule.user or g.login else: twilio_rule.user = g.login twilio_rule.customer = assign_customer(wanted=twilio_rule.customer, permission=Scope.admin_twilio_rules) try: twilio_rule = twilio_rule.create() except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send( current_app._get_current_object(), event='twiliorule-created', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=twilio_rule.id, type='twilio_rule', request=request, ) if twilio_rule: return ( jsonify(status='ok', id=twilio_rule.id, twilioRule=twilio_rule.serialize), 201, { 'Location': absolute_url('/twiliorule/' + twilio_rule.id) }, ) else: raise ApiError('insert twilio rule failed', 500)
def graylog(): try: incomingAlert = parse_graylog(request.json) except ValueError as e: raise ApiError(str(e), 400) if request.args.get('event', None): incomingAlert.event = request.args.get('event') if request.args.get('event_type', None): incomingAlert.event_type = request.args.get('event_type') if request.args.get('environment', None): incomingAlert.environment = request.args.get('environment') if request.args.get('service', None): incomingAlert.service = request.args.get('service').split(',') if request.args.get('severity', None): incomingAlert.severity = request.args.get('severity') incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) text = 'graylog alert received via webhook' write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.user, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update of graylog check failed', 500)
def prometheus(): alerts = [] if request.json and 'alerts' in request.json: external_url = request.json.get('externalURL', None) for alert in request.json['alerts']: try: incomingAlert = parse_prometheus(alert, external_url) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer( wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) alerts.append(alert) else: raise ApiError('no alerts in Prometheus notification payload', 400) for alert in alerts: text = 'prometheus alert received via webhook' write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.user, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) if len(alerts) == 1: return jsonify(status='ok', id=alerts[0].id, alert=alerts[0].serialize), 201 else: return jsonify(status='ok', ids=[alert.id for alert in alerts]), 201
def serverdensity(): try: incomingAlert = parse_serverdensity(request.json) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status="ok", id=alert.id, alert=alert.serialize), 201 else: raise ApiError("insert or update of ServerDensity alert failed", 500)
def create_heartbeat(): try: heartbeat = Heartbeat.parse(request.json) except ValueError as e: raise ApiError(str(e), 400) heartbeat.customer = assign_customer(wanted=heartbeat.customer, permission=Scope.admin_heartbeats) try: heartbeat = heartbeat.create() except Exception as e: raise ApiError(str(e), 500) write_audit_trail.send(current_app._get_current_object(), event='heartbeat-created', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=heartbeat.id, type='heartbeat', request=request) if heartbeat: return jsonify(status='ok', id=heartbeat.id, heartbeat=heartbeat.serialize), 201 else: raise ApiError('insert or update of received heartbeat failed', 500)
def pingdom(): try: incomingAlert = parse_pingdom(request.json) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update of pingdom check failed', 500)
def cloudwatch(): try: incomingAlert = parse_notification(request.get_json(force=True)) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status='ok', id=alert.id, alert=alert.serialize), 201 else: raise ApiError('insert or update of cloudwatch alarm failed', 500)
def update_key(key): if not request.json: raise ApiError('nothing to change', 400) if not current_app.config['AUTH_REQUIRED']: key = ApiKey.find_by_id(key) elif Scope.admin in g.scopes or Scope.admin_keys in g.scopes: key = ApiKey.find_by_id(key) else: key = ApiKey.find_by_id(key, user=g.login) if not key: raise ApiError('not found', 404) update = request.json update['customer'] = assign_customer(wanted=update.get('customer'), permission=Scope.admin_keys) for want_scope in update.get('scopes', []): if not Permission.is_in_scope(want_scope, have_scopes=g.scopes): raise ApiError( "Requested scope '{}' not in existing scopes: {}".format( want_scope, ','.join(g.scopes)), 403) admin_audit_trail.send(current_app._get_current_object(), event='apikey-updated', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=key.id, type='apikey', request=request) updated = key.update(**request.json) if updated: return jsonify(status='ok', key=updated.serialize) else: raise ApiError('failed to update API key', 500)
def custom(webhook): try: incomingAlert = custom_webhooks.webhooks[webhook].incoming( query_string=request.args, payload=request.get_json() or request.get_data(as_text=True)) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status="ok", id=alert.id, alert=alert.serialize), 201 else: raise ApiError("insert or update via %s webhook failed" % webhook, 500)
def stackdriver(): try: incomingAlert = parse_stackdriver(request.get_json(force=True)) except ValueError as e: raise ApiError(str(e), 400) incomingAlert.customer = assign_customer(wanted=incomingAlert.customer) add_remote_ip(request, incomingAlert) try: alert = process_alert(incomingAlert) except RejectException as e: raise ApiError(str(e), 403) except Exception as e: raise ApiError(str(e), 500) if alert: return jsonify(status="ok", id=alert.id, alert=alert.serialize), 201 else: raise ApiError("insert or update of StackDriver notification failed", 500)
def update_twilio_rule(twilio_rule_id): if not request.json: raise ApiError('nothing to change', 400) if not current_app.config['AUTH_REQUIRED']: twilio_rule = TwilioRule.find_by_id(twilio_rule_id) elif Scope.admin in g.scopes or Scope.admin_twilio_rules in g.scopes: twilio_rule = TwilioRule.find_by_id(twilio_rule_id) else: twilio_rule = TwilioRule.find_by_id(twilio_rule_id, g.customers) if not twilio_rule: raise ApiError('not found', 404) update = request.json update['user'] = g.login update['customer'] = assign_customer(wanted=update.get('customer'), permission=Scope.admin_twilio_rules) write_audit_trail.send( current_app._get_current_object(), event='twilio_rule-updated', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=twilio_rule.id, type='twilio_rule', request=request, ) updated = twilio_rule.update(**update) if updated: return jsonify(status='ok', twilioRule=updated.serialize) else: raise ApiError('failed to update twilio rule', 500)
def custom(webhook, path): if webhook not in custom_webhooks.webhooks: raise ApiError(f"Custom webhook '{webhook}' not found.", 404) try: rv = custom_webhooks.webhooks[webhook].incoming( path=path or request.path, query_string=request.args, payload=request.get_json() or request.form or request.get_data(as_text=True)) except TypeError: rv = custom_webhooks.webhooks[webhook].incoming( query_string=request.args, payload=request.get_json() or request.form or request.get_data(as_text=True)) except AlertaException as e: raise ApiError(e.message, code=e.code, errors=e.errors) except Exception as e: raise ApiError(str(e), 400) if isinstance(rv, Alert): rv = [rv] if isinstance(rv, list): alerts = [] for alert in rv: alert.customer = assign_customer(wanted=alert.customer) def audit_trail_alert(event: str): write_audit_trail.send(current_app._get_current_object(), event=event, message=alert.text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) try: alert = process_alert(alert) except RejectException as e: audit_trail_alert(event='alert-rejected') raise ApiError(str(e), 403) except RateLimit as e: audit_trail_alert(event='alert-rate-limited') return jsonify(status='error', message=str(e), id=alert.id), 429 except HeartbeatReceived as heartbeat: audit_trail_alert(event='alert-heartbeat') return jsonify(status='ok', message=str(heartbeat), id=heartbeat.id), 202 except BlackoutPeriod as e: audit_trail_alert(event='alert-blackout') return jsonify(status='ok', message=str(e), id=alert.id), 202 except ForwardingLoop as e: return jsonify(status='ok', message=str(e)), 202 except AlertaException as e: raise ApiError(e.message, code=e.code, errors=e.errors) except Exception as e: raise ApiError(str(e), 500) text = f'alert received via {webhook} webhook' write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=alert.id, type='alert', request=request) alerts.append(alert) if len(alerts) == 1: return jsonify(status='ok', id=alerts[0].id, alert=alerts[0].serialize), 201 else: return jsonify(status='ok', ids=[alert.id for alert in alerts]), 201 else: text = f'request received via {webhook} webhook' write_audit_trail.send(current_app._get_current_object(), event='webhook-received', message=text, user=g.login, customers=g.customers, scopes=g.scopes, resource_id=None, type='user-defined', request=request) return rv
def test_assign_customer(self): with self.app.test_request_context('/'): self.app.preprocess_request() # nothing wanted, assign one g.customers = ['Customer1'] g.scopes = [] self.assertEqual(assign_customer(wanted=None), 'Customer1') # nothing wanted, but too many, throw error g.customers = ['Customer1', 'Customer2'] g.scopes = [] with self.assertRaises(ApiError) as e: assign_customer(wanted=None) exc = e.exception self.assertEqual(str(exc), 'must define customer as more than one possibility') # customer wanted, matches so allow g.customers = ['Customer1'] g.scopes = [] self.assertEqual(assign_customer(wanted='Customer1'), 'Customer1') # customer wanted, in list so allow g.customers = ['Customer1', 'Customer2'] g.scopes = [] self.assertEqual(assign_customer(wanted='Customer2'), 'Customer2') # customer wanted not in list, throw exception g.customers = ['Customer1', 'Customer2'] g.scopes = [] with self.assertRaises(ApiError) as e: assign_customer(wanted='Customer3') exc = e.exception self.assertEqual(str(exc), "not allowed to set customer to 'Customer3'") # no customers, admin scope so allow g.customers = [] g.scopes = ['admin'] self.assertEqual(assign_customer(wanted=None), None) self.assertEqual(assign_customer(wanted='Customer1'), 'Customer1') g.customers = ['Customer1', 'Customer2'] g.scopes = ['admin'] with self.assertRaises(ApiError) as e: assign_customer(wanted=None) exc = e.exception self.assertEqual(str(exc), 'must define customer as more than one possibility') self.assertEqual(assign_customer(wanted='Customer3'), 'Customer3') # wrong scope g.customers = ['Customer1'] g.scopes = ['read:keys', 'write:keys'] with self.assertRaises(ApiError) as e: assign_customer(wanted='Customer2', permission=Scope.admin_keys) exc = e.exception self.assertEqual(str(exc), "not allowed to set customer to 'Customer2'") # right scope g.customers = ['Customer1'] g.scopes = ['admin:keys', 'read:keys', 'write:keys'] self.assertEqual(assign_customer(wanted='Customer2', permission=Scope.admin_keys), 'Customer2')
def test_assign_customer(self): with self.app.test_request_context('/'): self.app.preprocess_request() # nothing wanted, assign one g.customers = ['Customer1'] g.scopes = [] self.assertEqual(assign_customer(wanted=None), 'Customer1') # nothing wanted, but too many, throw error g.customers = ['Customer1', 'Customer2'] g.scopes = [] with self.assertRaises(ApiError) as e: assign_customer(wanted=None) exc = e.exception self.assertEqual( str(exc), 'must define customer as more than one possibility') # customer wanted, matches so allow g.customers = ['Customer1'] g.scopes = [] self.assertEqual(assign_customer(wanted='Customer1'), 'Customer1') # customer wanted, in list so allow g.customers = ['Customer1', 'Customer2'] g.scopes = [] self.assertEqual(assign_customer(wanted='Customer2'), 'Customer2') # customer wanted not in list, throw exception g.customers = ['Customer1', 'Customer2'] g.scopes = [] with self.assertRaises(ApiError) as e: assign_customer(wanted='Customer3') exc = e.exception self.assertEqual(str(exc), "not allowed to set customer to 'Customer3'") # no customers, admin scope so allow g.customers = [] g.scopes = ['admin'] self.assertEqual(assign_customer(wanted=None), None) self.assertEqual(assign_customer(wanted='Customer1'), 'Customer1') g.customers = ['Customer1', 'Customer2'] g.scopes = ['admin'] with self.assertRaises(ApiError) as e: assign_customer(wanted=None) exc = e.exception self.assertEqual( str(exc), 'must define customer as more than one possibility') self.assertEqual(assign_customer(wanted='Customer3'), 'Customer3') # wrong scope g.customers = ['Customer1'] g.scopes = ['read:keys', 'write:keys'] with self.assertRaises(ApiError) as e: assign_customer(wanted='Customer2', permission=Scope.admin_keys) exc = e.exception self.assertEqual(str(exc), "not allowed to set customer to 'Customer2'") # right scope g.customers = ['Customer1'] g.scopes = ['admin:keys', 'read:keys', 'write:keys'] self.assertEqual( assign_customer(wanted='Customer2', permission=Scope.admin_keys), 'Customer2')