Example #1
0
    def setUp(self):
        super(KeyValuesControllerRBACTestCase, self).setUp()

        self.kvps = {}

        # Insert mock users
        user_1_db = UserDB(name='user1')
        user_1_db = User.add_or_update(user_1_db)
        self.users['user_1'] = user_1_db

        user_2_db = UserDB(name='user2')
        user_2_db = User.add_or_update(user_2_db)
        self.users['user_2'] = user_2_db

        # Insert mock kvp objects
        kvp_api = KeyValuePairSetAPI(name='test_system_scope', value='value1',
                                     scope=FULL_SYSTEM_SCOPE)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_1'] = kvp_db

        kvp_api = KeyValuePairSetAPI(name='test_system_scope_secret', value='value_secret',
                                     scope=FULL_SYSTEM_SCOPE, secret=True)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_2'] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE, name='test_user_scope_1', user='******')
        kvp_db = KeyValuePairDB(name=name, value='valueu12', scope=FULL_USER_SCOPE)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_3'] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE, name='test_user_scope_2', user='******')
        kvp_api = KeyValuePairSetAPI(name=name, value='user_secret', scope=FULL_USER_SCOPE,
                                     secret=True)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_4'] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE, name='test_user_scope_3', user='******')
        kvp_db = KeyValuePairDB(name=name, value='valueu21', scope=FULL_USER_SCOPE)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_5'] = kvp_db

        self.system_scoped_items_count = 2
        self.user_scoped_items_count = 3
        self.user_scoped_items_per_user_count = {
            'user1': 2,
            'user2': 1
        }
Example #2
0
    def setUp(self):
        super(KeyValuesControllerRBACTestCase, self).setUp()

        self.kvps = {}

        # Insert mock users
        user_1_db = UserDB(name="user1")
        user_1_db = User.add_or_update(user_1_db)
        self.users["user_1"] = user_1_db

        user_2_db = UserDB(name="user2")
        user_2_db = User.add_or_update(user_2_db)
        self.users["user_2"] = user_2_db

        # Insert mock kvp objects
        kvp_api = KeyValuePairSetAPI(name="test_system_scope", value="value1", scope=FULL_SYSTEM_SCOPE)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps["kvp_1"] = kvp_db

        kvp_api = KeyValuePairSetAPI(
            name="test_system_scope_secret", value="value_secret", scope=FULL_SYSTEM_SCOPE, secret=True
        )
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps["kvp_2"] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE, name="test_user_scope_1", user="******")
        kvp_db = KeyValuePairDB(name=name, value="valueu12", scope=FULL_USER_SCOPE)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps["kvp_3"] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE, name="test_user_scope_2", user="******")
        kvp_api = KeyValuePairSetAPI(name=name, value="user_secret", scope=FULL_USER_SCOPE, secret=True)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps["kvp_4"] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE, name="test_user_scope_3", user="******")
        kvp_db = KeyValuePairDB(name=name, value="valueu21", scope=FULL_USER_SCOPE)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps["kvp_5"] = kvp_db

        self.system_scoped_items_count = 2
        self.user_scoped_items_count = 3
        self.user_scoped_items_per_user_count = {"user1": 2, "user2": 1}
Example #3
0
    def put(self, kvp, name, scope=FULL_SYSTEM_SCOPE):
        """
        Create a new entry or update an existing one.
        """
        if not scope:
            scope = FULL_SYSTEM_SCOPE
        requester_user = get_requester()

        scope = getattr(kvp, 'scope', scope)
        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        user = getattr(kvp, 'user', requester_user) or requester_user

        # Validate that the authenticated user is admin if user query param is provided
        assert_request_user_is_admin_if_user_query_param_is_provider(request=pecan.request,
                                                                     user=user)

        key_ref = get_key_reference(scope=scope, name=name, user=user)
        lock_name = self._get_lock_name_for_key(name=key_ref, scope=scope)
        LOG.debug('PUT scope: %s, name: %s', scope, name)
        # TODO: Custom permission check since the key doesn't need to exist here

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            try:
                existing_kvp_api = self._get_one_by_scope_and_name(
                    scope=scope,
                    name=key_ref
                )
            except StackStormDBObjectNotFoundError:
                existing_kvp_api = None

            kvp.name = key_ref
            kvp.scope = scope

            try:
                kvp_db = KeyValuePairAPI.to_model(kvp)

                if existing_kvp_api:
                    kvp_db.id = existing_kvp_api.id

                kvp_db = KeyValuePair.add_or_update(kvp_db)
            except (ValidationError, ValueError) as e:
                LOG.exception('Validation failed for key value data=%s', kvp)
                abort(http_client.BAD_REQUEST, str(e))
                return
            except CryptoKeyNotSetupException as e:
                LOG.exception(str(e))
                abort(http_client.BAD_REQUEST, str(e))
                return
            except InvalidScopeException as e:
                LOG.exception(str(e))
                abort(http_client.BAD_REQUEST, str(e))
                return
        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair updated. KeyValuePair.id=%s' % (kvp_db.id), extra=extra)

        kvp_api = KeyValuePairAPI.from_model(kvp_db)
        return kvp_api
Example #4
0
    def put(self, name, kvp):
        """
        Create a new entry or update an existing one.
        """
        lock_name = self._get_lock_name_for_key(name=name)

        # TODO: Custom permission check since the key doesn't need to exist here

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            existing_kvp = self._get_by_name(resource_name=name)

            kvp.name = name

            try:
                kvp_db = KeyValuePairAPI.to_model(kvp)

                if existing_kvp:
                    kvp_db.id = existing_kvp.id

                kvp_db = KeyValuePair.add_or_update(kvp_db)
            except (ValidationError, ValueError) as e:
                LOG.exception('Validation failed for key value data=%s', kvp)
                abort(http_client.BAD_REQUEST, str(e))
                return
            except CryptoKeyNotSetupException as e:
                LOG.exception(str(e))
                abort(http_client.BAD_REQUEST, str(e))
                return
        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair updated. KeyValuePair.id=%s' % (kvp_db.id), extra=extra)

        kvp_api = KeyValuePairAPI.from_model(kvp_db)
        return kvp_api
    def put(self, name, kvp):
        """
        Create a new entry or update an existing one.
        """
        lock_name = self._get_lock_name_for_key(name=name)

        # TODO: Custom permission check since the key doesn't need to exist here

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            existing_kvp = self.__get_by_name(name=name)

            kvp.name = name

            try:
                kvp_db = KeyValuePairAPI.to_model(kvp)

                if existing_kvp:
                    kvp_db.id = existing_kvp.id

                kvp_db = KeyValuePair.add_or_update(kvp_db)
            except (ValidationError, ValueError) as e:
                LOG.exception('Validation failed for key value data=%s', kvp)
                abort(http_client.BAD_REQUEST, str(e))
                return

        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair updated. KeyValuePair.id=%s' % (kvp_db.id), extra=extra)

        kvp_api = KeyValuePairAPI.from_model(kvp_db)
        return kvp_api
Example #6
0
    def put(self, name, kvp):
        """
        Create a new entry or update an existing one.
        """
        # TODO: There is a race, add custom add_or_update which updates by non
        # id field
        existing_kvp = self.__get_by_name(name=name)

        kvp.name = name

        try:
            kvp_db = KeyValuePairAPI.to_model(kvp)

            if existing_kvp:
                kvp_db.id = existing_kvp.id

            kvp_db = KeyValuePair.add_or_update(kvp_db)
        except (ValidationError, ValueError) as e:
            LOG.exception('Validation failed for key value data=%s', kvp)
            abort(http_client.BAD_REQUEST, str(e))
            return

        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair updated. KeyValuePair.id=%s' % (kvp_db.id), extra=extra)
        kvp_api = KeyValuePairAPI.from_model(kvp_db)

        return kvp_api
Example #7
0
    def put(self, name, kvp):
        """
        Create a new entry or update an existing one.
        """
        # TODO: There is a race, add custom add_or_update which updates by non
        # id field
        existing_kvp = self.__get_by_name(name=name)

        kvp.name = name

        try:
            kvp_db = KeyValuePairAPI.to_model(kvp)

            if existing_kvp:
                kvp_db.id = existing_kvp.id

            kvp_db = KeyValuePair.add_or_update(kvp_db)
        except (ValidationError, ValueError) as e:
            LOG.exception('Validation failed for key value data=%s', kvp)
            abort(http_client.BAD_REQUEST, str(e))
            return

        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair updated. KeyValuePair.id=%s' % (kvp_db.id),
                  extra=extra)
        kvp_api = KeyValuePairAPI.from_model(kvp_db)

        return kvp_api
Example #8
0
    def put(self, kvp, name, scope=FULL_SYSTEM_SCOPE):
        """
        Create a new entry or update an existing one.
        """
        if not scope:
            scope = FULL_SYSTEM_SCOPE
        requester_user = get_requester()

        scope = getattr(kvp, 'scope', scope)
        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        user = getattr(kvp, 'user', requester_user) or requester_user

        # Validate that the authenticated user is admin if user query param is provided
        assert_request_user_is_admin_if_user_query_param_is_provided(
            request=pecan.request, user=user)

        key_ref = get_key_reference(scope=scope, name=name, user=user)
        lock_name = self._get_lock_name_for_key(name=key_ref, scope=scope)
        LOG.debug('PUT scope: %s, name: %s', scope, name)
        # TODO: Custom permission check since the key doesn't need to exist here

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            try:
                existing_kvp_api = self._get_one_by_scope_and_name(
                    scope=scope, name=key_ref)
            except StackStormDBObjectNotFoundError:
                existing_kvp_api = None

            kvp.name = key_ref
            kvp.scope = scope

            try:
                kvp_db = KeyValuePairAPI.to_model(kvp)

                if existing_kvp_api:
                    kvp_db.id = existing_kvp_api.id

                kvp_db = KeyValuePair.add_or_update(kvp_db)
            except (ValidationError, ValueError) as e:
                LOG.exception('Validation failed for key value data=%s', kvp)
                abort(http_client.BAD_REQUEST, str(e))
                return
            except CryptoKeyNotSetupException as e:
                LOG.exception(str(e))
                abort(http_client.BAD_REQUEST, str(e))
                return
            except InvalidScopeException as e:
                LOG.exception(str(e))
                abort(http_client.BAD_REQUEST, str(e))
                return
        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair updated. KeyValuePair.id=%s' % (kvp_db.id),
                  extra=extra)

        kvp_api = KeyValuePairAPI.from_model(kvp_db)
        return kvp_api
    def get_all(self, **kw):
        """
            List all keys.

            Handles requests:
                GET /keys/
        """
        # Prefix filtering
        prefix_filter = kw.get('prefix', None)

        if prefix_filter:
            kw['name__startswith'] = prefix_filter
            del kw['prefix']

        kvp_dbs = KeyValuePair.get_all(**kw)
        kvps = [KeyValuePairAPI.from_model(kvp_db) for kvp_db in kvp_dbs]

        return kvps
    def get_one(self, name):
        """
            List key by name.

            Handle:
                GET /keys/key1
        """
        kvp_db = self.__get_by_name(name=name)

        if not kvp_db:
            LOG.exception('Database lookup for name="%s" resulted in exception.', name)
            abort(http_client.NOT_FOUND)
            return

        try:
            kvp_api = KeyValuePairAPI.from_model(kvp_db)
        except (ValidationError, ValueError) as e:
            abort(http_client.INTERNAL_SERVER_ERROR, str(e))
            return

        return kvp_api
Example #11
0
    def setUp(self):
        super(KeyValuesControllerRBACTestCase, self).setUp()

        self.kvps = {}

        # Insert mock users
        user_1_db = UserDB(name='user1')
        user_1_db = User.add_or_update(user_1_db)
        self.users['user_1'] = user_1_db

        user_2_db = UserDB(name='user2')
        user_2_db = User.add_or_update(user_2_db)
        self.users['user_2'] = user_2_db

        # Insert mock kvp objects
        kvp_api = KeyValuePairSetAPI(name='test_system_scope',
                                     value='value1',
                                     scope=FULL_SYSTEM_SCOPE)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_1'] = kvp_db

        kvp_api = KeyValuePairSetAPI(name='test_system_scope_secret',
                                     value='value_secret',
                                     scope=FULL_SYSTEM_SCOPE,
                                     secret=True)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_2'] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE,
                                 name='test_user_scope_1',
                                 user='******')
        kvp_db = KeyValuePairDB(name=name,
                                value='valueu12',
                                scope=FULL_USER_SCOPE)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_3'] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE,
                                 name='test_user_scope_2',
                                 user='******')
        kvp_api = KeyValuePairSetAPI(name=name,
                                     value='user_secret',
                                     scope=FULL_USER_SCOPE,
                                     secret=True)
        kvp_db = KeyValuePairSetAPI.to_model(kvp_api)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_4'] = kvp_db

        name = get_key_reference(scope=FULL_USER_SCOPE,
                                 name='test_user_scope_3',
                                 user='******')
        kvp_db = KeyValuePairDB(name=name,
                                value='valueu21',
                                scope=FULL_USER_SCOPE)
        kvp_db = KeyValuePair.add_or_update(kvp_db)
        kvp_db = KeyValuePairAPI.from_model(kvp_db)
        self.kvps['kvp_5'] = kvp_db

        self.system_scoped_items_count = 2
        self.user_scoped_items_count = 3
        self.user_scoped_items_per_user_count = {'user1': 2, 'user2': 1}
Example #12
0
    def put(self, kvp, name, requester_user, scope=FULL_SYSTEM_SCOPE):
        """
        Create a new entry or update an existing one.
        """
        if not scope:
            scope = FULL_SYSTEM_SCOPE

        if not requester_user:
            requester_user = UserDB(cfg.CONF.system_user.user)

        scope = getattr(kvp, 'scope', scope)
        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        user = getattr(kvp, 'user', requester_user.name) or requester_user.name

        # Validate that the authenticated user is admin if user query param is provided
        assert_user_is_admin_if_user_query_param_is_provided(user_db=requester_user,
                                                             user=user,
                                                             require_rbac=True)

        # Validate that encrypted option can only be used by admins
        encrypted = getattr(kvp, 'encrypted', False)
        self._validate_encrypted_query_parameter(encrypted=encrypted, scope=scope,
                                                 requester_user=requester_user)

        key_ref = get_key_reference(scope=scope, name=name, user=user)
        lock_name = self._get_lock_name_for_key(name=key_ref, scope=scope)
        LOG.debug('PUT scope: %s, name: %s', scope, name)
        # TODO: Custom permission check since the key doesn't need to exist here

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            try:
                existing_kvp_api = self._get_one_by_scope_and_name(
                    scope=scope,
                    name=key_ref
                )
            except StackStormDBObjectNotFoundError:
                existing_kvp_api = None

            # st2client sends invalid id when initially setting a key so we ignore those
            id_ = kvp.__dict__.get('id', None)
            if not existing_kvp_api and id_ and not bson.ObjectId.is_valid(id_):
                del kvp.__dict__['id']

            kvp.name = key_ref
            kvp.scope = scope

            try:
                kvp_db = KeyValuePairAPI.to_model(kvp)

                if existing_kvp_api:
                    kvp_db.id = existing_kvp_api.id

                kvp_db = KeyValuePair.add_or_update(kvp_db)
            except (ValidationError, ValueError) as e:
                LOG.exception('Validation failed for key value data=%s', kvp)
                abort(http_client.BAD_REQUEST, six.text_type(e))
                return
            except CryptoKeyNotSetupException as e:
                LOG.exception(six.text_type(e))
                abort(http_client.BAD_REQUEST, six.text_type(e))
                return
            except InvalidScopeException as e:
                LOG.exception(six.text_type(e))
                abort(http_client.BAD_REQUEST, six.text_type(e))
                return
        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair updated. KeyValuePair.id=%s' % (kvp_db.id), extra=extra)

        kvp_api = KeyValuePairAPI.from_model(kvp_db)
        return kvp_api
Example #13
0
    def put(self, kvp, name, requester_user, scope=None):
        """
        Create a new entry or update an existing one.
        """
        if not scope or scope == ALL_SCOPE:
            # Default to system scope
            scope = FULL_SYSTEM_SCOPE

        if not requester_user:
            requester_user = UserDB(name=cfg.CONF.system_user.user)

        scope = getattr(kvp, "scope", scope)
        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        user = getattr(kvp, "user", requester_user.name) or requester_user.name

        rbac_utils = get_rbac_backend().get_utils_class()

        # Validate that the authenticated user is admin if user query param is provided
        rbac_utils.assert_user_is_admin_if_user_query_param_is_provided(
            user_db=requester_user, user=user, require_rbac=True)

        # Set key reference for system or user scope
        key_ref = get_key_reference(scope=scope, name=name, user=user)
        extra = {
            "scope": scope,
            "name": name,
            "user": user,
            "key_ref": key_ref
        }
        LOG.debug("PUT /v1/keys/%s", name, extra=extra)

        # Setup a kvp database object used for verifying permission
        kvp_db = KeyValuePairDB(
            uid="%s:%s:%s" % (ResourceType.KEY_VALUE_PAIR, scope, key_ref),
            scope=scope,
            name=key_ref,
        )

        # Check that user has permission to the key value pair.
        # If RBAC is enabled, this check will verify if user has system role with all access.
        # If RBAC is enabled, this check guards against a user accessing another user's kvp.
        # If RBAC is enabled, user needs to be explicitly granted permission to set a system kvp.
        # The check is sufficient to allow decryption of the system kvp.
        rbac_utils.assert_user_has_resource_db_permission(
            user_db=requester_user,
            resource_db=kvp_db,
            permission_type=PermissionType.KEY_VALUE_PAIR_SET,
        )

        # Validate that the pre-encrypted option can only be used by admins
        encrypted = getattr(kvp, "encrypted", False)
        self._validate_encrypted_query_parameter(encrypted=encrypted,
                                                 scope=scope,
                                                 requester_user=requester_user)

        # Acquire a lock to avoid race condition between concurrent API calls
        with self._coordinator.get_lock(
                self._get_lock_name_for_key(name=key_ref, scope=scope)):
            try:
                existing_kvp_api = self._get_one_by_scope_and_name(
                    scope=scope, name=key_ref)
            except StackStormDBObjectNotFoundError:
                existing_kvp_api = None

            # st2client sends invalid id when initially setting a key so we ignore those
            id_ = kvp.__dict__.get("id", None)
            if not existing_kvp_api and id_ and not bson.ObjectId.is_valid(
                    id_):
                del kvp.__dict__["id"]

            kvp.name = key_ref
            kvp.scope = scope

            try:
                kvp_db = KeyValuePairAPI.to_model(kvp)

                if existing_kvp_api:
                    kvp_db.id = existing_kvp_api.id

                kvp_db = KeyValuePair.add_or_update(kvp_db)
            except (ValidationError, ValueError) as e:
                LOG.exception("Validation failed for key value data=%s", kvp)
                abort(http_client.BAD_REQUEST, six.text_type(e))
                return
            except CryptoKeyNotSetupException as e:
                LOG.exception(six.text_type(e))
                abort(http_client.BAD_REQUEST, six.text_type(e))
                return
            except InvalidScopeException as e:
                LOG.exception(six.text_type(e))
                abort(http_client.BAD_REQUEST, six.text_type(e))
                return

        extra["kvp_db"] = kvp_db
        LOG.audit("PUT /v1/keys/%s succeeded id=%s",
                  name,
                  kvp_db.id,
                  extra=extra)

        return KeyValuePairAPI.from_model(kvp_db)