Пример #1
0
 def get(cls, value):
     # DB does not contain key but the key_hash.
     value_hash = hash_utils.hash(value)
     for model_object in ApiKeyDB.objects(key_hash=value_hash):
         return model_object
     raise ApiKeyNotFoundError('ApiKey with key_hash=%s not found.' %
                               value_hash)
Пример #2
0
class TestApiKeyBasedAuth(FunctionalTest):

    enable_auth = True

    apikey1 = None
    apikey_disabled = None

    @classmethod
    def setUpClass(cls):
        super(TestApiKeyBasedAuth, cls).setUpClass()
        models = FixturesLoader().save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                                      fixtures_dict=TEST_MODELS)
        cls.apikey1 = models['apikeys']['apikey1.yaml']
        cls.apikey_disabled = models['apikeys']['apikey_disabled.yaml']

    @mock.patch.object(User, 'get_by_name', mock.Mock(return_value=UserDB(name='bill')))
    def test_apikey_validation_apikey_in_headers(self):
        response = self.app.get('/v1/actions', headers={'St2-Api-key': KEY1_KEY},
                                expect_errors=False)
        self.assertTrue('application/json' in response.headers['content-type'])
        self.assertEqual(response.status_int, 200)

    @mock.patch.object(User, 'get_by_name', mock.Mock(return_value=UserDB(name='bill')))
    def test_apikey_validation_apikey_in_query_params(self):
        response = self.app.get('/v1/actions?st2-api-key=%s' % (KEY1_KEY), expect_errors=False)
        self.assertTrue('application/json' in response.headers['content-type'])
        self.assertEqual(response.status_int, 200)

    def test_apikey_disabled(self):
        response = self.app.get('/v1/actions', headers={'St2-Api-key': DISABLED_KEY},
                                expect_errors=True)
        self.assertTrue('application/json' in response.headers['content-type'])
        self.assertEqual(response.status_int, 401)
        self.assertEqual(response.json_body['faultstring'], 'Unauthorized - API key is disabled.')

    def test_apikey_not_found(self):
        response = self.app.get('/v1/actions', headers={'St2-Api-key': 'UNKNOWN'},
                                expect_errors=True)
        self.assertTrue('application/json' in response.headers['content-type'])
        self.assertEqual(response.status_int, 401)
        self.assertRegexpMatches(response.json_body['faultstring'],
                                 '^Unauthorized - ApiKey with key_hash=([a-zA-Z0-9]+) not found.$')

    @mock.patch.object(
        Token, 'get',
        mock.Mock(return_value=TokenDB(id=OBJ_ID, user=USER, token=TOKEN, expiry=FUTURE)))
    @mock.patch.object(
        ApiKey, 'get',
        mock.Mock(return_value=ApiKeyDB(user=USER, key_hash=KEY1_KEY, enabled=True)))
    @mock.patch.object(User, 'get_by_name', mock.Mock(return_value=USER_DB))
    def test_multiple_auth_sources(self):
        response = self.app.get('/v1/actions',
                                headers={'X-Auth-Token': TOKEN, 'St2-Api-key': KEY1_KEY},
                                expect_errors=True)
        self.assertTrue('application/json' in response.headers['content-type'])
        self.assertEqual(response.status_int, 401)
        self.assertEqual(response.json_body['faultstring'],
                         'Unauthorized - Only one of Token or API key expected.')
Пример #3
0
USR_TOKEN = TokenDB(id=bson.ObjectId(),
                    user="******",
                    token=uuid.uuid4().hex,
                    expiry=EXPIRY)

FIXTURES_PACK = "generic"
FIXTURES = {"users": ["system_user.yaml", "token_user.yaml"]}

# These parameters are used for the tests of getting value from datastore and decrypting it at
# Jinja expression in a action metadata definition.
TEST_USER = UserDB(name="user1")
TEST_TOKEN = TokenDB(id=bson.ObjectId(),
                     user=TEST_USER,
                     token=uuid.uuid4().hex,
                     expiry=EXPIRY)
TEST_APIKEY = ApiKeyDB(user=TEST_USER, key_hash="secret_key", enabled=True)


def mock_get_token(*args, **kwargs):
    if args[0] == SYS_TOKEN.token:
        return SYS_TOKEN
    return USR_TOKEN


@mock.patch.object(PoolPublisher, "publish", mock.MagicMock())
class ActionExecutionControllerTestCaseAuthEnabled(FunctionalTest):

    enable_auth = True

    @classmethod
    @mock.patch.object(Token, "get",
Пример #4
0
class TestApiKeyBasedAuth(FunctionalTest):

    enable_auth = True

    apikey1 = None
    apikey_disabled = None

    @classmethod
    def setUpClass(cls):
        super(TestApiKeyBasedAuth, cls).setUpClass()
        models = FixturesLoader().save_fixtures_to_db(
            fixtures_pack=FIXTURES_PACK, fixtures_dict=TEST_MODELS
        )
        cls.apikey1 = models["apikeys"]["apikey1.yaml"]
        cls.apikey_disabled = models["apikeys"]["apikey_disabled.yaml"]

    @mock.patch.object(User, "get_by_name", mock.Mock(return_value=UserDB(name="bill")))
    def test_apikey_validation_apikey_in_headers(self):
        response = self.app.get(
            "/v1/actions", headers={"St2-Api-key": KEY1_KEY}, expect_errors=False
        )
        self.assertIn("application/json", response.headers["content-type"])
        self.assertEqual(response.status_int, 200)

    @mock.patch.object(User, "get_by_name", mock.Mock(return_value=UserDB(name="bill")))
    def test_apikey_validation_apikey_in_query_params(self):
        response = self.app.get(
            "/v1/actions?st2-api-key=%s" % (KEY1_KEY), expect_errors=False
        )
        self.assertIn("application/json", response.headers["content-type"])
        self.assertEqual(response.status_int, 200)

    @mock.patch.object(User, "get_by_name", mock.Mock(return_value=UserDB(name="bill")))
    def test_apikey_validation_apikey_in_cookies(self):
        response = self.app.get(
            "/v1/actions", headers={"St2-Api-key": KEY1_KEY}, expect_errors=False
        )
        self.assertIn("application/json", response.headers["content-type"])
        self.assertEqual(response.status_int, 200)

        with mock.patch.object(self.app.cookiejar, "clear", return_value=None):
            response = self.app.get("/v1/actions", expect_errors=True)
        self.assertEqual(response.status_int, 401)
        self.assertEqual(
            response.json_body["faultstring"],
            "Unauthorized - One of Token or API key required.",
        )

    def test_apikey_disabled(self):
        response = self.app.get(
            "/v1/actions", headers={"St2-Api-key": DISABLED_KEY}, expect_errors=True
        )
        self.assertIn("application/json", response.headers["content-type"])
        self.assertEqual(response.status_int, 401)
        self.assertEqual(
            response.json_body["faultstring"], "Unauthorized - API key is disabled."
        )

    def test_apikey_not_found(self):
        response = self.app.get(
            "/v1/actions", headers={"St2-Api-key": "UNKNOWN"}, expect_errors=True
        )
        self.assertIn("application/json", response.headers["content-type"])
        self.assertEqual(response.status_int, 401)
        self.assertRegexpMatches(
            response.json_body["faultstring"],
            "^Unauthorized - ApiKey with key_hash=([a-zA-Z0-9]+) not found.$",
        )

    @mock.patch.object(
        Token,
        "get",
        mock.Mock(
            return_value=TokenDB(id=OBJ_ID, user=USER, token=TOKEN, expiry=FUTURE)
        ),
    )
    @mock.patch.object(
        ApiKey,
        "get",
        mock.Mock(return_value=ApiKeyDB(user=USER, key_hash=KEY1_KEY, enabled=True)),
    )
    @mock.patch.object(User, "get_by_name", mock.Mock(return_value=USER_DB))
    def test_multiple_auth_sources(self):
        response = self.app.get(
            "/v1/actions",
            headers={"X-Auth-Token": TOKEN, "St2-Api-key": KEY1_KEY},
            expect_errors=True,
        )
        self.assertIn("application/json", response.headers["content-type"])
        self.assertEqual(response.status_int, 200)
Пример #5
0
    def test_get_uid(self):
        pack_db = PackDB(ref='ma_pack')
        self.assertEqual(pack_db.get_uid(), 'pack:ma_pack')
        self.assertTrue(pack_db.has_valid_uid())

        sensor_type_db = SensorTypeDB(name='sname', pack='spack')
        self.assertEqual(sensor_type_db.get_uid(), 'sensor_type:spack:sname')
        self.assertTrue(sensor_type_db.has_valid_uid())

        action_db = ActionDB(name='aname', pack='apack', runner_type={})
        self.assertEqual(action_db.get_uid(), 'action:apack:aname')
        self.assertTrue(action_db.has_valid_uid())

        rule_db = RuleDB(name='rname', pack='rpack')
        self.assertEqual(rule_db.get_uid(), 'rule:rpack:rname')
        self.assertTrue(rule_db.has_valid_uid())

        trigger_type_db = TriggerTypeDB(name='ttname', pack='ttpack')
        self.assertEqual(trigger_type_db.get_uid(), 'trigger_type:ttpack:ttname')
        self.assertTrue(trigger_type_db.has_valid_uid())

        trigger_db = TriggerDB(name='tname', pack='tpack')
        self.assertTrue(trigger_db.get_uid().startswith('trigger:tpack:tname:'))

        # Verify that same set of parameters always results in the same hash
        parameters = {'a': 1, 'b': 'unicode', 'c': [1, 2, 3], 'd': {'g': 1, 'h': 2}}
        paramers_hash = json.dumps(parameters, sort_keys=True)
        paramers_hash = hashlib.md5(paramers_hash.encode()).hexdigest()

        parameters = {'a': 1, 'b': 'unicode', 'c': [1, 2, 3], 'd': {'g': 1, 'h': 2}}
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = {'c': [1, 2, 3], 'b': u'unicode', 'd': {'h': 2, 'g': 1}, 'a': 1}
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = {'b': u'unicode', 'c': [1, 2, 3], 'd': {'h': 2, 'g': 1}, 'a': 1}
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = OrderedDict({'c': [1, 2, 3], 'b': u'unicode', 'd': {'h': 2, 'g': 1}, 'a': 1})
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        policy_type_db = PolicyTypeDB(resource_type='action', name='concurrency')
        self.assertEqual(policy_type_db.get_uid(), 'policy_type:action:concurrency')
        self.assertTrue(policy_type_db.has_valid_uid())

        policy_db = PolicyDB(pack='dummy', name='policy1')
        self.assertEqual(policy_db.get_uid(), 'policy:dummy:policy1')

        api_key_db = ApiKeyDB(key_hash='valid')
        self.assertEqual(api_key_db.get_uid(), 'api_key:valid')
        self.assertTrue(api_key_db.has_valid_uid())

        api_key_db = ApiKeyDB()
        self.assertEqual(api_key_db.get_uid(), 'api_key:')
        self.assertFalse(api_key_db.has_valid_uid())
Пример #6
0
class TestTokenController(FunctionalTest):

    @classmethod
    def setUpClass(cls, **kwargs):
        kwargs['extra_environ'] = {
            'REMOTE_USER': USERNAME
        }
        super(TestTokenController, cls).setUpClass(**kwargs)

    def test_token_model(self):
        dt = date_utils.get_datetime_utc_now()
        tk1 = TokenAPI(user='******', token=uuid.uuid4().hex,
                       expiry=isotime.format(dt, offset=False))
        tkdb1 = TokenAPI.to_model(tk1)
        self.assertIsNotNone(tkdb1)
        self.assertIsInstance(tkdb1, TokenDB)
        self.assertEqual(tkdb1.user, tk1.user)
        self.assertEqual(tkdb1.token, tk1.token)
        self.assertEqual(tkdb1.expiry, isotime.parse(tk1.expiry))
        tkdb2 = Token.add_or_update(tkdb1)
        self.assertEqual(tkdb1, tkdb2)
        self.assertIsNotNone(tkdb2.id)
        tk2 = TokenAPI.from_model(tkdb2)
        self.assertEqual(tk2.user, tk1.user)
        self.assertEqual(tk2.token, tk1.token)
        self.assertEqual(tk2.expiry, tk1.expiry)

    def test_token_model_null_token(self):
        dt = date_utils.get_datetime_utc_now()
        tk = TokenAPI(user='******', token=None, expiry=isotime.format(dt))
        self.assertRaises(ValueError, Token.add_or_update, TokenAPI.to_model(tk))

    def test_token_model_null_user(self):
        dt = date_utils.get_datetime_utc_now()
        tk = TokenAPI(user=None, token=uuid.uuid4().hex, expiry=isotime.format(dt))
        self.assertRaises(ValueError, Token.add_or_update, TokenAPI.to_model(tk))

    def test_token_model_null_expiry(self):
        tk = TokenAPI(user='******', token=uuid.uuid4().hex, expiry=None)
        self.assertRaises(ValueError, Token.add_or_update, TokenAPI.to_model(tk))

    def _test_token_post(self, path=TOKEN_V1_PATH):
        ttl = cfg.CONF.auth.token_ttl
        timestamp = date_utils.get_datetime_utc_now()
        response = self.app.post_json(path, {}, expect_errors=False)
        expected_expiry = date_utils.get_datetime_utc_now() + datetime.timedelta(seconds=ttl)
        expected_expiry = date_utils.add_utc_tz(expected_expiry)
        self.assertEqual(response.status_int, 201)
        self.assertIsNotNone(response.json['token'])
        self.assertEqual(response.json['user'], USERNAME)
        actual_expiry = isotime.parse(response.json['expiry'])
        self.assertLess(timestamp, actual_expiry)
        self.assertLess(actual_expiry, expected_expiry)
        return response

    def test_token_post_unauthorized(self):
        response = self.app.post_json(TOKEN_V1_PATH, {}, expect_errors=True, extra_environ={
            'REMOTE_USER': ''
        })
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(side_effect=Exception()))
    @mock.patch.object(
        User, 'add_or_update',
        mock.Mock(return_value=UserDB(name=USERNAME)))
    def test_token_post_new_user(self):
        self._test_token_post()

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_existing_user(self):
        self._test_token_post()

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_success_x_api_url_header_value(self):
        # auth.api_url option is explicitly set
        cfg.CONF.set_override('api_url', override='https://example.com', group='auth')

        resp = self._test_token_post()
        self.assertEqual(resp.headers['X-API-URL'], 'https://example.com')

        # auth.api_url option is not set, url is inferred from listen host and port
        cfg.CONF.set_override('api_url', override=None, group='auth')

        resp = self._test_token_post()
        self.assertEqual(resp.headers['X-API-URL'], 'http://127.0.0.1:9101')

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_default_url_path(self):
        self._test_token_post(path=TOKEN_DEFAULT_PATH)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_set_ttl(self):
        timestamp = date_utils.add_utc_tz(date_utils.get_datetime_utc_now())
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': 60}, expect_errors=False)
        expected_expiry = date_utils.get_datetime_utc_now() + datetime.timedelta(seconds=60)
        self.assertEqual(response.status_int, 201)
        actual_expiry = isotime.parse(response.json['expiry'])
        self.assertLess(timestamp, actual_expiry)
        self.assertLess(actual_expiry, expected_expiry)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_no_data_in_body_text_plain_context_type_used(self):
        response = self.app.post(TOKEN_V1_PATH, expect_errors=False, content_type='text/plain')
        self.assertEqual(response.status_int, 201)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_set_ttl_over_policy(self):
        ttl = cfg.CONF.auth.token_ttl
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': ttl + 60}, expect_errors=True)
        self.assertEqual(response.status_int, 400)
        message = 'TTL specified %s is greater than max allowed %s.' % (
                  ttl + 60, ttl
        )
        self.assertEqual(response.json['faultstring'], message)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_set_bad_ttl(self):
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': -1}, expect_errors=True)
        self.assertEqual(response.status_int, 400)
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': 0}, expect_errors=True)
        self.assertEqual(response.status_int, 400)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_unauthorized(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. 401 is expected because an API key or token is not provided in header.
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH, data, expect_errors=True)
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_unauthorized_bad_api_key(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. 401 is expected because the API key is bad.
        headers = {'St2-Api-Key': 'foobar'}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH, data, headers=headers, expect_errors=True)
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_unauthorized_bad_token(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. 401 is expected because the token is bad.
        headers = {'X-Auth-Token': 'foobar'}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH, data, headers=headers, expect_errors=True)
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    @mock.patch.object(
        ApiKey, 'get',
        mock.MagicMock(return_value=ApiKeyDB(user=USERNAME, key_hash='foobar')))
    def test_token_get_auth_with_api_key(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. Use an API key to authenticate with the st2 auth get token endpoint.
        headers = {'St2-Api-Key': 'foobar'}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH, data, headers=headers, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        self.assertTrue(response.json['valid'])

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_auth_with_token(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, {}, expect_errors=False)

        # Verify the token. Use a token to authenticate with the st2 auth get token endpoint.
        headers = {'X-Auth-Token': str(response.json['token'])}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH, data, headers=headers, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        self.assertTrue(response.json['valid'])

    @mock.patch.object(
        User, 'get_by_name',
        mock.MagicMock(return_value=UserDB(name=USERNAME)))
    @mock.patch.object(
        ApiKey, 'get',
        mock.MagicMock(return_value=ApiKeyDB(user=USERNAME, key_hash='foobar')))
    @mock.patch.object(
        Token, 'get',
        mock.MagicMock(
            return_value=TokenDB(
                user=USERNAME, token='12345',
                expiry=date_utils.get_datetime_utc_now() - datetime.timedelta(minutes=1))))
    def test_token_get_unauthorized_bad_ttl(self):
        # Verify the token. 400 is expected because the token has expired.
        headers = {'St2-Api-Key': 'foobar'}
        data = {'token': '12345'}
        response = self.app.post_json(TOKEN_VERIFY_PATH, data, headers=headers, expect_errors=False)
        self.assertEqual(response.status_int, 200)
        self.assertFalse(response.json['valid'])
Пример #7
0
class TestTokenController(FunctionalTest):
    def setUp(self):
        super(TestTokenController, self).setUp()
        type(pecan.request).remote_user = mock.PropertyMock(
            return_value=USERNAME)

    def test_token_model(self):
        dt = date_utils.get_datetime_utc_now()
        tk1 = TokenAPI(user='******',
                       token=uuid.uuid4().hex,
                       expiry=isotime.format(dt, offset=False))
        tkdb1 = TokenAPI.to_model(tk1)
        self.assertIsNotNone(tkdb1)
        self.assertIsInstance(tkdb1, TokenDB)
        self.assertEqual(tkdb1.user, tk1.user)
        self.assertEqual(tkdb1.token, tk1.token)
        self.assertEqual(tkdb1.expiry, isotime.parse(tk1.expiry))
        tkdb2 = Token.add_or_update(tkdb1)
        self.assertEqual(tkdb1, tkdb2)
        self.assertIsNotNone(tkdb2.id)
        tk2 = TokenAPI.from_model(tkdb2)
        self.assertEqual(tk2.user, tk1.user)
        self.assertEqual(tk2.token, tk1.token)
        self.assertEqual(tk2.expiry, tk1.expiry)

    def test_token_model_null_token(self):
        dt = date_utils.get_datetime_utc_now()
        tk = TokenAPI(user='******', token=None, expiry=isotime.format(dt))
        self.assertRaises(ValueError, Token.add_or_update,
                          TokenAPI.to_model(tk))

    def test_token_model_null_user(self):
        dt = date_utils.get_datetime_utc_now()
        tk = TokenAPI(user=None,
                      token=uuid.uuid4().hex,
                      expiry=isotime.format(dt))
        self.assertRaises(ValueError, Token.add_or_update,
                          TokenAPI.to_model(tk))

    def test_token_model_null_expiry(self):
        tk = TokenAPI(user='******', token=uuid.uuid4().hex, expiry=None)
        self.assertRaises(ValueError, Token.add_or_update,
                          TokenAPI.to_model(tk))

    def _test_token_post(self, path=TOKEN_V1_PATH):
        ttl = cfg.CONF.auth.token_ttl
        timestamp = date_utils.get_datetime_utc_now()
        response = self.app.post_json(path, {}, expect_errors=False)
        expected_expiry = date_utils.get_datetime_utc_now(
        ) + datetime.timedelta(seconds=ttl)
        expected_expiry = date_utils.add_utc_tz(expected_expiry)
        self.assertEqual(response.status_int, 201)
        self.assertIsNotNone(response.json['token'])
        self.assertEqual(response.json['user'], USERNAME)
        actual_expiry = isotime.parse(response.json['expiry'])
        self.assertLess(timestamp, actual_expiry)
        self.assertLess(actual_expiry, expected_expiry)

    def test_token_post_unauthorized(self):
        type(pecan.request).remote_user = None
        response = self.app.post_json(TOKEN_V1_PATH, {}, expect_errors=True)
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(side_effect=Exception()))
    @mock.patch.object(User, 'add_or_update',
                       mock.Mock(return_value=UserDB(name=USERNAME)))
    def test_token_post_new_user(self):
        self._test_token_post()

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_existing_user(self):
        self._test_token_post()

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_default_url_path(self):
        self._test_token_post(path=TOKEN_DEFAULT_PATH)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_set_ttl(self):
        timestamp = date_utils.add_utc_tz(date_utils.get_datetime_utc_now())
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': 60},
                                      expect_errors=False)
        expected_expiry = date_utils.get_datetime_utc_now(
        ) + datetime.timedelta(seconds=60)
        self.assertEqual(response.status_int, 201)
        actual_expiry = isotime.parse(response.json['expiry'])
        self.assertLess(timestamp, actual_expiry)
        self.assertLess(actual_expiry, expected_expiry)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_set_ttl_over_policy(self):
        ttl = cfg.CONF.auth.token_ttl
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': ttl + 60},
                                      expect_errors=True)
        self.assertEqual(response.status_int, 400)
        message = 'TTL specified %s is greater than max allowed %s.' % (
            ttl + 60, ttl)
        self.assertEqual(response.json['faultstring'], message)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_post_set_bad_ttl(self):
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': -1},
                                      expect_errors=True)
        self.assertEqual(response.status_int, 400)
        response = self.app.post_json(TOKEN_V1_PATH, {'ttl': 0},
                                      expect_errors=True)
        self.assertEqual(response.status_int, 400)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_unauthorized(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. 401 is expected because an API key or token is not provided in header.
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH,
                                      data,
                                      expect_errors=True)
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_unauthorized_bad_api_key(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. 401 is expected because the API key is bad.
        headers = {'St2-Api-Key': 'foobar'}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH,
                                      data,
                                      headers=headers,
                                      expect_errors=True)
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_unauthorized_bad_token(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. 401 is expected because the token is bad.
        headers = {'X-Auth-Token': 'foobar'}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH,
                                      data,
                                      headers=headers,
                                      expect_errors=True)
        self.assertEqual(response.status_int, 401)

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    @mock.patch.object(
        ApiKey, 'get',
        mock.MagicMock(return_value=ApiKeyDB(user=USERNAME, key_hash='foobar'))
    )
    def test_token_get_auth_with_api_key(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. Use an API key to authenticate with the st2 auth get token endpoint.
        headers = {'St2-Api-Key': 'foobar'}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH,
                                      data,
                                      headers=headers,
                                      expect_errors=True)
        self.assertEqual(response.status_int, 200)
        self.assertTrue(response.json['valid'])

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    def test_token_get_auth_with_token(self):
        # Create a new token.
        response = self.app.post_json(TOKEN_V1_PATH, expect_errors=False)

        # Verify the token. Use a token to authenticate with the st2 auth get token endpoint.
        headers = {'X-Auth-Token': str(response.json['token'])}
        data = {'token': str(response.json['token'])}
        response = self.app.post_json(TOKEN_VERIFY_PATH,
                                      data,
                                      headers=headers,
                                      expect_errors=True)
        self.assertEqual(response.status_int, 200)
        self.assertTrue(response.json['valid'])

    @mock.patch.object(User, 'get_by_name',
                       mock.MagicMock(return_value=UserDB(name=USERNAME)))
    @mock.patch.object(
        ApiKey, 'get',
        mock.MagicMock(return_value=ApiKeyDB(user=USERNAME, key_hash='foobar'))
    )
    @mock.patch.object(
        Token, 'get',
        mock.MagicMock(
            return_value=TokenDB(user=USERNAME,
                                 token='12345',
                                 expiry=date_utils.get_datetime_utc_now() -
                                 datetime.timedelta(minutes=1))))
    def test_token_get_unauthorized_bad_ttl(self):
        # Verify the token. 400 is expected because the token has expired.
        headers = {'St2-Api-Key': 'foobar'}
        data = {'token': '12345'}
        response = self.app.post_json(TOKEN_VERIFY_PATH,
                                      data,
                                      headers=headers,
                                      expect_errors=False)
        self.assertEqual(response.status_int, 200)
        self.assertFalse(response.json['valid'])
Пример #8
0
    def test_get_uid(self):
        pack_db = PackDB(ref="ma_pack")
        self.assertEqual(pack_db.get_uid(), "pack:ma_pack")
        self.assertTrue(pack_db.has_valid_uid())

        sensor_type_db = SensorTypeDB(name="sname", pack="spack")
        self.assertEqual(sensor_type_db.get_uid(), "sensor_type:spack:sname")
        self.assertTrue(sensor_type_db.has_valid_uid())

        action_db = ActionDB(name="aname", pack="apack", runner_type={})
        self.assertEqual(action_db.get_uid(), "action:apack:aname")
        self.assertTrue(action_db.has_valid_uid())

        rule_db = RuleDB(name="rname", pack="rpack")
        self.assertEqual(rule_db.get_uid(), "rule:rpack:rname")
        self.assertTrue(rule_db.has_valid_uid())

        trigger_type_db = TriggerTypeDB(name="ttname", pack="ttpack")
        self.assertEqual(trigger_type_db.get_uid(), "trigger_type:ttpack:ttname")
        self.assertTrue(trigger_type_db.has_valid_uid())

        trigger_db = TriggerDB(name="tname", pack="tpack")
        self.assertTrue(trigger_db.get_uid().startswith("trigger:tpack:tname:"))

        # Verify that same set of parameters always results in the same hash
        parameters = {"a": 1, "b": "unicode", "c": [1, 2, 3], "d": {"g": 1, "h": 2}}
        paramers_hash = json.dumps(parameters, sort_keys=True)
        paramers_hash = hashlib.md5(paramers_hash.encode()).hexdigest()

        parameters = {"a": 1, "b": "unicode", "c": [1, 2, 3], "d": {"g": 1, "h": 2}}
        trigger_db = TriggerDB(name="tname", pack="tpack", parameters=parameters)
        self.assertEqual(
            trigger_db.get_uid(), "trigger:tpack:tname:%s" % (paramers_hash)
        )
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = {"c": [1, 2, 3], "b": "unicode", "d": {"h": 2, "g": 1}, "a": 1}
        trigger_db = TriggerDB(name="tname", pack="tpack", parameters=parameters)
        self.assertEqual(
            trigger_db.get_uid(), "trigger:tpack:tname:%s" % (paramers_hash)
        )
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = {"b": "unicode", "c": [1, 2, 3], "d": {"h": 2, "g": 1}, "a": 1}
        trigger_db = TriggerDB(name="tname", pack="tpack", parameters=parameters)
        self.assertEqual(
            trigger_db.get_uid(), "trigger:tpack:tname:%s" % (paramers_hash)
        )
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = OrderedDict(
            {"c": [1, 2, 3], "b": "unicode", "d": {"h": 2, "g": 1}, "a": 1}
        )
        trigger_db = TriggerDB(name="tname", pack="tpack", parameters=parameters)
        self.assertEqual(
            trigger_db.get_uid(), "trigger:tpack:tname:%s" % (paramers_hash)
        )
        self.assertTrue(trigger_db.has_valid_uid())

        policy_type_db = PolicyTypeDB(resource_type="action", name="concurrency")
        self.assertEqual(policy_type_db.get_uid(), "policy_type:action:concurrency")
        self.assertTrue(policy_type_db.has_valid_uid())

        policy_db = PolicyDB(pack="dummy", name="policy1")
        self.assertEqual(policy_db.get_uid(), "policy:dummy:policy1")

        api_key_db = ApiKeyDB(key_hash="valid")
        self.assertEqual(api_key_db.get_uid(), "api_key:valid")
        self.assertTrue(api_key_db.has_valid_uid())

        api_key_db = ApiKeyDB()
        self.assertEqual(api_key_db.get_uid(), "api_key:")
        self.assertFalse(api_key_db.has_valid_uid())
Пример #9
0
    def test_get_uid(self):
        pack_db = PackDB(ref='ma_pack')
        self.assertEqual(pack_db.get_uid(), 'pack:ma_pack')
        self.assertTrue(pack_db.has_valid_uid())

        sensor_type_db = SensorTypeDB(name='sname', pack='spack')
        self.assertEqual(sensor_type_db.get_uid(), 'sensor_type:spack:sname')
        self.assertTrue(sensor_type_db.has_valid_uid())

        action_db = ActionDB(name='aname', pack='apack', runner_type={})
        self.assertEqual(action_db.get_uid(), 'action:apack:aname')
        self.assertTrue(action_db.has_valid_uid())

        rule_db = RuleDB(name='rname', pack='rpack')
        self.assertEqual(rule_db.get_uid(), 'rule:rpack:rname')
        self.assertTrue(rule_db.has_valid_uid())

        trigger_type_db = TriggerTypeDB(name='ttname', pack='ttpack')
        self.assertEqual(trigger_type_db.get_uid(), 'trigger_type:ttpack:ttname')
        self.assertTrue(trigger_type_db.has_valid_uid())

        trigger_db = TriggerDB(name='tname', pack='tpack')
        self.assertTrue(trigger_db.get_uid().startswith('trigger:tpack:tname:'))

        # Verify that same set of parameters always results in the same hash
        parameters = {'a': 1, 'b': 'unicode', 'c': [1, 2, 3], 'd': {'g': 1, 'h': 2}}
        paramers_hash = json.dumps(parameters, sort_keys=True)
        paramers_hash = hashlib.md5(paramers_hash.encode()).hexdigest()

        parameters = {'a': 1, 'b': 'unicode', 'c': [1, 2, 3], 'd': {'g': 1, 'h': 2}}
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = {'c': [1, 2, 3], 'b': u'unicode', 'd': {'h': 2, 'g': 1}, 'a': 1}
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = {'b': u'unicode', 'c': [1, 2, 3], 'd': {'h': 2, 'g': 1}, 'a': 1}
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        parameters = OrderedDict({'c': [1, 2, 3], 'b': u'unicode', 'd': {'h': 2, 'g': 1}, 'a': 1})
        trigger_db = TriggerDB(name='tname', pack='tpack', parameters=parameters)
        self.assertEqual(trigger_db.get_uid(), 'trigger:tpack:tname:%s' % (paramers_hash))
        self.assertTrue(trigger_db.has_valid_uid())

        policy_type_db = PolicyTypeDB(resource_type='action', name='concurrency')
        self.assertEqual(policy_type_db.get_uid(), 'policy_type:action:concurrency')
        self.assertTrue(policy_type_db.has_valid_uid())

        policy_db = PolicyDB(pack='dummy', name='policy1')
        self.assertEqual(policy_db.get_uid(), 'policy:dummy:policy1')

        api_key_db = ApiKeyDB(key_hash='valid')
        self.assertEqual(api_key_db.get_uid(), 'api_key:valid')
        self.assertTrue(api_key_db.has_valid_uid())

        api_key_db = ApiKeyDB()
        self.assertEqual(api_key_db.get_uid(), 'api_key:')
        self.assertFalse(api_key_db.has_valid_uid())
Пример #10
0
 def get(cls, value):
     # DB does not contain key but the key_hash.
     value_hash = hash_utils.hash(value)
     for model_object in ApiKeyDB.objects(key_hash=value_hash):
         return model_object
     raise ApiKeyNotFoundError('ApiKey with key_hash=%s not found.' % value_hash)