Esempio n. 1
0
 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
Esempio n. 2
0
 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
Esempio n. 3
0
 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
Esempio n. 4
0
 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))
Esempio n. 5
0
 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))
Esempio n. 6
0
class AuthTestCase(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')
Esempio n. 7
0
class UserTestCase(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']['email'], '*****@*****.**')
        self.assertEqual(data['user']['roles'], ['operator'])
        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
        })
Esempio n. 8
0
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')
Esempio n. 9
0
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 be status=open
        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'], 'open')

        # 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=open
        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'], 'open')

        # 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')
Esempio n. 10
0
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_zrouting: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'
            },
            'API_KEY': 'default-key',
            'HOOK': 'not-set'
        }

        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': f'Key {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):
        plugins.plugins.clear()
        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'], 'dsc-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'])
Esempio n. 11
0
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)
Esempio n. 12
0
class AuthLdapTestCase(unittest.TestCase):
    class LDAPObjectMock:
        def __init__(self, user_to_login, pass_to_login, user_to_bind,
                     pass_to_bind, search_results):
            self.user_to_login = user_to_login
            self.pass_to_login = pass_to_login
            self.user_to_bind = user_to_bind
            self.pass_to_bind = pass_to_bind
            self.search_results = search_results

        def simple_bind_s(self,
                          who=None,
                          cred=None,
                          serverctrls=None,
                          clientctrls=None):
            # raise Exception("{}-{}......{}-{}".format(who, cred, self.user_to_bind, self.pass_to_bind))
            if not ((who == self.user_to_login and cred == self.pass_to_login)
                    or
                    (who == self.user_to_bind and cred == self.pass_to_bind)):
                raise ldap.INVALID_CREDENTIALS
            pass

        def search_s(self,
                     base,
                     scope,
                     filterstr=None,
                     attrlist=None,
                     attrsonly=0):
            return self.search_results

    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 tearDown(self):
        db.destroy()

    def test_401_error(self):

        response = self.client.get('/alerts')
        self.assertEqual(response.status_code, 401)

    def test_ldap_login_defined_dn(self):

        # Attemps to login with the defined DN instead of performing a search
        self.app.config['LDAP_DOMAINS_SEARCH_QUERY'] = {}

        mock_ldap = AuthLdapTestCase.LDAPObjectMock(
            'DN=josephine', 'jojo', 'user_to_bind', 'password_to_bind',
            [('DN=josephine', {
                'mail': [bytearray('*****@*****.**', 'utf-8')]
            })])

        data = self.login_test(mock_ldap, 200)
        self.assertIn('token', data)

    def test_ldap_login_search(self):

        mock_ldap = AuthLdapTestCase.LDAPObjectMock(
            'DN=josephine', 'jojo', 'user_to_bind', 'password_to_bind',
            [('DN=josephine', {
                'mail': [bytearray('*****@*****.**', 'utf-8')]
            })])

        data = self.login_test(mock_ldap, 200)
        self.assertIn('token', data)

    def test_ldap_login_wrong_password(self):

        mock_ldap = AuthLdapTestCase.LDAPObjectMock(
            'DN=josephine', 'jojo_wrong', 'user_to_bind', 'password_to_bind',
            [('DN=josephine', {
                'mail': [bytearray('*****@*****.**', 'utf-8')]
            })])

        data = self.login_test(mock_ldap, 401)
        self.assertIn('message', data)
        self.assertEqual('invalid username or password', data.get('message'))

    def test_ldap_login_wrong_bind_password(self):

        mock_ldap = AuthLdapTestCase.LDAPObjectMock(
            'DN=josephine', 'jojo', 'user_to_bind', 'password_to_bind_wrong',
            [('DN=josephine', {
                'mail': [bytearray('*****@*****.**', 'utf-8')]
            })])

        data = self.login_test(mock_ldap, 401)
        self.assertIn('message', data)
        self.assertEqual('invalid ldap bind username or password',
                         data.get('message'))

    def login_test(self, mock_ldap, expected_response_code):
        # 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)
        json.loads(response.data.decode('utf-8'))

        payload = {'email': '*****@*****.**', 'password': '******'}

        # login now that customer mapping exists
        with patch('ldap.initialize', return_value=mock_ldap):
            response = self.client.post('/auth/login',
                                        data=json.dumps(payload),
                                        content_type='application/json')
            self.assertEqual(response.status_code, expected_response_code)

        return json.loads(response.data.decode('utf-8'))
Esempio n. 13
0
class ForwarderTestCase(unittest.TestCase):
    def setUp(self):

        test_config = {
            'DEBUG': False,
            'TESTING': True,
            'AUTH_REQUIRED': True,
            'BASE_URL': 'http://localhost:8080',
            'PLUGINS': ['forwarder']
        }

        HMAC_AUTH_CREDENTIALS = [
            {  # http://localhost:9001
                'key': 'e3b8afc0-db18-4c51-865d-b95322742c5e',
                'secret': 'MDhjZGMyYTRkY2YyNjk1MTEyMWFlNmM3Y2UxZDU1ZjIK',
                'algorithm': 'sha256'
            },
        ]

        FWD_DESTINATIONS = [
            ('http://localhost:9000', {
                'username': '******',
                'password': '******',
                'timeout': 10
            }, ['alerts', 'actions']),  # BasicAuth
            # ('https://httpbin.org/anything', dict(username='******', password='******', ssl_verify=False), ['*']),
            ('http://localhost:9001', {
                'key': 'e3b8afc0-db18-4c51-865d-b95322742c5e',
                'secret': 'MDhjZGMyYTRkY2YyNjk1MTEyMWFlNmM3Y2UxZDU1ZjIK'
            }, ['actions']),  # Hawk HMAC
            ('http://localhost:9002', {
                'key': 'demo-key'
            }, ['delete']),  # API key
            ('http://localhost:9003', {
                'token': 'bearer-token'
            }, ['*']),  # Bearer token
        ]

        test_config['HMAC_AUTH_CREDENTIALS'] = HMAC_AUTH_CREDENTIALS
        test_config['FWD_DESTINATIONS'] = FWD_DESTINATIONS

        self.app = create_app(test_config)
        self.client = self.app.test_client()

        self.resource = str(uuid4()).upper()[:8]

        self.major_alert = {
            'id': 'b528c6f7-0925-4f6d-b930-fa6c0bba51dc',
            'event': 'node_marginal',
            'resource': self.resource,
            'environment': 'Production',
            'service': ['Network'],
            'severity': 'major',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'timeout': 40
        }
        self.repeated_major_alert = {
            'id': '4ba2b0d6-ff4a-4fc0-8d93-45939c819465',
            'event': 'node_marginal',
            'resource': self.resource,
            'environment': 'Production',
            'service': ['Network'],
            'severity': 'major',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'timeout': 40
        }
        self.warn_alert = {
            'id': '67344228-bd03-4660-9c45-ff9c8f1d53d0',
            'event': 'node_marginal',
            'resource': self.resource,
            'environment': 'Production',
            'service': ['Network'],
            'severity': 'warning',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'timeout': 50
        }
        self.normal_alert = {
            'id': 'cb12250d-42ed-42cc-97ef-592f3a49618c',
            'event': 'node_up',
            'resource': self.resource,
            'environment': 'Production',
            'service': ['Network'],
            'severity': 'normal',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'timeout': 100
        }

        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()

    def tearDown(self):
        plugins.plugins.clear()
        db.destroy()

    @requests_mock.mock()
    def test_forward_alert(self, m):

        ok_response = """
        {"status": "ok"}
        """
        m.post('http://localhost:9000/alert', text=ok_response)
        m.post('http://localhost:9001/alert', text=ok_response)
        m.post('http://localhost:9002/alert', text=ok_response)
        m.post('http://localhost:9003/alert', text=ok_response)

        headers = {
            'Authorization': 'Key %s' % self.api_key.key,
            'Content-type': 'application/json',
            'Origin': 'http://localhost:5000',
            'X-Alerta-Loop': 'http://localhost:5000',
        }
        response = self.client.post('/alert',
                                    data=json.dumps(self.major_alert),
                                    headers=headers)
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['status'], 'ok')

        history = m.request_history
        self.assertEqual(history[0].port, 9000)
        self.assertEqual(history[1].port, 9003)

    @requests_mock.mock()
    def test_forward_action(self, m):

        ok_response = """
        {"status": "ok"}
        """
        m.post('http://localhost:9000/alert', text=ok_response)
        m.post('http://localhost:9003/alert', text=ok_response)

        # create alert
        headers = {
            'Authorization': 'Key %s' % self.api_key.key,
            'Content-type': 'application/json'
        }
        response = self.client.post('/alert',
                                    data=json.dumps(self.warn_alert),
                                    headers=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']

        m.put('http://localhost:9000/alert/{}/action'.format(alert_id),
              text=ok_response)
        m.put('http://localhost:9001/alert/{}/action'.format(alert_id),
              text=ok_response)
        m.put('http://localhost:9002/alert/{}/action'.format(alert_id),
              text=ok_response)
        m.put('http://localhost:9003/alert/{}/action'.format(alert_id),
              text=ok_response)

        headers = {
            'Authorization': 'Key %s' % self.api_key.key,
            'Content-type': 'application/json',
            'Origin': 'http://localhost:8000'
        }
        response = self.client.put('/alert/{}/action'.format(alert_id),
                                   data=json.dumps({'action': 'ack'}),
                                   headers=headers)
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['status'], 'ok')

        history = m.request_history
        self.assertEqual(history[0].port, 9000)
        self.assertEqual(history[1].port, 9003)
        self.assertEqual(history[2].port, 9000)
        self.assertEqual(history[3].port, 9001)
        self.assertEqual(history[4].port, 9003)

    @requests_mock.mock()
    def test_forward_delete(self, m):

        ok_response = """
        {"status": "ok"}
        """
        m.post('http://localhost:9000/alert', text=ok_response)
        m.post('http://localhost:9003/alert', text=ok_response)

        # create alert
        headers = {
            'Authorization': 'Key %s' % self.api_key.key,
            'Content-type': 'application/json'
        }
        response = self.client.post('/alert',
                                    data=json.dumps(self.warn_alert),
                                    headers=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']

        m.delete('http://localhost:9002/alert/{}'.format(alert_id),
                 text=ok_response)
        m.delete('http://localhost:9003/alert/{}'.format(alert_id),
                 text=ok_response)

        headers = {
            'Authorization': 'Key %s' % self.api_key.key,
            'Content-type': 'application/json',
            'Origin': 'http://localhost:8000'
        }
        response = self.client.delete('/alert/{}'.format(alert_id),
                                      headers=headers)
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['status'], 'ok')

        history = m.request_history
        self.assertEqual(history[0].port, 9000)
        self.assertEqual(history[1].port, 9003)
        self.assertEqual(history[2].port, 9002)
        self.assertEqual(history[3].port, 9003)

    @requests_mock.mock()
    def test_forward_heartbeat(self, m):
        # FIXME: currently not possible
        pass

    @requests_mock.mock()
    def test_already_processed(self, m):
        # Alert is not processed locally or forwarded when an Alerta server
        # receives an alert which it has already processed. This is
        # determined by checking to see if the BASE_URL of the server
        # is already in the X-Alerta-Loop header. A 202 is returned because
        # the alert was accepted, even though it wasn't processed.

        ok_response = """
        {"status": "ok"}
        """
        m.post('http://localhost:9000/alert', text=ok_response)
        m.post('http://localhost:9001/alert', text=ok_response)
        m.post('http://localhost:9002/alert', text=ok_response)
        m.post('http://localhost:9003/alert', text=ok_response)

        headers = {
            'Authorization': 'Key %s' % self.api_key.key,
            'Content-type': 'application/json',
            'Origin': 'http://localhost:5000',
            'X-Alerta-Loop': 'http://localhost:8080,http://localhost:5000',
        }
        response = self.client.post('/alert',
                                    data=json.dumps(self.major_alert),
                                    headers=headers)
        self.assertEqual(response.status_code, 202)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['status'], 'ok')
        self.assertEqual(
            data['message'],
            'Alert forwarded by http://localhost:5000 already processed by http://localhost:8080'
        )

        self.assertEqual(m.called, False)

    @requests_mock.mock()
    def test_forward_loop(self, m):
        # Alert is processed locally but not forwarded on to the remote
        # because it is already in the X-Alerta-Loop header. A 201 is
        # returned because the alert has been received and processed.

        ok_response = """
        {"status": "ok"}
        """
        m.post('http://localhost:9000/alert', text=ok_response)
        m.post('http://localhost:9001/alert', text=ok_response)
        m.post('http://localhost:9002/alert', text=ok_response)
        m.post('http://localhost:9003/alert', text=ok_response)

        headers = {
            'Authorization':
            'Key %s' % self.api_key.key,
            'Content-type':
            'application/json',
            'X-Alerta-Loop':
            'http://localhost:9000,http://localhost:9001,http://localhost:9002,http://localhost:9003',
        }
        response = self.client.post('/alert',
                                    data=json.dumps(self.warn_alert),
                                    headers=headers)
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['status'], 'ok')

        self.assertEqual(m.called, False)

    def test_do_not_forward(self):
        # check forwarding rule for remote
        pass

    def test_base_url(self):

        with self.app.test_request_context('/'):
            self.assertEqual(base_url(), 'http://localhost:8080')
Esempio n. 14
0
class BuiltinsTestCase(unittest.TestCase):
    def setUp(self):

        test_config = {
            'TESTING':
            True,
            'AUTH_REQUIRED':
            True,
            'PLUGINS': [
                'remote_ip', 'reject', 'heartbeat', 'blackout', 'acked_by',
                'forwarder'
            ]
        }
        os.environ['ALLOWED_ENVIRONMENTS'] = 'Production,Staging,Development'

        self.app = create_app(test_config)
        self.client = self.app.test_client()

        self.resource = str(uuid4()).upper()[:8]

        self.reject_alert = {
            'event': 'node_marginal',
            'resource': self.resource,
            'environment': 'Production',
            'service':
            [],  # alert will be rejected because service not defined
            'severity': 'warning',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'tags': ['one', 'two']
        }

        self.accept_alert = {
            'event': 'node_marginal',
            'resource': self.resource,
            'environment': 'Production',
            'service':
            ['Network'],  # alert will be accepted because service defined
            'severity': 'warning',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'tags': ['three', 'four']
        }

        self.critical_alert = {
            'event': 'node_down',
            'resource': self.resource,
            'environment': 'Production',
            'service': ['Network'],
            'severity': 'critical',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'tags': []
        }

        self.ok_alert = {
            'event': 'node_up',
            'resource': self.resource,
            'environment': 'Production',
            'service': ['Network'],
            'severity': 'ok',
            'correlate': ['node_down', 'node_marginal', 'node_up'],
            'tags': []
        }
        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',
            'X-Forwarded-For': '172.217.20.36'
        }

    def tearDown(self):
        plugins.plugins.clear()
        db.destroy()

    def test_remote_ip_alert(self):

        # create alert
        response = self.client.post('/alert',
                                    json=self.critical_alert,
                                    headers=self.headers)
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['alert']['attributes']['ip'], '172.217.20.36')

    def test_reject_alert(self):

        # create alert that will be rejected
        response = self.client.post('/alert',
                                    data=json.dumps(self.reject_alert),
                                    headers=self.headers)
        self.assertEqual(response.status_code, 403)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['status'], 'error')
        self.assertEqual(data['message'],
                         '[POLICY] Alert must define a service')

        # create alert that will be accepted
        response = self.client.post('/alert',
                                    data=json.dumps(self.accept_alert),
                                    headers=self.headers)
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['status'], 'ok')
        self.assertRegex(
            data['id'],
            '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')

    def test_heartbeat_alert(self):

        self.heartbeat_alert = {
            'event': 'Heartbeat',
            'resource': 'hb01',
            'environment': 'Production',
            'service': ['Svc1'],
            'severity': 'informational',
        }

        # create alert
        response = self.client.post('/alert',
                                    json=self.heartbeat_alert,
                                    headers=self.headers)
        self.assertEqual(response.status_code, 202)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['message'], 'Alert converted to Heartbeat')

    # XXX - blackout plugin tested extensively in test_blackouts.py

    def test_acked_by_plugin(self):

        # create alert
        response = self.client.post('/alert',
                                    json=self.critical_alert,
                                    headers=self.headers)
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))

        alert_id = data['id']

        # ack alert
        payload = {'action': 'ack', 'text': 'ack the alert'}
        response = self.client.put('/alert/' + alert_id + '/action',
                                   json=payload,
                                   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']['attributes']['acked-by'],
                         '*****@*****.**')

        # clear alert
        response = self.client.post('/alert',
                                    json=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')
        self.assertEqual(data['alert']['attributes']['acked-by'],
                         '*****@*****.**')

        # critical alert (unacked)
        response = self.client.post('/alert',
                                    json=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')
        self.assertNotIn('acked-by', data['alert']['attributes'])

        # ack alert (again)
        payload = {'action': 'ack', 'text': 'ack the alert, again'}
        response = self.client.put('/alert/' + alert_id + '/action',
                                   json=payload,
                                   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']['attributes']['acked-by'],
                         '*****@*****.**')

        # unack alert
        payload = {'action': 'unack', 'text': 'unack the alert'}
        response = self.client.put('/alert/' + alert_id + '/action',
                                   json=payload,
                                   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.assertNotIn('acked-by', data['alert']['attributes'])
Esempio n. 15
0
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')
Esempio n. 16
0
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')
Esempio n. 17
0
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'])
Esempio n. 18
0
class AuthTestCase(unittest.TestCase):

    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 API key - not for production use',
                key='demo-key'
            )
            self.api_key.create()

        self.headers = {
            'Authorization': f'Key {self.api_key.key}',
            'Content-type': 'application/json'
        }

    def tearDown(self):
        plugins.plugins.clear()
        db.destroy()

    def test_401_error(self):

        response = self.client.get('/alerts')
        self.assertEqual(response.status_code, 401)

    def test_user_defined_key(self):

        self.assertEqual(self.api_key.key, 'demo-key')

    def test_admin_key(self):

        payload = {
            'user': '******',
            'scopes': ['admin']
        }

        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')

        admin_api_key = data['key']

        response = self.client.post('/alert', data=json.dumps(self.alert),
                                    content_type='application/json', headers={'Authorization': 'Key ' + admin_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')

        alert_id = data['id']

        response = self.client.get('/alerts', headers={'Authorization': 'Key ' + admin_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/' + admin_api_key, headers={'Authorization': 'Key ' + admin_api_key})
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['key']['scopes'], ['admin'])

        # delete alert
        response = self.client.delete('/alert/' + alert_id, headers={'Authorization': 'Key ' + admin_api_key})
        self.assertEqual(response.status_code, 200)

        response = self.client.delete('/key/' + admin_api_key, headers=self.headers)
        self.assertEqual(response.status_code, 200)

    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')

        alert_id = data['id']

        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'])

        # delete alert
        response = self.client.delete('/alert/' + alert_id, headers={'Authorization': 'Key ' + rw_api_key})
        self.assertEqual(response.status_code, 403)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['message'], 'Missing required scope: delete:alerts')

        response = self.client.delete('/key/' + rw_api_key, headers=self.headers)
        self.assertEqual(response.status_code, 200)

    def test_rw_delete_key(self):

        payload = {
            'user': '******',
            'scopes': ['read', 'write', 'delete:alerts']
        }

        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-delete key')
        self.assertEqual(data['data']['scopes'], ['read', 'write', 'delete:alerts'])

        rwd_api_key = data['key']

        response = self.client.post('/alert', data=json.dumps(self.alert),
                                    content_type='application/json', headers={'Authorization': 'Key ' + rwd_api_key})
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['alert']['history'][0]['user'], 'rw-delete-demo-key-user')

        alert_id = data['id']

        response = self.client.get('/alerts', headers={'Authorization': 'Key ' + rwd_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/' + rwd_api_key, headers={'Authorization': 'Key ' + rwd_api_key})
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['key']['scopes'], ['read', 'write', 'delete:alerts'])

        # delete alert
        response = self.client.delete('/alert/' + alert_id, headers={'Authorization': 'Key ' + rwd_api_key})
        self.assertEqual(response.status_code, 200)

        response = self.client.delete('/key/' + rwd_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': f'Key {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(b'[email protected]:blackforest').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
        })

    def test_hmac_auth(self):

        credentials = {
            'id': self.access_key,
            'key': self.secret_key,
            'algorithm': 'sha256'
        }

        sender = Sender(
            url='http://localhost/alerts',
            method='GET',
            content='',
            content_type='application/json',
            credentials=credentials
        )
        headers = {
            'Authorization': sender.request_header,
            'Content-Type': 'application/json'
        }
        response = self.client.get('/alerts', headers=headers)
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.data.decode('utf-8'))

        sender = Sender(
            url='http://localhost/alert',
            method='POST',
            content=json.dumps(self.alert),
            content_type='application/json',
            credentials=credentials
        )
        headers = {
            'Authorization': sender.request_header,
            'Content-Type': 'application/json'
        }
        response = self.client.post('/alert', data=json.dumps(self.alert),
                                    content_type='application/json', headers=headers)
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))
        self.assertEqual(data['alert']['event'], 'Foo')
Esempio n. 19
0
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
        })
Esempio n. 20
0
class AlertNotesTestCase(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']
        }

        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
        }

        with self.app.test_request_context('/'):
            self.app.preprocess_request()
            self.admin_api_key = ApiKey(user='******',
                                        scopes=ADMIN_SCOPES,
                                        text='demo-key')
            self.customer_api_key = ApiKey(user='******',
                                           scopes=ADMIN_SCOPES,
                                           text='demo-key',
                                           customer='Foo')
            self.admin_api_key.create()
            self.customer_api_key.create()

    def tearDown(self):
        db.destroy()

    def test_alert_notes(self):

        self.headers = {
            'Authorization': f'Key {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)
        data = json.loads(response.data.decode('utf-8'))

        alert_id = data['id']

        # get alert
        response = self.client.get(f'/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')

        # add note to alert
        note = {'text': 'this is a note'}
        response = self.client.put(f'/alert/{alert_id}/note',
                                   data=json.dumps(note),
                                   headers=self.headers)
        self.assertEqual(response.status_code, 201)
        data = json.loads(response.data.decode('utf-8'))

        note_id = data['id']

        self.assertEqual(data['note']['text'], 'this is a note')
        self.assertEqual(data['note']['user'], '*****@*****.**')
        self.assertEqual(
            sorted(data['note']['attributes']),
            sorted({
                'resource': 'node404',
                'event': 'node_down',
                'environment': 'Production',
                'severity': 'major',
                'status': 'open'
            }))
        self.assertEqual(data['note']['type'], 'alert')
        self.assertIsNotNone(data['note']['createTime'])
        self.assertIsNone(data['note']['updateTime'])
        self.assertIn(alert_id, data['note']['_links']['alert'])
        self.assertEqual(data['note']['customer'], None)

        # list notes for alert
        response = self.client.get(f'/alert/{alert_id}/notes',
                                   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['notes'][0]['id'], note_id)
        self.assertEqual(data['notes'][0]['text'], 'this is a note')

        # update note text
        note = {'text': 'this note has changed'}
        response = self.client.put(f'/alert/{alert_id}/note/{note_id}',
                                   data=json.dumps(note),
                                   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['note']['text'], 'this note has changed')
        self.assertEqual(data['note']['user'], '*****@*****.**')
        self.assertEqual(
            sorted(data['note']['attributes']),
            sorted({
                'resource': 'node404',
                'event': 'node_down',
                'environment': 'Production',
                'severity': 'major',
                'status': 'open'
            }))
        self.assertEqual(data['note']['type'], 'alert')
        self.assertIsNotNone(data['note']['createTime'])
        self.assertIsNotNone(data['note']['updateTime'])
        self.assertIn(alert_id, data['note']['_links']['alert'])
        self.assertEqual(data['note']['customer'], None)

        # list notes for alert (again)
        response = self.client.get(f'/alert/{alert_id}/notes',
                                   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['notes'][0]['id'], note_id)
        self.assertEqual(data['notes'][0]['text'], 'this note has changed')

        # delete note
        response = self.client.delete(f'/alert/{alert_id}/note/{note_id}',
                                      headers=self.headers)
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.data.decode('utf-8'))

        self.assertEqual(data['status'], 'ok')
Esempio n. 21
0
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 = {
            '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_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
        response = self.client.post('/blackout',
                                    data=json.dumps({
                                        "environment": "Production",
                                        "service": ["Network"]
                                    }),
                                    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)

        # 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')
Esempio n. 22
0
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})
Esempio n. 23
0
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)
Esempio n. 24
0
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)
Esempio n. 25
0
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):
        plugins.plugins.clear()
        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.assertCountEqual([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.assertCountEqual([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.assertCountEqual([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.assertCountEqual([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.assertCountEqual([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.assertCountEqual([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)
Esempio n. 26
0
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)
Esempio n. 27
0
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)
Esempio n. 28
0
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')
Esempio n. 29
0
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')
Esempio n. 30
0
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)