Ejemplo n.º 1
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
Ejemplo n.º 2
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
Ejemplo n.º 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
Ejemplo n.º 4
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
Ejemplo n.º 5
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(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
Ejemplo n.º 6
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
Ejemplo n.º 7
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
        }
Ejemplo n.º 8
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}
Ejemplo n.º 9
0
Archivo: config.py Proyecto: zwunix/st2
def set_datastore_value_for_config_key(pack_name,
                                       key_name,
                                       value,
                                       secret=False,
                                       user=None):
    """
    Set config value in the datastore.

    This function takes care of correctly encoding the key name, serializing the
    value, etc.

    :param pack_name: Pack name.
    :type pack_name: ``str``

    :param key_name: Config key name.
    :type key_name: ``str``

    :param secret: True if this value is a secret.
    :type secret: ``bool``

    :param user: Optional username if working on a user-scoped config item.
    :type user: ``str``

    :rtype: :class:`KeyValuePairDB`
    """

    if user:
        scope = FULL_USER_SCOPE
    else:
        scope = FULL_SYSTEM_SCOPE

    name = get_key_reference(scope=scope, name=key_name, user=user)

    kvp_api = KeyValuePairAPI(name=name,
                              value=value,
                              scope=scope,
                              secret=secret)
    kvp_db = KeyValuePairAPI.to_model(kvp_api)

    # TODO: Obtain a lock
    try:
        existing_kvp_db = KeyValuePair.get_by_scope_and_name(scope=scope,
                                                             name=name)
    except StackStormDBObjectNotFoundError:
        existing_kvp_db = None

    if existing_kvp_db:
        kvp_db.id = existing_kvp_db.id

    kvp_db = KeyValuePair.add_or_update(kvp_db)
    return kvp_db
Ejemplo n.º 10
0
    def setUpClass(cls):
        super(ActionExecutionControllerTestCaseAuthEnabled, cls).setUpClass()
        cls.action = copy.deepcopy(ACTION_1)
        headers = {
            "content-type": "application/json",
            "X-Auth-Token": str(SYS_TOKEN.token),
        }
        post_resp = cls.app.post_json("/v1/actions",
                                      cls.action,
                                      headers=headers)
        cls.action["id"] = post_resp.json["id"]

        cls.action_encrypt = copy.deepcopy(ACTION_DEFAULT_ENCRYPT)
        post_resp = cls.app.post_json("/v1/actions",
                                      cls.action_encrypt,
                                      headers=headers)
        cls.action_encrypt["id"] = post_resp.json["id"]

        FixturesLoader().save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                             fixtures_dict=FIXTURES)

        # register datastore values which are used in this tests
        KeyValuePairAPI._setup_crypto()
        register_items = [
            {
                "name":
                "secret",
                "secret":
                True,
                "value":
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               "foo"),
            },
            {
                "name":
                "user1:secret",
                "secret":
                True,
                "scope":
                FULL_USER_SCOPE,
                "value":
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               "bar"),
            },
        ]
        cls.kvps = [
            KeyValuePair.add_or_update(KeyValuePairDB(**x))
            for x in register_items
        ]
Ejemplo n.º 11
0
    def setUpClass(cls):
        super(ActionExecutionControllerTestCaseAuthEnabled, cls).setUpClass()
        cls.action = copy.deepcopy(ACTION_1)
        headers = {
            'content-type': 'application/json',
            'X-Auth-Token': str(SYS_TOKEN.token)
        }
        post_resp = cls.app.post_json('/v1/actions',
                                      cls.action,
                                      headers=headers)
        cls.action['id'] = post_resp.json['id']

        cls.action_encrypt = copy.deepcopy(ACTION_DEFAULT_ENCRYPT)
        post_resp = cls.app.post_json('/v1/actions',
                                      cls.action_encrypt,
                                      headers=headers)
        cls.action_encrypt['id'] = post_resp.json['id']

        FixturesLoader().save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                             fixtures_dict=FIXTURES)

        # register datastore values which are used in this tests
        KeyValuePairAPI._setup_crypto()
        register_items = [
            {
                'name':
                'secret',
                'secret':
                True,
                'value':
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               'foo')
            },
            {
                'name':
                'user1:secret',
                'secret':
                True,
                'scope':
                FULL_USER_SCOPE,
                'value':
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               'bar')
            },
        ]
        cls.kvps = [
            KeyValuePair.add_or_update(KeyValuePairDB(**x))
            for x in register_items
        ]
Ejemplo n.º 12
0
    def delete(self, name, requester_user, scope=FULL_SYSTEM_SCOPE, user=None):
        """
        Delete the key value pair.

        Handles requests:
            DELETE /keys/1
        """
        if not scope:
            scope = FULL_SYSTEM_SCOPE

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

        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        user = user or requester_user.name

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

        key_ref = get_key_reference(scope=scope, name=name, user=user)
        lock_name = self._get_lock_name_for_key(name=key_ref, scope=scope)

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            from_model_kwargs = {"mask_secrets": True}
            kvp_api = self._get_one_by_scope_and_name(
                name=key_ref, scope=scope, from_model_kwargs=from_model_kwargs)

            kvp_db = KeyValuePairAPI.to_model(kvp_api)

            LOG.debug(
                "DELETE /keys/ lookup with scope=%s name=%s found object: %s",
                scope,
                name,
                kvp_db,
            )

            try:
                KeyValuePair.delete(kvp_db)
            except Exception as e:
                LOG.exception(
                    "Database delete encountered exception during "
                    'delete of name="%s". ',
                    name,
                )
                abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
                return

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

        return Response(status=http_client.NO_CONTENT)
Ejemplo n.º 13
0
Archivo: config.py Proyecto: Bala96/st2
def deserialize_key_value(value, secret=False):
    """
    Deserialize the datastore item value.

    Note: Right now only strings as supported so only thing this function does is it decrypts
    secret values.

    :param value: Value to deserialize.
    :type value: ``str``

    :param secret: True if a value is a secret and is encrypted.
    :type secret: ``bool``
    """
    if secret:
        KeyValuePairAPI._setup_crypto()
        value = symmetric_decrypt(KeyValuePairAPI.crypto_key, value)

    return value
Ejemplo n.º 14
0
def deserialize_key_value(value, secret=False):
    """
    Deserialize the datastore item value.

    Note: Right now only strings as supported so only thing this function does is it decrypts
    secret values.

    :param value: Value to deserialize.
    :type value: ``str``

    :param secret: True if a value is a secret and is encrypted.
    :type secret: ``bool``
    """
    if secret:
        KeyValuePairAPI._setup_crypto()
        value = symmetric_decrypt(KeyValuePairAPI.crypto_key, value)

    return value
Ejemplo n.º 15
0
    def delete(self, name, requester_user, scope=FULL_SYSTEM_SCOPE, user=None):
        """
            Delete the key value pair.

            Handles requests:
                DELETE /keys/1
        """
        if not scope:
            scope = FULL_SYSTEM_SCOPE

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

        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        user = user or requester_user.name

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

        key_ref = get_key_reference(scope=scope, name=name, user=user)
        lock_name = self._get_lock_name_for_key(name=key_ref, scope=scope)

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            from_model_kwargs = {'mask_secrets': True}
            kvp_api = self._get_one_by_scope_and_name(
                name=key_ref,
                scope=scope,
                from_model_kwargs=from_model_kwargs
            )

            kvp_db = KeyValuePairAPI.to_model(kvp_api)

            LOG.debug('DELETE /keys/ lookup with scope=%s name=%s found object: %s',
                      scope, name, kvp_db)

            try:
                KeyValuePair.delete(kvp_db)
            except Exception as e:
                LOG.exception('Database delete encountered exception during '
                              'delete of name="%s". ', name)
                abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
                return

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

        return Response(status=http_client.NO_CONTENT)
Ejemplo n.º 16
0
    def setUpClass(cls):
        super(ActionExecutionControllerTestCaseAuthEnabled, cls).setUpClass()
        cls.action = copy.deepcopy(ACTION_1)
        headers = {'content-type': 'application/json', 'X-Auth-Token': str(SYS_TOKEN.token)}
        post_resp = cls.app.post_json('/v1/actions', cls.action, headers=headers)
        cls.action['id'] = post_resp.json['id']

        cls.action_encrypt = copy.deepcopy(ACTION_DEFAULT_ENCRYPT)
        post_resp = cls.app.post_json('/v1/actions', cls.action_encrypt, headers=headers)
        cls.action_encrypt['id'] = post_resp.json['id']

        FixturesLoader().save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                             fixtures_dict=FIXTURES)

        # register datastore values which are used in this tests
        KeyValuePairAPI._setup_crypto()
        register_items = [
            {'name': 'secret', 'secret': True,
             'value': crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key, 'foo')},
            {'name': 'user1:secret', 'secret': True, 'scope': FULL_USER_SCOPE,
             'value': crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key, 'bar')},
        ]
        cls.kvps = [KeyValuePair.add_or_update(KeyValuePairDB(**x)) for x in register_items]
Ejemplo n.º 17
0
    def delete(self, name, scope=FULL_SYSTEM_SCOPE, user=None):
        """
            Delete the key value pair.

            Handles requests:
                DELETE /keys/1
        """
        if not scope:
            scope = FULL_SYSTEM_SCOPE

        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        requester_user = get_requester()
        user = 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)

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            from_model_kwargs = {'mask_secrets': True}
            kvp_api = self._get_one_by_scope_and_name(
                name=key_ref,
                scope=scope,
                from_model_kwargs=from_model_kwargs
            )

            kvp_db = KeyValuePairAPI.to_model(kvp_api)

            LOG.debug('DELETE /keys/ lookup with scope=%s name=%s found object: %s',
                      scope, name, kvp_db)

            try:
                KeyValuePair.delete(kvp_db)
            except Exception as e:
                LOG.exception('Database delete encountered exception during '
                              'delete of name="%s". ', name)
                abort(http_client.INTERNAL_SERVER_ERROR, str(e))
                return

        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair deleted. KeyValuePair.id=%s' % (kvp_db.id), extra=extra)
Ejemplo n.º 18
0
    def delete(self, name, scope=FULL_SYSTEM_SCOPE, user=None):
        """
            Delete the key value pair.

            Handles requests:
                DELETE /keys/1
        """
        if not scope:
            scope = FULL_SYSTEM_SCOPE

        scope = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        requester_user = get_requester()
        user = 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)

        # Note: We use lock to avoid a race
        with self._coordinator.get_lock(lock_name):
            from_model_kwargs = {'mask_secrets': True}
            kvp_api = self._get_one_by_scope_and_name(
                name=key_ref, scope=scope, from_model_kwargs=from_model_kwargs)

            kvp_db = KeyValuePairAPI.to_model(kvp_api)

            LOG.debug(
                'DELETE /keys/ lookup with scope=%s name=%s found object: %s',
                scope, name, kvp_db)

            try:
                KeyValuePair.delete(kvp_db)
            except Exception as e:
                LOG.exception(
                    'Database delete encountered exception during '
                    'delete of name="%s". ', name)
                abort(http_client.INTERNAL_SERVER_ERROR, str(e))
                return

        extra = {'kvp_db': kvp_db}
        LOG.audit('KeyValuePair deleted. KeyValuePair.id=%s' % (kvp_db.id),
                  extra=extra)
Ejemplo n.º 19
0
    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
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
Archivo: config.py Proyecto: Bala96/st2
def set_datastore_value_for_config_key(pack_name, key_name, value, secret=False, user=None):
    """
    Set config value in the datastore.

    This function takes care of correctly encoding the key name, serializing the
    value, etc.

    :param pack_name: Pack name.
    :type pack_name: ``str``

    :param key_name: Config key name.
    :type key_name: ``str``

    :param secret: True if this value is a secret.
    :type secret: ``bool``

    :param user: Optional username if working on a user-scoped config item.
    :type user: ``str``

    :rtype: :class:`KeyValuePairDB`
    """

    if user:
        scope = USER_SCOPE
    else:
        scope = SYSTEM_SCOPE

    name = get_key_reference(scope=scope, name=key_name, user=user)

    kvp_api = KeyValuePairAPI(name=name, value=value, scope=scope, secret=secret)
    kvp_db = KeyValuePairAPI.to_model(kvp_api)

    # TODO: Obtain a lock
    existing_kvp_db = KeyValuePair.get_by_scope_and_name(scope=scope, name=name)
    if existing_kvp_db:
        kvp_db.id = existing_kvp_db.id

    kvp_db = KeyValuePair.add_or_update(kvp_db)
    return kvp_db
Ejemplo n.º 22
0
    def delete(self, name, requester_user, scope=None, user=None):
        """
        Delete the key value pair.

        Handles requests:
            DELETE /keys/1
        """
        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 = get_datastore_full_scope(scope)
        self._validate_scope(scope=scope)

        user = user 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("DELETE /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 delete 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_DELETE,
        )

        # 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)):
            from_model_kwargs = {"mask_secrets": True}
            kvp_api = self._get_one_by_scope_and_name(
                name=key_ref, scope=scope, from_model_kwargs=from_model_kwargs)
            kvp_db = KeyValuePairAPI.to_model(kvp_api)

            extra["kvp_db"] = kvp_db
            LOG.debug("DELETE /v1/keys/%s", name, extra=extra)

            try:
                KeyValuePair.delete(kvp_db)
            except Exception as e:
                LOG.exception(
                    "Database delete encountered exception during "
                    'delete of name="%s". ',
                    name,
                )
                abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
                return

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

        return Response(status=http_client.NO_CONTENT)
Ejemplo n.º 23
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}
Ejemplo n.º 24
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
Ejemplo n.º 25
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)