def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'node_marginal', 'resource': 'node404', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key' ) self.customer_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo' ) self.admin_api_key.create() self.customer_api_key.create()
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'doe.com'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='demo-key' ) self.api_key.create() self.headers = { 'Authorization': f'Key {self.api_key.key}', 'Content-type': 'application/json' }
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 list_keys(): query = qb.from_params(request.args, customers=g.customers) total = ApiKey.count(query) paging = Page.from_params(request.args, total) if not current_app.config['AUTH_REQUIRED']: keys = ApiKey.find_all(query, page=paging.page, page_size=paging.page_size) elif Scope.admin in g.scopes or Scope.admin_keys in g.scopes: keys = ApiKey.find_all(query, page=paging.page, page_size=paging.page_size) elif not g.get('login', None): raise ApiError("Must define 'user' to list user keys", 400) else: keys = ApiKey.find_by_user(user=g.login) if keys: return jsonify(status='ok', page=paging.page, pageSize=paging.page_size, pages=paging.pages, more=paging.has_more, keys=[key.serialize for key in keys], total=total) else: return jsonify(status='ok', page=paging.page, pageSize=paging.page_size, pages=paging.pages, more=paging.has_more, message='not found', keys=[], total=0)
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': ['reject'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'resource': 'node404', 'event': 'node_marginal', 'environment': 'Production', 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key') self.customer_api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo') self.admin_api_key.create() self.customer_api_key.create()
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': ['timeout'], 'ALERT_TIMEOUT': 24680, 'ACK_TIMEOUT': 98765, 'SHELVE_TIMEOUT': 12345 } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'node_marginal', 'resource': 'node404', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key') self.customer_api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo') self.admin_api_key.create() self.customer_api_key.create()
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['bonaparte.fr', 'debeauharnais.fr'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key') self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' }
def key(username, want_key, scopes, duration, text, customer, all, force): """ Create an admin API key. """ if username and username not in current_app.config['ADMIN_USERS']: raise click.UsageError('User {} not an admin'.format(username)) if all and want_key: raise click.UsageError('Can only set API key with "--username".') scopes = [Scope(s) for s in scopes] or [Scope.admin, Scope.write, Scope.read] expires = datetime.utcnow() + timedelta(seconds=duration) if duration else None text = text or 'Created by alertad script' def create_key(admin, key=None): key = ApiKey( user=admin, key=key, scopes=scopes, expire_time=expires, text=text, customer=customer ) try: key = key.create() except Exception as e: click.echo('ERROR: {}'.format(e)) else: return key if all: for admin in current_app.config['ADMIN_USERS']: keys = [k for k in ApiKey.find_by_user(admin) if k.scopes == scopes] if keys and not force: key = keys[0] else: key = create_key(admin) click.echo('{:40} {}'.format(key.key, key.user)) elif username: keys = [k for k in ApiKey.find_by_user(username) if k.scopes == scopes] if want_key: found_key = [k for k in keys if k.key == want_key] if found_key: key = found_key[0] else: key = create_key(username, key=want_key) else: if keys and not force: key = keys[0] else: key = create_key(username) if key: click.echo(key.key) else: sys.exit(1) else: raise click.UsageError("Must set '--username' or use '--all'")
def make_key(user, scopes=None, type=None, text=''): api_key = ApiKey( user=user, scopes=scopes, type=type, text=text ) return api_key.create().key
def get_key(key): 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: user = g.get('login', None) key = ApiKey.find_by_id(key, user) if key: return jsonify(status='ok', total=1, key=key.serialize) else: raise ApiError('not found', 404)
def create_key(admin, key): key = ApiKey(user=admin, key=key, scopes=['admin', 'write', 'read'], text='Admin key created by alertad script', expire_time=None) try: db.get_db() # init db on global app context key = key.create() except Exception as e: click.echo('ERROR: {}'.format(e)) else: click.echo('{} {}'.format(key.key, key.user))
def create_key(admin, key=None): key = ApiKey(user=admin, key=key, scopes=scopes, expire_time=expires, text=text, customer=customer) try: key = key.create() except Exception as e: click.echo('ERROR: {}'.format(e)) else: return key
def create_key(admin): key = ApiKey( user=admin, scopes=['admin', 'write', 'read'], text='Admin key created by alertad script', expire_time=None ) try: db.get_db() # init db on global app context key = key.create() except Exception as e: click.echo('ERROR: {}'.format(e)) else: click.echo('{} {}'.format(key.key, key.user))
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['bonaparte.fr', 'debeauharnais.fr', 'manorfarm.ru'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='demo-key' ) self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' }
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 key.customer = key.customer or g.get('customer', None) else: key.user = g.user key.customer = g.get('customer', None) if not key.user: raise ApiError("Must set 'user' to create API key", 400) for want_scope in key.scopes: if not Permission.is_in_scope(want_scope, g.scopes): raise ApiError("Requested scope '%s' not in existing scopes: %s" % (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 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 key.customer = key.customer or g.get('customer', None) else: key.user = g.user key.customer = g.get('customer', None) 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 '%s' not in existing scopes: %s" % (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 list_keys(): if not current_app.config['AUTH_REQUIRED']: keys = ApiKey.find_all() elif 'admin' in g.scopes or 'admin:keys' in g.scopes: keys = ApiKey.find_all() elif not g.get('user', None): raise ApiError("Must define 'user' to list user keys", 400) else: keys = ApiKey.find_by_user(g.user) if keys: return jsonify(status="ok", keys=[key.serialize for key in keys], total=len(keys)) else: return jsonify(status="ok", message="not found", keys=[], total=0)
def list_keys(): if not current_app.config['AUTH_REQUIRED']: keys = ApiKey.find_all() elif Scope.admin in g.scopes or Scope.admin_keys in g.scopes: keys = ApiKey.find_all() elif not g.get('login', None): raise ApiError("Must define 'user' to list user keys", 400) else: keys = ApiKey.find_by_user(user=g.login) if keys: return jsonify(status='ok', keys=[key.serialize for key in keys], total=len(keys)) else: return jsonify(status='ok', message='not found', keys=[], total=0)
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 setUp(self): self.access_key = 'cc3b7f30-360e-47bc-8abb-c0a27625e134' self.secret_key = 'MjM0ODU4NGI1YWQxZWMyYzcxNjAxZDA4MzczNGQ1M2IK' test_config = { 'DEBUG': True, 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'DELETE_SCOPES': ['delete:alerts'], 'ALLOWED_EMAIL_DOMAINS': ['bonaparte.fr', 'debeauharnais.fr', 'manorfarm.ru'], 'HMAC_AUTH_CREDENTIALS': [{ 'key': self.access_key, 'secret': self.secret_key, 'algorithm': 'sha256' }] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='demo-key') self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' }
def delete_key(key): key = ApiKey.find_by_id(key) if not key: raise ApiError('not found', 404) if key.delete(): return jsonify(status='ok') else: raise ApiError('failed to delete API key', 500)
def delete_key(key): key = ApiKey.find_by_id(key) if not key: raise ApiError("not found", 404) if key.delete(): return jsonify(status="ok") else: raise ApiError("failed to delete API key", 500)
def keys(): """List admin API keys.""" for admin in current_app.config['ADMIN_USERS']: try: db.get_db() # init db on global app context keys = ApiKey.find_by_user(admin) except Exception as e: click.echo('ERROR: {}'.format(e)) else: for key in keys: click.echo('{:40} {}'.format(key.key, key.user))
def keys(): """ List admin API keys. """ for admin in current_app.config['ADMIN_USERS']: try: keys = [k for k in ApiKey.find_by_user(admin) if Scope.admin in k.scopes] except Exception as e: click.echo('ERROR: {}'.format(e)) else: for key in keys: click.echo('{:40} {}'.format(key.key, key.user))
def wrapped(*args, **kwargs): auth_header = request.headers.get('Authorization', '') m = re.match(r'Key (\S+)', auth_header) param = m.group(1) if m else request.args.get('api-key', None) if param: key = ApiKey.verify_key(param) if not key: raise ApiError("API key parameter '%s' is invalid" % param, 401) g.user = key.user g.customer = key.customer g.scopes = key.scopes if not Permission.is_in_scope(scope, g.scopes): raise ApiError('Missing required scope: %s' % scope, 403) else: return f(*args, **kwargs) auth_header = request.headers.get('Authorization', '') m = re.match(r'Bearer (\S+)', auth_header) token = m.group(1) if m else None if token: try: jwt = Jwt.parse(token) except DecodeError: raise ApiError('Token is invalid', 401) except ExpiredSignature: raise ApiError('Token has expired', 401) except InvalidAudience: raise ApiError('Invalid audience', 401) g.user = jwt.preferred_username g.customer = jwt.customer g.scopes = jwt.scopes if not Permission.is_in_scope(scope, g.scopes): raise ApiError("Missing required scope: %s" % scope, 403) else: return f(*args, **kwargs) if not current_app.config['AUTH_REQUIRED']: g.user = None g.customer = None g.scopes = [] return f(*args, **kwargs) # Google App Engine Cron Service if request.headers.get('X-Appengine-Cron', False) and request.headers.get('X-Forwarded-For', '') == '0.1.0.1': return f(*args, **kwargs) raise ApiError('Missing authorization API Key or Bearer Token', 401)
def delete_key(key): key = ApiKey.find_by_id(key) if not key: raise ApiError('not found', 404) admin_audit_trail.send(current_app._get_current_object(), event='apikey-deleted', message='', user=g.login, customers=g.customers, scopes=g.scopes, resource_id=key.id, type='apikey', request=request) if key.delete(): return jsonify(status='ok') else: raise ApiError('failed to delete API key', 500)
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'foo.com', 'bar.com'] } self.app = create_app(test_config) self.client = self.app.test_client() self.foo_alert = { 'event': 'foo1', 'resource': 'foo1', 'environment': 'Production', 'service': ['Web'] } self.bar_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='admin-key' ) self.api_key.create() self.admin_headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' }
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 list_keys(): if not current_app.config['AUTH_REQUIRED']: keys = ApiKey.find_all() elif 'admin' in g.scopes or 'admin:keys' in g.scopes: keys = ApiKey.find_all() elif not g.get('user', None): raise ApiError("Must define 'user' to list user keys", 400) else: keys = ApiKey.find_by_user(g.user) if keys: return jsonify( status="ok", keys=[key.serialize for key in keys], total=len(keys) ) else: return jsonify( status="ok", message="not found", keys=[], total=0 )
def list_keys(): if not current_app.config['AUTH_REQUIRED']: keys = ApiKey.find_all() elif Scope.admin in g.scopes or Scope.admin_keys in g.scopes: keys = ApiKey.find_all() elif not g.get('login', None): raise ApiError("Must define 'user' to list user keys", 400) else: keys = ApiKey.find_by_user(user=g.login) if keys: return jsonify( status='ok', keys=[key.serialize for key in keys], total=len(keys) ) else: return jsonify( status='ok', message='not found', keys=[], total=0 )
def setUp(self): test_config = { 'TESTING': True, 'DEBUG': True, 'AUTH_REQUIRED': True, 'AUTH_PROVIDER': 'ldap', 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'LDAP_URL': 'ldap://myldap.server', 'LDAP_BIND_USERNAME': '******', 'LDAP_BIND_PASSWORD': '******', 'LDAP_DOMAINS_SEARCH_QUERY': { 'debeauharnais.fr': 'sAMAccountName={username}' }, 'LDAP_DOMAINS_USER_BASEDN': { 'debeauharnais.fr': '' }, 'LDAP_DOMAINS': { 'debeauharnais.fr': 'DN=%s' } } self.app = create_app(test_config) self.client = self.app.test_client() with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='demo-key') self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' }
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 setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'foo.com', 'bar.com'] } self.app = create_app(test_config) self.client = self.app.test_client() self.foo_alert = { 'event': 'foo1', 'resource': 'foo1', 'environment': 'Production', 'service': ['Web'] } self.bar_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='admin-key' ) self.api_key.create() self.admin_headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' }
def update_key(key): if not request.json: raise ApiError('nothing to change', 400) key = ApiKey.find_by_id(key) if not key: raise ApiError('not found', 404) admin_audit_trail.send(current_app._get_current_object(), event='apikey-updated', message='', user=g.user, 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 setUp(self): # create dummy routing rules self.dist = pkg_resources.Distribution(__file__, project_name='alerta-routing', version='0.1') s = 'rules = tests.test_routing:rules' self.entry_point = pkg_resources.EntryPoint.parse(s, dist=self.dist) self.dist._ep_map = {'alerta.routing': {'rules': self.entry_point}} pkg_resources.working_set.add(self.dist) test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'foo.com', 'bar.com'], 'PD_API_KEYS': { 'Tyrell Corporation': 'tc-key', 'Cyberdyne Systems': 'cs-key', 'Weyland-Yutani': 'wy-key', 'Zorin Enterprises': 'ze-key' }, 'SLACK_API_KEYS': { 'Soylent Corporation': 'sc-key', 'Omni Consumer Products': 'ocp-key', # 'Dolmansaxlil Shoe Corporation': 'dsc-key' # use default key }, 'API_KEY': 'default-key' } self.app = create_app(test_config) self.client = self.app.test_client() self.tier1_tc_alert = { 'event': 'foo1', 'resource': 'foo1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Tyrell Corporation' # tier 1 } self.tier1_wy_alert = { 'event': 'foo1', 'resource': 'foo1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Weyland-Yutani' # tier 1 } self.tier2_sc_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Soylent Corporation' # tier 2 } self.tier2_ocp_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Omni Consumer Products' # tier 2 } self.tier2_dsc_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Dolmansaxlil Shoe Corporation' # tier 2 } self.tier3_it_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Initech' # tier 3 } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='admin-key' ) self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } # create dummy plugins plugins.plugins['pagerduty'] = DummyPagerDutyPlugin() plugins.plugins['slack'] = DummySlackPlugin() plugins.plugins['config'] = DummyConfigPlugin()
class BlackoutsTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': [] } self.app = create_app(test_config) self.client = self.app.test_client() self.prod_alert = { 'resource': 'node404', 'event': 'node_down', 'environment': 'Production', 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'], 'origin': 'foo/bar' } self.dev_alert = { 'resource': 'node404', 'event': 'node_marginal', 'environment': 'Development', 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'], 'origin': 'foo/bar' } self.fatal_alert = { 'event': 'node_down', 'resource': 'net01', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'tags': ['foo'], 'attributes': {'foo': 'abc def', 'bar': 1234, 'baz': False}, 'origin': 'foo/bar' } self.critical_alert = { 'event': 'node_marginal', 'resource': 'net02', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/bar', 'timeout': 30 } self.major_alert = { 'event': 'node_marginal', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/bar', 'timeout': 40 } self.normal_alert = { 'event': 'node_up', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'normal', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 100 } self.minor_alert = { 'event': 'node_marginal', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'minor', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 40 } self.ok_alert = { 'event': 'node_up', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'ok', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 100 } self.warn_alert = { 'event': 'node_marginal', 'resource': 'net05', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 50 } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key' ) self.customer_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo' ) self.admin_api_key.create() self.customer_api_key.create() def tearDown(self): plugins.plugins.clear() db.destroy() def test_suppress_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout response = self.client.post('/blackout', data=json.dumps({'environment': 'Production'}), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.customer_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_notification_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'True' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create new blackout blackout = { 'environment': 'Production', 'service': ['Core'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # new alert should be status=blackout response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # duplicate alert should be status=blackout response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # duplicate alert should be status=blackout (again) response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # increase severity alert should be status=blackout self.prod_alert['severity'] = 'major' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # increase severity alert should be status=blackout (again) self.prod_alert['severity'] = 'critical' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout self.prod_alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout (again) self.prod_alert['severity'] = 'warning' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # normal severity alert should be status=closed self.prod_alert['severity'] = 'ok' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # normal severity alert should be status=closed (again) response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # non-normal severity alert should be status=blackout (again) self.prod_alert['severity'] = 'major' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout self.prod_alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # non-normal severity alert should be status=open self.prod_alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'open') # normal severity alert should be status=closed self.prod_alert['severity'] = 'ok' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') def test_previous_status(self): self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create an alert => critical, open response = self.client.post('/alert', data=json.dumps(self.fatal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'open') alert_id_1 = data['id'] # ack the alert => critical, ack response = self.client.put('/alert/' + alert_id_1 + '/action', data=json.dumps({'action': 'ack'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id_1, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'ack') # create 2nd alert => critical, open response = self.client.post('/alert', data=json.dumps(self.critical_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'open') alert_id_2 = data['id'] # shelve 2nd alert => critical, shelved response = self.client.put('/alert/' + alert_id_2 + '/action', data=json.dumps({'action': 'shelve'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id_2, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'shelved') # create a blackout os.environ['NOTIFICATION_BLACKOUT'] = 'yes' plugins.plugins['blackout'] = Blackout() blackout = { 'environment': 'Production', 'service': ['Network'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # update 1st alert => critical, blackout response = self.client.post('/alert', data=json.dumps(self.fatal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'blackout') # create 3rd alert => major, blackout response = self.client.post('/alert', data=json.dumps(self.major_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'major') self.assertEqual(data['alert']['status'], 'blackout') # clear 3rd alert => normal, closed response = self.client.post('/alert', data=json.dumps(self.normal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'normal') self.assertEqual(data['alert']['status'], 'closed') # create 4th alert => minor, blackout response = self.client.post('/alert', data=json.dumps(self.minor_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'minor') self.assertEqual(data['alert']['status'], 'blackout') # clear 4th alert => ok, closed response = self.client.post('/alert', data=json.dumps(self.ok_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'ok') self.assertEqual(data['alert']['status'], 'closed') # create 5th alert => warning, blackout response = self.client.post('/alert', data=json.dumps(self.warn_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'warning') self.assertEqual(data['alert']['status'], 'blackout') # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # update 1st alert => critical, ack response = self.client.post('/alert', data=json.dumps(self.fatal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'ack') # update 2nd alert => critical, shelved response = self.client.post('/alert', data=json.dumps(self.critical_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'shelved') # update 3rd alert => normal, closed response = self.client.post('/alert', data=json.dumps(self.normal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'normal') self.assertEqual(data['alert']['status'], 'closed') # update 4th alert => minor, open response = self.client.post('/alert', data=json.dumps(self.minor_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'minor') self.assertEqual(data['alert']['status'], 'open') # update 5th alert => warning, open response = self.client.post('/alert', data=json.dumps(self.warn_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'warning') self.assertEqual(data['alert']['status'], 'open') def test_whole_environment_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (for whole development environment) blackout = { 'environment': 'Development' } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress production alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # suppress development alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # do not suppress any alerts response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) def test_combination_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for services on a particular host) blackout = { 'environment': 'Production', 'resource': 'node404', 'service': ['Network', 'Web'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for groups of alerts with particular tags) blackout = { 'environment': 'Production', 'group': 'Network', 'tags': ['system:web01', 'switch:off'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) self.prod_alert['tags'].append('system:web01') # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # create alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for resources with a particular tag) blackout = { 'environment': 'Development', 'resource': 'node404', 'tags': ['level=40'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) self.dev_alert['tags'].append('level=40') # suppress alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_origin_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for an origin) blackout = { 'environment': 'Production', 'origin': 'foo/bar', } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # do not suppress alert response = self.client.post('/alert', data=json.dumps(self.minor_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for origin with particular tags) blackout = { 'environment': 'Production', 'tags': ['system:web01', 'switch:off'], 'origin': 'foo/bar' } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) self.prod_alert['tags'].append('system:web01') # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # create alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for origin with certain event) blackout = { 'environment': 'Development', 'event': 'node_marginal', 'origin': 'foo/quux' } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) self.dev_alert['origin'] = 'foo/quux' # suppress alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # list blackouts response = self.client.get('/blackouts', headers=self.headers) self.assertEqual(response.status_code, 200) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_edit_blackout(self): # create new blackout os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for services on a particular host) blackout = { 'environment': 'Production', 'resource': 'node404', 'service': ['Network', 'Web'], 'startTime': '2019-01-01T00:00:00.000Z', 'endTime': '2049-12-31T23:59:59.999Z' } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # extend blackout period & change environment update = { 'environment': 'Development', 'event': None, 'tags': [], 'endTime': '2099-12-31T23:59:59.999Z' } response = self.client.put('/blackout/' + blackout_id, data=json.dumps(update), headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') # check updates worked and didn't change anything else response = self.client.get('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['blackout']['environment'], 'Development') self.assertEqual(data['blackout']['resource'], 'node404') self.assertEqual(data['blackout']['service'], ['Network', 'Web']) self.assertEqual(data['blackout']['group'], None) self.assertEqual(data['blackout']['startTime'], '2019-01-01T00:00:00.000Z') self.assertEqual(data['blackout']['endTime'], '2099-12-31T23:59:59.999Z') # suppress alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 202) def test_user_info(self): self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create new blackout response = self.client.post('/blackout', data=json.dumps({'environment': 'Production', 'service': [ 'Network'], 'text': 'administratively down'}), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['blackout']['user'], '*****@*****.**') self.assertIsInstance(DateTime.parse(data['blackout']['createTime']), datetime) self.assertEqual(data['blackout']['text'], 'administratively down')
class RoutingTestCase(unittest.TestCase): def setUp(self): # create dummy routing rules self.dist = pkg_resources.Distribution(__file__, project_name='alerta-routing', version='0.1') s = 'rules = tests.test_routing:rules' self.entry_point = pkg_resources.EntryPoint.parse(s, dist=self.dist) self.dist._ep_map = {'alerta.routing': {'rules': self.entry_point}} pkg_resources.working_set.add(self.dist) test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'foo.com', 'bar.com'], 'PD_API_KEYS': { 'Tyrell Corporation': 'tc-key', 'Cyberdyne Systems': 'cs-key', 'Weyland-Yutani': 'wy-key', 'Zorin Enterprises': 'ze-key' }, 'SLACK_API_KEYS': { 'Soylent Corporation': 'sc-key', 'Omni Consumer Products': 'ocp-key', # 'Dolmansaxlil Shoe Corporation': 'dsc-key' # use default key }, 'API_KEY': 'default-key' } self.app = create_app(test_config) self.client = self.app.test_client() self.tier1_tc_alert = { 'event': 'foo1', 'resource': 'foo1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Tyrell Corporation' # tier 1 } self.tier1_wy_alert = { 'event': 'foo1', 'resource': 'foo1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Weyland-Yutani' # tier 1 } self.tier2_sc_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Soylent Corporation' # tier 2 } self.tier2_ocp_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Omni Consumer Products' # tier 2 } self.tier2_dsc_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Dolmansaxlil Shoe Corporation' # tier 2 } self.tier3_it_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'], 'customer': 'Initech' # tier 3 } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='admin-key' ) self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } # create dummy plugins plugins.plugins['pagerduty'] = DummyPagerDutyPlugin() plugins.plugins['slack'] = DummySlackPlugin() plugins.plugins['config'] = DummyConfigPlugin() def tearDown(self): self.dist._ep_map.clear() def test_config(self): os.environ['BOOL_ENVVAR'] = 'yes' os.environ['INT_ENVVAR'] = '2020' os.environ['FLOAT_ENVVAR'] = '0.99' os.environ['LIST_ENVVAR'] = 'up,down,left,right' os.environ['STR_ENVVAR'] = 'a string with spaces' os.environ['DICT_ENVVAR'] = '{"key":"value", "key2": "value2" }' self.app.config.update({ 'BOOL_SETTING': True, 'INT_SETTING': 1001, 'FLOAT_SETTING': 7.07, 'LIST_SETTING': ['a', 2, 'z'], 'STR_SETTING': ' long string with spaces', 'DICT_SETTING': {'a': 'dict', 'with': 'three', 'keys': 3}, }) # create alert response = self.client.post('/alert', data=json.dumps(self.tier1_tc_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['attributes']['env']['bool'], True) self.assertEqual(data['alert']['attributes']['env']['int'], 2020) self.assertEqual(data['alert']['attributes']['env']['float'], 0.99) self.assertEqual(data['alert']['attributes']['env']['list'], ['up', 'down', 'left', 'right']) self.assertEqual(data['alert']['attributes']['env']['str'], 'a string with spaces') self.assertEqual(data['alert']['attributes']['env']['dict'], dict(key='value', key2='value2')) self.assertEqual(data['alert']['attributes']['setting']['bool'], True) self.assertEqual(data['alert']['attributes']['setting']['int'], 1001) self.assertEqual(data['alert']['attributes']['setting']['float'], 7.07) self.assertEqual(data['alert']['attributes']['setting']['list'], ['a', 2, 'z']) self.assertEqual(data['alert']['attributes']['setting']['str'], ' long string with spaces') self.assertEqual(data['alert']['attributes']['setting']['dict'], {'a': 'dict', 'with': 'three', 'keys': 3}) self.assertEqual(data['alert']['attributes']['default']['bool'], False) self.assertEqual(data['alert']['attributes']['default']['int'], 999) self.assertEqual(data['alert']['attributes']['default']['float'], 5.55) self.assertEqual(data['alert']['attributes']['default']['list'], ['j', 'k']) self.assertEqual(data['alert']['attributes']['default']['str'], 'setting') self.assertEqual(data['alert']['attributes']['default']['dict'], dict(baz='quux')) def test_config_precedence(self): os.environ['var1'] = 'env1' self.app.config.update({ 'var1': 'setting1', 'var2': 'setting2' }) # create alert response = self.client.post('/alert', data=json.dumps(self.tier1_tc_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['attributes']['precedence']['var1'], 'env1') self.assertEqual(data['alert']['attributes']['precedence']['var2'], 'setting2') self.assertEqual(data['alert']['attributes']['precedence']['var3'], 'default3') def test_routing(self): # create alert (pagerduty key for Tyrell Corporation) response = self.client.post('/alert', data=json.dumps(self.tier1_tc_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['attributes']['NOTIFY'], 'pagerduty') self.assertEqual(data['alert']['attributes']['API_KEY'], 'tc-key') # create alert (pagerduty key for Weyland-Yutani) response = self.client.post('/alert', data=json.dumps(self.tier1_wy_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['attributes']['NOTIFY'], 'pagerduty') self.assertEqual(data['alert']['attributes']['API_KEY'], 'wy-key') # create alert (slack key for customer Soylent Corporation) response = self.client.post('/alert', data=json.dumps(self.tier2_sc_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['attributes']['NOTIFY'], 'slack') self.assertEqual(data['alert']['attributes']['API_KEY'], 'sc-key') # create alert (slack key for customer Omni Consumer Products) response = self.client.post('/alert', data=json.dumps(self.tier2_ocp_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['attributes']['NOTIFY'], 'slack') self.assertEqual(data['alert']['attributes']['API_KEY'], 'ocp-key') # create alert (use default slack key for Dolmansaxlil Shoe Corporation) response = self.client.post('/alert', data=json.dumps(self.tier2_dsc_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['attributes']['NOTIFY'], 'slack') self.assertEqual(data['alert']['attributes']['API_KEY'], 'default-key') # create alert (no key) response = self.client.post('/alert', data=json.dumps(self.tier3_it_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertNotIn('NOTIFY', data['alert']['attributes']) self.assertNotIn('API_KEY', data['alert']['attributes'])
def wrapped(*args, **kwargs): # API Key (Authorization: Key <key>) if 'Authorization' in request.headers: auth_header = request.headers['Authorization'] m = re.match(r'Key (\S+)', auth_header) key = m.group(1) if m else None # API Key (X-API-Key: <key>) elif 'X-API-Key' in request.headers: key = request.headers['X-API-Key'] # API Key (/foo?api-key=<key>) else: key = request.args.get('api-key', None) if key: key_info = ApiKey.verify_key(key) if not key_info: raise ApiError("API key parameter '%s' is invalid" % key, 401) g.user_id = None g.login = key_info.user g.customers = [key_info.customer] if key_info.customer else [] g.scopes = key_info.scopes # type: List[Scope] if not Permission.is_in_scope(scope, have_scopes=g.scopes): raise ApiError('Missing required scope: %s' % scope.value, 403) else: return f(*args, **kwargs) # Bearer Token auth_header = request.headers.get('Authorization', '') m = re.match(r'Bearer (\S+)', auth_header) token = m.group(1) if m else None if token: try: jwt = Jwt.parse(token) except DecodeError: raise ApiError('Token is invalid', 401) except ExpiredSignature: raise ApiError('Token has expired', 401) except InvalidAudience: raise ApiError('Invalid audience', 401) g.user_id = jwt.subject g.login = jwt.preferred_username g.customers = jwt.customers g.scopes = jwt.scopes # type: List[Scope] if not Permission.is_in_scope(scope, have_scopes=g.scopes): raise ApiError('Missing required scope: %s' % scope.value, 403) else: return f(*args, **kwargs) # Basic Auth auth_header = request.headers.get('Authorization', '') m = re.match(r'Basic (\S+)', auth_header) credentials = m.group(1) if m else None if credentials: try: username, password = base64.b64decode(credentials).decode('utf-8').split(':') except Exception as e: raise BasicAuthError('Invalid credentials', 400, errors=[str(e)]) user = User.check_credentials(username, password) if not user: raise BasicAuthError('Authorization required', 401) if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified: raise BasicAuthError('email not verified', 401) if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]): raise BasicAuthError('Unauthorized domain', 403) g.user_id = user.id g.login = user.email g.customers = get_customers(user.email, groups=[user.domain]) g.scopes = Permission.lookup(user.email, roles=user.roles) # type: List[Scope] if not Permission.is_in_scope(scope, have_scopes=g.scopes): raise BasicAuthError('Missing required scope: %s' % scope.value, 403) else: return f(*args, **kwargs) if not current_app.config['AUTH_REQUIRED']: g.user_id = None g.login = None g.customers = [] g.scopes = [] # type: List[Scope] return f(*args, **kwargs) # Google App Engine Cron Service if request.headers.get('X-Appengine-Cron', False) and request.headers.get('X-Forwarded-For', '') == '0.1.0.1': return f(*args, **kwargs) raise ApiError('Missing authorization API Key or Bearer Token', 401)
class CustomersTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'foo.com', 'bar.com'] } self.app = create_app(test_config) self.client = self.app.test_client() self.foo_alert = { 'event': 'foo1', 'resource': 'foo1', 'environment': 'Production', 'service': ['Web'] } self.bar_alert = { 'event': 'bar1', 'resource': 'bar1', 'environment': 'Production', 'service': ['Web'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='admin-key' ) self.api_key.create() self.admin_headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } def tearDown(self): db.destroy() def test_customers(self): # add customer mappings payload = { 'customer': 'Bar Corp', 'match': 'bar.com' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 201) payload = { 'customer': 'Foo Bar Corp', 'match': '*****@*****.**' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 201) response = self.client.get('/customers', headers=self.admin_headers) self.assertEqual(response.status_code, 200) # create users payload = { 'name': 'Bar User', 'email': '*****@*****.**', 'password': '******', 'text': '' } response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data, 'Failed to create user') self.bar_bearer_headers = { 'Authorization': 'Bearer %s' % data['token'], 'Content-type': 'application/json' } payload = { 'name': 'Foo Bar User', 'email': '*****@*****.**', 'password': '******', 'text': '' } response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data, 'Failed to create user') self.foobar_bearer_headers = { 'Authorization': 'Bearer %s' % data['token'], 'Content-type': 'application/json' } # create API key for [email protected] payload = { 'user': '******', 'scopes': ['read', 'write'], 'text': '' } response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.bar_bearer_headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-write key') self.bar_api_key_headers = { 'Authorization': 'Key %s' % data['key'], 'Content-type': 'application/json' } # create API keys for [email protected] payload = { 'user': '******', 'scopes': ['read', 'write'], 'text': '', 'customer': 'Foo Bar Corp' } response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.foobar_bearer_headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-write key') self.foobar_api_key_headers = { 'Authorization': 'Key %s' % data['key'], 'Content-type': 'application/json' } payload = { 'user': '******', 'scopes': ['read', 'write'], 'text': '', 'customer': 'Bar Corp' } response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.foobar_bearer_headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-write key') self.foobar_bar_only_api_key_headers = { 'Authorization': 'Key %s' % data['key'], 'Content-type': 'application/json' } # get list of customers for users response = self.client.get('/customers', headers=self.bar_api_key_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual([c['customer'] for c in data['customers']], ['Bar Corp']) response = self.client.get('/customers', headers=self.foobar_api_key_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual([c['customer'] for c in data['customers']], ['Foo Bar Corp']) # create alerts using API keys response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.bar_api_key_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['customer'], 'Bar Corp') response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.foobar_api_key_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['customer'], 'Foo Bar Corp') response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.foobar_bar_only_api_key_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['customer'], 'Bar Corp') response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.foobar_bar_only_api_key_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['customer'], 'Bar Corp') # create alerts using Bearer tokens response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.bar_bearer_headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['customer'], 'Bar Corp') self.foo_alert['customer'] = 'Foo Bar Corp' response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.foobar_bearer_headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['customer'], 'Foo Bar Corp') def test_blackouts(self): # add customer mappings payload = { 'customer': 'Foo Corp', 'match': 'foo.com' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 201) payload = { 'customer': 'Bar Corp', 'match': 'bar.com' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 201) # create users payload = { 'name': 'Foo User', 'email': '*****@*****.**', 'password': '******', 'text': '' } response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data, 'Failed to create user') foo_user_headers = { 'Authorization': 'Bearer %s' % data['token'], 'Content-type': 'application/json' } payload = { 'name': 'Bar User', 'email': '*****@*****.**', 'password': '******', 'text': '' } response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data, 'Failed to create user') bar_user_headers = { 'Authorization': 'Bearer %s' % data['token'], 'Content-type': 'application/json' } # create customer blackout by foo user response = self.client.post( '/blackout', data=json.dumps({'environment': 'Production'}), headers=foo_user_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # new alert by foo user should be suppressed response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=foo_user_headers) self.assertEqual(response.status_code, 202) # new alert by bar user should not be suppressed response = self.client.post('/alert', data=json.dumps(self.bar_alert), headers=bar_user_headers) self.assertEqual(response.status_code, 201) # delete blackout by id response = self.client.delete('/blackout/' + blackout_id, headers=self.admin_headers) self.assertEqual(response.status_code, 200) # create global blackout by admin user response = self.client.post( '/blackout', data=json.dumps({'environment': 'Production'}), headers=self.admin_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # new alert by foo user should be suppressed response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=foo_user_headers) self.assertEqual(response.status_code, 202) # new alert by bar user should be suppressed response = self.client.post('/alert', data=json.dumps(self.bar_alert), headers=bar_user_headers) self.assertEqual(response.status_code, 202) # delete blackout by id response = self.client.delete('/blackout/' + blackout_id, headers=self.admin_headers) self.assertEqual(response.status_code, 200) 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_invalid_customer(self): self.foo_alert['customer'] = '' response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.admin_headers) self.assertEqual(response.status_code, 400) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['message'], 'customer must not be an empty string') def test_edit_customer(self): # add customer mappings payload = { 'customer': 'Foo Corp', 'match': 'foo.com' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.admin_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) customer_id = data['id'] # change customer name update = { 'customer': 'Bar Corp' } response = self.client.put('/customer/' + customer_id, data=json.dumps(update), headers=self.admin_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') # check updates worked and didn't change anything else response = self.client.get('/customer/' + customer_id, headers=self.admin_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['customer']['customer'], 'Bar Corp') self.assertEqual(data['customer']['match'], 'foo.com') # change customer lookup update = { 'match': 'bar.com' } response = self.client.put('/customer/' + customer_id, data=json.dumps(update), headers=self.admin_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') # check updates worked and didn't change anything else response = self.client.get('/customer/' + customer_id, headers=self.admin_headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['customer']['customer'], 'Bar Corp') self.assertEqual(data['customer']['match'], 'bar.com')
class BlackoutsTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'node_marginal', 'resource': 'node404', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key' ) self.customer_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo' ) self.admin_api_key.create() self.customer_api_key.create() def tearDown(self): db.destroy() def test_suppress_alerts(self): self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout response = self.client.post('/blackout', data=json.dumps({"environment": "Production"}), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.customer_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200)
class AuthTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['bonaparte.fr', 'debeauharnais.fr'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key') self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } def tearDown(self): db.destroy() def test_401_error(self): response = self.client.get('/alerts') self.assertEqual(response.status_code, 401) def test_readwrite_key(self): payload = {'user': '******', 'type': 'read-write'} response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-write key') rw_api_key = data['key'] response = self.client.post( '/alert', data=json.dumps(self.alert), content_type='application/json', headers={'Authorization': 'Key ' + rw_api_key}) self.assertEqual(response.status_code, 201) response = self.client.get( '/alerts', headers={'Authorization': 'Key ' + rw_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.delete('/key/' + rw_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) def test_readonly_key(self): payload = {'user': '******', 'type': 'read-only'} response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-only key') ro_api_key = data['key'] response = self.client.post( '/alert', data=json.dumps(self.alert), content_type='application/json', headers={'Authorization': 'Key ' + ro_api_key}) self.assertEqual(response.status_code, 403) response = self.client.get( '/alerts', headers={'Authorization': 'Key ' + ro_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.delete('/key/' + ro_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) def test_users(self): # add customer mapping payload = {'customer': 'Bonaparte Industries', 'match': 'bonaparte.fr'} response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) payload = { 'name': 'Napoleon Bonaparte', 'email': '*****@*****.**', 'password': '******', 'text': 'added to circle of trust' } # create user response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data, 'Failed to create user') with self.app.test_request_context(): jwt = Jwt.parse(data['token']) user_id = jwt.subject # get user response = self.client.get('/users', headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn(user_id, [u['id'] for u in data['users']]) # create duplicate user response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 409) # delete user response = self.client.delete('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_login(self): name = 'Josephine de Beauharnais' payload = { 'name': name, 'email': '*****@*****.**', 'password': '******', 'text': 'Test login' } # sign-up user with no customer mapping response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 403) # add customer mapping payload = { 'customer': 'Bonaparte Industries', 'match': 'debeauharnais.fr' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) customer_id = data['id'] payload = {'email': '*****@*****.**', 'password': '******'} # login now that customer mapping exists response = self.client.post('/auth/login', data=json.dumps(payload), content_type='application/json') # self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('token', data) token = data['token'] headers = { 'Authorization': 'Bearer ' + token, 'Content-type': 'application/json' } # create a customer demo key payload = {'user': '******', 'type': 'read-only'} response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-only key') customer_api_key = data['key'] response = self.client.get( '/alerts', headers={'Authorization': 'Key ' + customer_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.delete( '/key/' + customer_api_key, headers={'Authorization': 'Key ' + customer_api_key}) self.assertEqual(response.status_code, 403) response = self.client.delete('/key/' + customer_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) # get user response = self.client.get('/users', headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn(name, [u['name'] for u in data['users']]) user_id = [u['id'] for u in data['users'] if u['name'] == name][0] # delete user response = self.client.delete('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) # delete customer mapping response = self.client.delete('/customer/' + customer_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_x_api_key(self): self.headers = { 'X-API-Key': self.api_key.key, 'Content-type': 'application/json' } payload = {'user': '******', 'type': 'read-write'} response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-write key') rw_api_key = data['key'] response = self.client.post('/alert', data=json.dumps(self.alert), content_type='application/json', headers={'X-API-Key': rw_api_key}) self.assertEqual(response.status_code, 201) response = self.client.get('/alerts', headers={'X-API-Key': rw_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.delete('/key/' + rw_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) def test_basic_auth(self): # add customer mapping payload = {'customer': 'Bonaparte Industries', 'match': 'bonaparte.fr'} response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) payload = { 'name': 'Napoleon Bonaparte', 'email': '*****@*****.**', 'password': '******', 'text': 'added to circle of trust' } # create user response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 200) # authenticate using basic auth headers = { 'Authorization': 'Basic ' + base64.b64encode( '[email protected]:blackforest'.encode('utf-8')).decode(), 'Content-type': 'application/json' } response = self.client.get('/users', headers=headers) self.assertEqual(response.status_code, 403) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['message'], 'Missing required scope: admin:users') response = self.client.get('/alerts', headers=headers) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok', response.data)
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': ['reject'] } self.app = create_app(test_config) self.client = self.app.test_client() self.prod_alert = { 'resource': 'node404', 'event': 'node_down', 'environment': 'Production', 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'] } self.dev_alert = { 'resource': 'node404', 'event': 'node_marginal', 'environment': 'Development', 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'] } self.fatal_alert = { 'event': 'node_down', 'resource': 'net01', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'tags': ['foo'], 'attributes': {'foo': 'abc def', 'bar': 1234, 'baz': False}, } self.critical_alert = { 'event': 'node_marginal', 'resource': 'net02', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 30 } self.major_alert = { 'event': 'node_marginal', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 40 } self.normal_alert = { 'event': 'node_up', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'normal', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 100 } self.minor_alert = { 'event': 'node_marginal', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'minor', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 40 } self.ok_alert = { 'event': 'node_up', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'ok', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 100 } self.warn_alert = { 'event': 'node_marginal', 'resource': 'net05', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 50 } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key' ) self.customer_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo' ) self.admin_api_key.create() self.customer_api_key.create()
class BlackoutsTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': ['reject'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'resource': 'node404', 'event': 'node_marginal', 'environment': 'Production', 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key') self.customer_api_key = ApiKey(user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo') self.admin_api_key.create() self.customer_api_key.create() def tearDown(self): db.destroy() def test_suppress_blackout(self): plugins.plugins['blackout'] = SuppressionBlackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout response = self.client.post('/blackout', data=json.dumps( {'environment': 'Production'}), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.customer_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_notification_blackout(self): plugins.plugins['blackout'] = NotificationBlackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create new blackout blackout = {'environment': 'Production', 'service': ['Core']} response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # new alert should be status=blackout response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # duplicate alert should be status=blackout response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # duplicate alert should be status=blackout (again) response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # increase severity alert should be status=blackout self.alert['severity'] = 'major' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # increase severity alert should be status=blackout (again) self.alert['severity'] = 'critical' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout self.alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout (again) self.alert['severity'] = 'warning' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # normal severity alert should be status=closed self.alert['severity'] = 'ok' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # normal severity alert should be status=closed (again) response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # non-normal severity alert should be status=blackout (again) self.alert['severity'] = 'major' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout self.alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # non-normal severity alert should be status=open self.alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'open') # normal severity alert should be status=closed self.alert['severity'] = 'ok' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') def test_combination_blackout(self): plugins.plugins['blackout'] = SuppressionBlackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for services on a particular host) blackout = { 'environment': 'Production', 'resource': 'node404', 'service': ['Network', 'Web'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # create alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for groups of alerts with particular tags) blackout = { 'environment': 'Production', 'group': 'Network', 'tags': ['system:web01', 'switch:off'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) self.alert['tags'].append('system:web01') # suppress alert response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_user_info(self): self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create new blackout response = self.client.post('/blackout', data=json.dumps({ 'environment': 'Production', 'service': ['Network'], 'text': 'administratively down' }), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['blackout']['user'], '*****@*****.**') self.assertIsInstance(DateTime.parse(data['blackout']['createTime']), datetime) self.assertEqual(data['blackout']['text'], 'administratively down')
class BlackoutsTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': ['reject'] } self.app = create_app(test_config) self.client = self.app.test_client() self.prod_alert = { 'resource': 'node404', 'event': 'node_down', 'environment': 'Production', 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'] } self.dev_alert = { 'resource': 'node404', 'event': 'node_marginal', 'environment': 'Development', 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'] } self.fatal_alert = { 'event': 'node_down', 'resource': 'net01', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'tags': ['foo'], 'attributes': {'foo': 'abc def', 'bar': 1234, 'baz': False}, } self.critical_alert = { 'event': 'node_marginal', 'resource': 'net02', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 30 } self.major_alert = { 'event': 'node_marginal', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 40 } self.normal_alert = { 'event': 'node_up', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'normal', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 100 } self.minor_alert = { 'event': 'node_marginal', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'minor', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 40 } self.ok_alert = { 'event': 'node_up', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'ok', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 100 } self.warn_alert = { 'event': 'node_marginal', 'resource': 'net05', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'timeout': 50 } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key' ) self.customer_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo' ) self.admin_api_key.create() self.customer_api_key.create() def tearDown(self): db.destroy() def test_suppress_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout response = self.client.post('/blackout', data=json.dumps({'environment': 'Production'}), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.customer_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_notification_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'True' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create new blackout blackout = { 'environment': 'Production', 'service': ['Core'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # new alert should be status=blackout response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # duplicate alert should be status=blackout response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # duplicate alert should be status=blackout (again) response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # increase severity alert should be status=blackout self.prod_alert['severity'] = 'major' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # increase severity alert should be status=blackout (again) self.prod_alert['severity'] = 'critical' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout self.prod_alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout (again) self.prod_alert['severity'] = 'warning' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # normal severity alert should be status=closed self.prod_alert['severity'] = 'ok' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # normal severity alert should be status=closed (again) response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # non-normal severity alert should be status=blackout (again) self.prod_alert['severity'] = 'major' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # decrease severity alert should be status=blackout self.prod_alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'blackout') # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # non-normal severity alert should be status=open self.prod_alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'open') # normal severity alert should be status=closed self.prod_alert['severity'] = 'ok' response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') def test_previous_status(self): self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create an alert => critical, open response = self.client.post('/alert', data=json.dumps(self.fatal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'open') alert_id_1 = data['id'] # ack the alert => critical, ack response = self.client.put('/alert/' + alert_id_1 + '/action', data=json.dumps({'action': 'ack'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id_1, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'ack') # create 2nd alert => critical, open response = self.client.post('/alert', data=json.dumps(self.critical_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'open') alert_id_2 = data['id'] # shelve 2nd alert => critical, shelved response = self.client.put('/alert/' + alert_id_2 + '/action', data=json.dumps({'action': 'shelve'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id_2, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'shelved') # create a blackout os.environ['NOTIFICATION_BLACKOUT'] = 'yes' plugins.plugins['blackout'] = Blackout() blackout = { 'environment': 'Production', 'service': ['Network'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # update 1st alert => critical, blackout response = self.client.post('/alert', data=json.dumps(self.fatal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'blackout') # create 3rd alert => major, blackout response = self.client.post('/alert', data=json.dumps(self.major_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'major') self.assertEqual(data['alert']['status'], 'blackout') # clear 3rd alert => normal, closed response = self.client.post('/alert', data=json.dumps(self.normal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'normal') self.assertEqual(data['alert']['status'], 'closed') # create 4th alert => minor, blackout response = self.client.post('/alert', data=json.dumps(self.minor_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'minor') self.assertEqual(data['alert']['status'], 'blackout') # clear 4th alert => ok, closed response = self.client.post('/alert', data=json.dumps(self.ok_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'ok') self.assertEqual(data['alert']['status'], 'closed') # create 5th alert => warning, blackout response = self.client.post('/alert', data=json.dumps(self.warn_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'warning') self.assertEqual(data['alert']['status'], 'blackout') # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # update 1st alert => critical, ack response = self.client.post('/alert', data=json.dumps(self.fatal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'ack') # update 2nd alert => critical, shelved response = self.client.post('/alert', data=json.dumps(self.critical_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'critical') self.assertEqual(data['alert']['status'], 'shelved') # update 3rd alert => normal, closed response = self.client.post('/alert', data=json.dumps(self.normal_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'normal') self.assertEqual(data['alert']['status'], 'closed') # update 4th alert => minor, open response = self.client.post('/alert', data=json.dumps(self.minor_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'minor') self.assertEqual(data['alert']['status'], 'open') # update 5th alert => warning, open response = self.client.post('/alert', data=json.dumps(self.warn_alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['severity'], 'warning') self.assertEqual(data['alert']['status'], 'open') def test_whole_environment_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (for whole development environment) blackout = { 'environment': 'Development' } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress production alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # suppress development alert response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # do not suppress any alerts response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) response = self.client.post('/alert', data=json.dumps(self.dev_alert), headers=self.headers) self.assertEqual(response.status_code, 201) def test_combination_blackout(self): os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for services on a particular host) blackout = { 'environment': 'Production', 'resource': 'node404', 'service': ['Network', 'Web'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for groups of alerts with particular tags) blackout = { 'environment': 'Production', 'group': 'Network', 'tags': ['system:web01', 'switch:off'] } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # do not suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) self.prod_alert['tags'].append('system:web01') # suppress alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 202) # remove blackout response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_edit_blackout(self): # create new blackout os.environ['NOTIFICATION_BLACKOUT'] = 'False' plugins.plugins['blackout'] = Blackout() self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create alert response = self.client.post('/alert', data=json.dumps(self.prod_alert), headers=self.headers) self.assertEqual(response.status_code, 201) # create blackout (only for services on a particular host) blackout = { 'environment': 'Production', 'resource': 'node404', 'service': ['Network', 'Web'], 'startTime': '2019-01-01T00:00:00.000Z', 'endTime': '2019-12-31T23:59:59.999Z' } response = self.client.post('/blackout', data=json.dumps(blackout), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # extend blackout period & change environment update = { 'environment': 'Development', 'endTime': '2020-12-31T23:59:59.999Z' } response = self.client.put('/blackout/' + blackout_id, data=json.dumps(update), headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') # check updates worked and didn't change anything else response = self.client.get('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['blackout']['environment'], 'Development') self.assertEqual(data['blackout']['resource'], 'node404') self.assertEqual(data['blackout']['service'], ['Network', 'Web']) self.assertEqual(data['blackout']['group'], None) self.assertEqual(data['blackout']['startTime'], '2019-01-01T00:00:00.000Z') self.assertEqual(data['blackout']['endTime'], '2020-12-31T23:59:59.999Z') def test_user_info(self): self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # create new blackout response = self.client.post('/blackout', data=json.dumps({'environment': 'Production', 'service': [ 'Network'], 'text': 'administratively down'}), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['blackout']['user'], '*****@*****.**') self.assertIsInstance(DateTime.parse(data['blackout']['createTime']), datetime) self.assertEqual(data['blackout']['text'], 'administratively down')
class AuthTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['bonaparte.fr', 'debeauharnais.fr', 'manorfarm.ru'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='demo-key' ) self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } def tearDown(self): db.destroy() def test_401_error(self): response = self.client.get('/alerts') self.assertEqual(response.status_code, 401) def test_readwrite_key(self): payload = { 'user': '******', 'type': 'read-write' } response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-write key') rw_api_key = data['key'] response = self.client.post('/alert', data=json.dumps(self.alert), content_type='application/json', headers={'Authorization': 'Key ' + rw_api_key}) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['history'][0]['user'], 'rw-demo-key-user') response = self.client.get('/alerts', headers={'Authorization': 'Key ' + rw_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.get('/key/' + rw_api_key, headers={'Authorization': 'Key ' + rw_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['key']['scopes'], ['read', 'write']) response = self.client.delete('/key/' + rw_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) def test_readonly_key(self): payload = { 'user': '******', 'type': 'read-only' } response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-only key') ro_api_key = data['key'] response = self.client.post('/alert', data=json.dumps(self.alert), content_type='application/json', headers={'Authorization': 'Key ' + ro_api_key}) self.assertEqual(response.status_code, 403) response = self.client.get('/alerts', headers={'Authorization': 'Key ' + ro_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.delete('/key/' + ro_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) def test_users(self): # add customer mapping payload = { 'customer': 'Bonaparte Industries', 'match': 'bonaparte.fr' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) payload = { 'name': 'Napoleon Bonaparte', 'email': '*****@*****.**', 'password': '******', 'text': 'added to circle of trust' } # create user response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data, 'Failed to create user') with self.app.test_request_context(): jwt = Jwt.parse(data['token']) user_id = jwt.subject # get user response = self.client.get('/users', headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn(user_id, [u['id'] for u in data['users']]) # create duplicate user response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 409) # delete user response = self.client.delete('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_login(self): name = 'Josephine de Beauharnais' payload = { 'name': name, 'email': '*****@*****.**', 'password': '******', 'text': 'Test login' } # sign-up user with no customer mapping response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 403) # add customer mapping payload = { 'customer': 'Bonaparte Industries', 'match': 'debeauharnais.fr' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) customer_id = data['id'] payload = { 'email': '*****@*****.**', 'password': '******' } # login now that customer mapping exists response = self.client.post('/auth/login', data=json.dumps(payload), content_type='application/json') # self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('token', data) token = data['token'] headers = { 'Authorization': 'Bearer ' + token, 'Content-type': 'application/json' } # create a customer demo key payload = { 'user': '******', 'type': 'read-only' } response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-only key') customer_api_key = data['key'] response = self.client.get('/alerts', headers={'Authorization': 'Key ' + customer_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.get('/key/' + customer_api_key, headers=headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['key']['scopes'], ['read']) response = self.client.delete('/key/' + customer_api_key, headers={'Authorization': 'Key ' + customer_api_key}) self.assertEqual(response.status_code, 403) response = self.client.delete('/key/' + customer_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) # get user response = self.client.get('/users', headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn(name, [u['name'] for u in data['users']]) user_id = [u['id'] for u in data['users'] if u['name'] == name][0] # delete user response = self.client.delete('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) # delete customer mapping response = self.client.delete('/customer/' + customer_id, headers=self.headers) self.assertEqual(response.status_code, 200) def test_x_api_key(self): self.headers = { 'X-API-Key': self.api_key.key, 'Content-type': 'application/json' } payload = { 'user': '******', 'type': 'read-write' } response = self.client.post('/key', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data['key'], 'Failed to create read-write key') rw_api_key = data['key'] response = self.client.post('/alert', data=json.dumps(self.alert), content_type='application/json', headers={'X-API-Key': rw_api_key}) self.assertEqual(response.status_code, 201) response = self.client.get('/alerts', headers={'X-API-Key': rw_api_key}) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('total', data) response = self.client.delete('/key/' + rw_api_key, headers=self.headers) self.assertEqual(response.status_code, 200) def test_edit_api_keys(self): self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } # create api key payload = { 'scopes': [Scope.read, Scope.write_alerts, Scope.write_blackouts], 'text': 'devops automation key', 'expireTime': '2099-12-31T23:59:59.999Z' } response = self.client.post('/key', data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) api_key_id = data['key'] # extend blackout period & change environment update = { 'scopes': [Scope.read, Scope.write_blackouts, Scope.write_webhooks], 'expireTime': '2022-12-31T23:59:59.999Z' } response = self.client.put('/key/' + api_key_id, data=json.dumps(update), headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') # check updates worked and didn't change anything else response = self.client.get('/key/' + api_key_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['key']['scopes'], [Scope.read, Scope.write_blackouts, Scope.write_webhooks]) self.assertEqual(data['key']['user'], '*****@*****.**') self.assertEqual(data['key']['text'], 'devops automation key') self.assertEqual(data['key']['expireTime'], '2022-12-31T23:59:59.999Z') def test_basic_auth(self): # add customer mapping payload = { 'customer': 'Bonaparte Industries', 'match': 'bonaparte.fr' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) payload = { 'name': 'Napoleon Bonaparte', 'email': '*****@*****.**', 'password': '******', 'text': 'added to circle of trust' } # create user response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 200) # authenticate using basic auth headers = { 'Authorization': 'Basic ' + base64.b64encode('[email protected]:blackforest'.encode('utf-8')).decode(), 'Content-type': 'application/json' } response = self.client.get('/users', headers=headers) self.assertEqual(response.status_code, 403) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['message'], 'Missing required scope: admin:users') response = self.client.get('/alerts', headers=headers) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok', response.data) def test_edit_user(self): # add customer mapping payload = { 'customer': 'Manor Farm', 'match': 'manorfarm.ru' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) payload = { 'name': 'Snowball', 'email': '*****@*****.**', 'password': '******', 'text': 'Can you not understand that liberty is worth more than ribbons?', 'attributes': {'two-legs': 'bad', 'hasFourLegs': True, 'isEvil': False} } # create user response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) with self.app.test_request_context(): jwt = Jwt.parse(data['token']) user_id = jwt.subject # get user response = self.client.get('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') self.assertEqual(data['user']['name'], 'Snowball') self.assertEqual(data['user']['email'], '*****@*****.**') self.assertEqual(data['user']['text'], 'Can you not understand that liberty is worth more than ribbons?') # FIXME: attribute keys with None (null) values aren't deleted in postgres # change user details update = { 'name': 'Squealer', 'text': 'Four legs good, two legs bad.', 'attributes': {'four-legs': 'good', 'isEvil': True} } response = self.client.put('/user/' + user_id, data=json.dumps(update), headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') # check updates worked and didn't change anything else response = self.client.get('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'Squealer') self.assertEqual(data['user']['email'], '*****@*****.**') self.assertEqual(data['user']['text'], 'Four legs good, two legs bad.') self.assertEqual(data['user']['attributes'], { 'four-legs': 'good', 'two-legs': 'bad', 'hasFourLegs': True, 'isEvil': True }) # just update attributes update = { 'attributes': {'four-legs': 'double good', 'isEvil': False, 'hasFourLegs': None} } response = self.client.put('/user/' + user_id + '/attributes', data=json.dumps(update), headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['status'], 'ok') # check updates worked and didn't change anything else response = self.client.get('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'Squealer') self.assertEqual(data['user']['email'], '*****@*****.**') self.assertEqual(data['user']['text'], 'Four legs good, two legs bad.') self.assertEqual(data['user']['attributes'], { 'four-legs': 'double good', 'two-legs': 'bad', 'isEvil': False })
class UsersTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'doe.com'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='demo-key' ) self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } def tearDown(self): db.destroy() def test_user(self): payload = { 'name': 'John Doe', 'email': '*****@*****.**', 'password': '******', 'roles': ['operator'], 'text': 'devops user' } # create user response = self.client.post('/user', data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'John Doe') self.assertEqual(data['user']['email'], '*****@*****.**') self.assertEqual(data['user']['roles'], ['operator']) self.assertEqual(data['user']['email_verified'], False) user_id = data['id'] payload = { 'role': 'devops' } # modify user (assign different role) response = self.client.put('/user/' + user_id, data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) # get user response = self.client.get('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'John Doe') self.assertEqual(data['user']['email'], '*****@*****.**') self.assertEqual(data['user']['roles'], ['devops']) self.assertEqual(data['user']['email_verified'], False) payload = { 'roles': ['devops', 'operator', 'user'] } # modify user (assign multiple roles) response = self.client.put('/user/' + user_id, data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) # get user response = self.client.get('/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'John Doe') self.assertEqual(data['user']['email'], '*****@*****.**') self.assertEqual(data['user']['roles'], ['devops', 'operator', 'user']) self.assertEqual(data['user']['email_verified'], False) def test_user_attributes(self): payload = { 'name': 'John Doe', 'email': '*****@*****.**', 'password': '******', 'roles': ['operator'], 'text': 'devops user' } # create user response = self.client.post('/user', data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'John Doe') self.assertEqual(data['user']['login'], '*****@*****.**') self.assertEqual(data['user']['roles'], ['operator']) self.assertEqual(data['user']['email'], '*****@*****.**') self.assertEqual(data['user']['email_verified'], False) payload = { 'email': '*****@*****.**', 'password': '******' } # login using new user response = self.client.post('/auth/login', data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIn('token', data) token = data['token'] headers = { 'Authorization': 'Bearer ' + token, 'Content-type': 'application/json' } payload = { 'attributes': { 'prefs': { 'isDark': True } } } # set user attribute response = self.client.put('/user/me/attributes', data=json.dumps(payload), headers=headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) # get user attribute response = self.client.get('/user/me/attributes', data=json.dumps(payload), headers=headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['attributes']['prefs'], {'isDark': True}) payload = { 'attributes': { 'prefs': { 'isMute': False, 'refreshInterval': 5000 } } } # set user attribute response = self.client.put('/user/me/attributes', data=json.dumps(payload), headers=headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) # get user attribute response = self.client.get('/user/me/attributes', data=json.dumps(payload), headers=headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['attributes']['prefs'], {'isDark': True, 'isMute': False, 'refreshInterval': 5000}) payload = { 'attributes': { 'prefs': { 'isMute': None } } } # unset user attribute response = self.client.put('/user/me/attributes', data=json.dumps(payload), headers=headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) # get user attribute response = self.client.get('/user/me/attributes', data=json.dumps(payload), headers=headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['attributes']['prefs'], {'isDark': True, 'isMute': None, 'refreshInterval': 5000})
class ShelvingTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': ['reject'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'node_marginal', 'resource': 'node404', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key' ) self.customer_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo' ) self.admin_api_key.create() self.customer_api_key.create() def tearDown(self): db.destroy() def test_alarm_shelving(self): self.headers = { 'Authorization': 'Key %s' % self.admin_api_key.key, 'Content-type': 'application/json' } # new alert should be status=open response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'open') alert_id = data['id'] # shelve alert response = self.client.put('/alert/' + alert_id + '/status', data=json.dumps({'status': 'shelved'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # duplicate alert should be status=shelved response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # duplicate alert should be status=shelved (again) response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # increase severity alert should stay status=shelved self.alert['severity'] = 'major' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # shelve alert response = self.client.put('/alert/' + alert_id + '/status', data=json.dumps({'status': 'shelved'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # decrease severity alert should be status=shelved self.alert['severity'] = 'minor' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # decrease severity alert should be status=shelved (again) self.alert['severity'] = 'warning' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # normal severity alert should be status=closed self.alert['severity'] = 'ok' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # normal severity alert should be status=closed (again) response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') # normal severity alert should be status=closed response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'closed') ### # increase severity alert should be status=shelved self.alert['severity'] = 'critical' response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # shelve alert response = self.client.put('/alert/' + alert_id + '/status', data=json.dumps({'status': 'shelved'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # duplicate alert should be status=shelved response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'shelved') # unshelve alert response = self.client.put('/alert/' + alert_id + '/status', data=json.dumps({'status': 'open'}), headers=self.headers) self.assertEqual(response.status_code, 200) response = self.client.get('/alert/' + alert_id, headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'open') # duplicate alert should be status=open response = self.client.post('/alert', data=json.dumps(self.alert), headers=self.headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['alert']['status'], 'open')
def wrapped(*args, **kwargs): # API Key (Authorization: Key <key>) if 'Authorization' in request.headers: auth_header = request.headers['Authorization'] m = re.match(r'Key (\S+)', auth_header) key = m.group(1) if m else None # API Key (X-API-Key: <key>) elif 'X-API-Key' in request.headers: key = request.headers['X-API-Key'] # API Key (/foo?api-key=<key>) else: key = request.args.get('api-key', None) if key: key_info = ApiKey.verify_key(key) if not key_info: raise ApiError("API key parameter '%s' is invalid" % key, 401) g.user = key_info.user g.customers = [key_info.customer] if key_info.customer else [] g.scopes = key_info.scopes if not Permission.is_in_scope(scope, g.scopes): raise ApiError('Missing required scope: %s' % scope, 403) else: return f(*args, **kwargs) # Bearer Token auth_header = request.headers.get('Authorization', '') m = re.match(r'Bearer (\S+)', auth_header) token = m.group(1) if m else None if token: try: jwt = Jwt.parse(token) except DecodeError: raise ApiError('Token is invalid', 401) except ExpiredSignature: raise ApiError('Token has expired', 401) except InvalidAudience: raise ApiError('Invalid audience', 401) g.user = jwt.preferred_username g.customers = jwt.customers g.scopes = jwt.scopes if not Permission.is_in_scope(scope, g.scopes): raise ApiError('Missing required scope: %s' % scope, 403) else: return f(*args, **kwargs) # Basic Auth auth_header = request.headers.get('Authorization', '') m = re.match(r'Basic (\S+)', auth_header) credentials = m.group(1) if m else None if credentials: try: username, password = base64.b64decode(credentials).decode( 'utf-8').split(':') except Exception as e: raise BasicAuthError('Invalid credentials', 400, errors=[str(e)]) user = User.check_credentials(username, password) if not user: raise BasicAuthError('Authorization required', 401) if current_app.config[ 'EMAIL_VERIFICATION'] and not user.email_verified: raise BasicAuthError('email not verified', 401) if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]): raise BasicAuthError('Unauthorized domain', 403) g.user = user.email g.customers = get_customers(user.email, groups=[user.domain]) g.scopes = Permission.lookup(user.email, groups=user.roles) if not Permission.is_in_scope(scope, g.scopes): raise BasicAuthError('Missing required scope: %s' % scope, 403) else: return f(*args, **kwargs) if not current_app.config['AUTH_REQUIRED']: g.user = None g.customers = [] g.scopes = [] return f(*args, **kwargs) # Google App Engine Cron Service if request.headers.get('X-Appengine-Cron', False) and request.headers.get( 'X-Forwarded-For', '') == '0.1.0.1': return f(*args, **kwargs) raise ApiError('Missing authorization API Key or Bearer Token', 401)
class GroupsTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'doe.com'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=[Scope.admin, Scope.read, Scope.write], text='demo-key' ) self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } def tearDown(self): db.destroy() def test_groups(self): # create a group payload = { 'name': 'Group 1', 'text': 'Test group #1' } response = self.client.post('/group', data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['group']['name'], 'Group 1') self.assertEqual(data['group']['text'], 'Test group #1') group_id = data['group']['id'] # get group response = self.client.get('/group/' + group_id, headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['group']['name'], 'Group 1') self.assertEqual(data['group']['text'], 'Test group #1') # create a duplicate group name # payload = { # 'name': 'Group 1', # 'text': 'Test group #1 duplicate' # } # response = self.client.post('/group', data=json.dumps(payload), headers=self.headers) # self.assertEqual(response.status_code, 500, response.data) # update a group name, text payload = { 'name': 'Group 1 changed', 'text': 'Test group #1 changed too' } response = self.client.put('/group/' + group_id, data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 200, response.data) response = self.client.get('/group/' + group_id, headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['group']['name'], 'Group 1 changed') self.assertEqual(data['group']['text'], 'Test group #1 changed too') # create a different group payload = { 'name': 'Group 2', 'text': 'Test group #2' } response = self.client.post('/group', data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['group']['name'], 'Group 2') self.assertEqual(data['group']['text'], 'Test group #2') group2_id = data['group']['id'] # list groups response = self.client.get('/groups', headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertListEqual([g['name'] for g in data['groups']], ['Group 1 changed', 'Group 2']) # create a user payload = { 'name': 'John Doe', 'email': '*****@*****.**', 'password': '******', 'roles': ['operator'], 'text': 'devops user' } response = self.client.post('/user', data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'John Doe') user_id = data['user']['id'] # add a user to first group response = self.client.put('/group/' + group_id + '/user/' + user_id, headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) # get users for first group response = self.client.get('/group/' + group_id + '/users', headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertListEqual([u['name'] for u in data['users']], ['John Doe']) # create another user payload = { 'name': 'Jane Doe', 'email': '*****@*****.**', 'password': '******', 'roles': ['manager'], 'text': 'manager' } response = self.client.post('/user', data=json.dumps(payload), headers=self.headers) self.assertEqual(response.status_code, 201, response.data) data = json.loads(response.data.decode('utf-8')) self.assertEqual(data['user']['name'], 'Jane Doe') user2_id = data['user']['id'] # add another user to first group response = self.client.put('/group/' + group_id + '/user/' + user2_id, headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) # get users for first group again response = self.client.get('/group/' + group_id + '/users', headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertListEqual([u['name'] for u in data['users']], ['John Doe', 'Jane Doe']) # add second user to second group response = self.client.put('/group/' + group2_id + '/user/' + user2_id, headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) # get users for second group response = self.client.get('/group/' + group2_id + '/users', headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertListEqual([u['name'] for u in data['users']], ['Jane Doe']) # get groups for first user response = self.client.get('/user/' + user_id + '/groups', headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertListEqual([g['name'] for g in data['groups']], ['Group 1 changed']) # get groups for second user response = self.client.get('/user/' + user2_id + '/groups', headers=self.headers) self.assertEqual(response.status_code, 200, response.data) data = json.loads(response.data.decode('utf-8')) self.assertListEqual([g['name'] for g in data['groups']], ['Group 1 changed', 'Group 2']) # delete groups response = self.client.delete('/group/' + group_id, headers=self.headers) self.assertEqual(response.status_code, 200, response.data) response = self.client.delete('/group/' + group2_id, headers=self.headers) self.assertEqual(response.status_code, 200, response.data)
def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'PLUGINS': [] } self.app = create_app(test_config) self.client = self.app.test_client() self.prod_alert = { 'resource': 'node404', 'event': 'node_down', 'environment': 'Production', 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'], 'origin': 'foo/bar' } self.dev_alert = { 'resource': 'node404', 'event': 'node_marginal', 'environment': 'Development', 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'service': ['Core', 'Web', 'Network'], 'group': 'Network', 'tags': ['level=20', 'switch:off'], 'origin': 'foo/bar' } self.fatal_alert = { 'event': 'node_down', 'resource': 'net01', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'tags': ['foo'], 'attributes': {'foo': 'abc def', 'bar': 1234, 'baz': False}, 'origin': 'foo/bar' } self.critical_alert = { 'event': 'node_marginal', 'resource': 'net02', 'environment': 'Production', 'service': ['Network'], 'severity': 'critical', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/bar', 'timeout': 30 } self.major_alert = { 'event': 'node_marginal', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'major', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/bar', 'timeout': 40 } self.normal_alert = { 'event': 'node_up', 'resource': 'net03', 'environment': 'Production', 'service': ['Network'], 'severity': 'normal', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 100 } self.minor_alert = { 'event': 'node_marginal', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'minor', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 40 } self.ok_alert = { 'event': 'node_up', 'resource': 'net04', 'environment': 'Production', 'service': ['Network'], 'severity': 'ok', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 100 } self.warn_alert = { 'event': 'node_marginal', 'resource': 'net05', 'environment': 'Production', 'service': ['Network'], 'severity': 'warning', 'correlate': ['node_down', 'node_marginal', 'node_up'], 'origin': 'foo/quux', 'timeout': 50 } with self.app.test_request_context('/'): self.app.preprocess_request() self.admin_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key' ) self.customer_api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='demo-key', customer='Foo' ) self.admin_api_key.create() self.customer_api_key.create()
class AuthTestCase(unittest.TestCase): def setUp(self): test_config = { 'TESTING': True, 'AUTH_REQUIRED': True, 'CUSTOMER_VIEWS': True, 'ADMIN_USERS': ['*****@*****.**'], 'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'example.com'] } self.app = create_app(test_config) self.client = self.app.test_client() self.alert = { 'event': 'Foo', 'resource': 'Bar', 'environment': 'Production', 'service': ['Quux'] } with self.app.test_request_context('/'): self.app.preprocess_request() self.api_key = ApiKey( user='******', scopes=['admin', 'read', 'write'], text='admin-key' ) self.api_key.create() self.headers = { 'Authorization': 'Key %s' % self.api_key.key, 'Content-type': 'application/json' } def tearDown(self): db.destroy() def test_blackouts(self): # add customer mapping payload = { 'customer': 'Example Corp', 'match': 'example.com' } response = self.client.post('/customer', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 201) # create user payload = { 'name': 'Example User', 'email': '*****@*****.**', 'password': '******', 'text': '' } response = self.client.post('/auth/signup', data=json.dumps(payload), content_type='application/json', headers=self.headers) self.assertEqual(response.status_code, 200) data = json.loads(response.data.decode('utf-8')) self.assertIsNotNone(data, 'Failed to create user') # use JWT token for user auth token = data['token'] user_headers = { 'Authorization': 'Bearer %s' % token, 'Content-type': 'application/json' } # create user blackout response = self.client.post('/blackout', data=json.dumps({"environment": "Production"}), headers=user_headers) self.assertEqual(response.status_code, 201) data = json.loads(response.data.decode('utf-8')) blackout_id = data['id'] # delete user blackout by admin response = self.client.delete('/blackout/' + blackout_id, headers=self.headers) self.assertEqual(response.status_code, 200)