Ejemplo n.º 1
0
    def setUpClass(cls):
        super(ExecutionCancellationTestCase, cls).setUpClass()
        for _, fixture in six.iteritems(FIXTURES['actions']):
            instance = ActionAPI(**fixture)
            Action.add_or_update(ActionAPI.to_model(instance))

        runners_registrar.register_runners()
Ejemplo n.º 2
0
    def setup_action_models(cls):
        action_db = ActionDB()
        action_db.name = 'action-1'
        action_db.description = 'awesomeness'
        action_db.enabled = True
        action_db.pack = 'wolfpack'
        action_db.entry_point = ''
        action_db.runner_type = {'name': 'test-runner'}
        action_db.parameters = {
            'actionstr': {'type': 'string', 'required': True},
            'actionint': {'type': 'number', 'default': 10},
            'runnerdummy': {'type': 'string', 'default': 'actiondummy'},
            'runnerimmutable': {'type': 'string', 'default': 'failed_override'},
            'actionimmutable': {'type': 'string', 'default': 'actionimmutable', 'immutable': True}
        }
        RunnerContainerTest.action_db = Action.add_or_update(action_db)

        action_db = ActionDB()
        action_db.name = 'action-2'
        action_db.description = 'awesomeness'
        action_db.enabled = True
        action_db.pack = 'wolfpack'
        action_db.entry_point = ''
        action_db.runner_type = {'name': 'test-failingrunner'}
        action_db.parameters = {}
        RunnerContainerTest.failingaction_db = Action.add_or_update(action_db)
Ejemplo n.º 3
0
    def test_parameter_schema(self):
        runnertype = self._create_save_runnertype(metadata=True)
        saved = self._create_save_action(runnertype, metadata=True)
        retrieved = Action.get_by_id(saved.id)

        # validate generated schema
        schema = util_schema.get_schema_for_action_parameters(retrieved)
        self.assertDictEqual(schema, PARAM_SCHEMA)
        validator = util_schema.get_validator()
        validator.check_schema(schema)

        # use schema to validate parameters
        jsonschema.validate({"r2": "abc", "p1": "def"}, schema, validator)
        jsonschema.validate({"r2": "abc", "p1": "def", "r1": {"r1a": "ghi"}}, schema, validator)
        self.assertRaises(jsonschema.ValidationError, jsonschema.validate,
                          '{"r2": "abc", "p1": "def"}', schema, validator)
        self.assertRaises(jsonschema.ValidationError, jsonschema.validate,
                          {"r2": "abc"}, schema, validator)
        self.assertRaises(jsonschema.ValidationError, jsonschema.validate,
                          {"r2": "abc", "p1": "def", "r1": 123}, schema, validator)

        # cleanup
        self._delete([retrieved])
        try:
            retrieved = Action.get_by_id(saved.id)
        except ValueError:
            retrieved = None
        self.assertIsNone(retrieved, 'managed to retrieve after failure.')
Ejemplo n.º 4
0
    def _register_action(self, pack, action):
        with open(action, 'r') as fd:
            try:
                content = json.load(fd)
            except ValueError:
                LOG.exception('Failed loading action json from %s.', action)
                raise

            try:
                model = Action.get_by_name(str(content['name']))
            except ValueError:
                model = ActionDB()
            model.name = content['name']
            model.description = content['description']
            model.enabled = content['enabled']
            model.pack = pack
            model.entry_point = content['entry_point']
            model.parameters = content.get('parameters', {})
            runner_type = str(content['runner_type'])
            valid_runner_type, runner_type_db = self._has_valid_runner_type(runner_type)
            if valid_runner_type:
                model.runner_type = {'name': runner_type_db.name}
            else:
                LOG.exception('Runner type %s doesn\'t exist.')
                raise

            try:
                model = Action.add_or_update(model)
                LOG.audit('Action created. Action %s from %s.', model, action)
            except Exception:
                LOG.exception('Failed to write action to db %s.', model.name)
                raise
Ejemplo n.º 5
0
    def delete(self, action_ref_or_id):
        """
            Delete an action.

            Handles requests:
                POST /actions/1?_method=delete
                DELETE /actions/1
                DELETE /actions/mypack.myaction
        """
        action_db = self._get_by_ref_or_id(ref_or_id=action_ref_or_id)
        action_id = action_db.id

        try:
            validate_not_part_of_system_pack(action_db)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, str(e))

        LOG.debug('DELETE /actions/ lookup with ref_or_id=%s found object: %s',
                  action_ref_or_id, action_db)

        try:
            Action.delete(action_db)
        except Exception as e:
            LOG.error('Database delete encountered exception during delete of id="%s". '
                      'Exception was %s', action_id, e)
            abort(http_client.INTERNAL_SERVER_ERROR, str(e))
            return

        extra = {'action_db': action_db}
        LOG.audit('Action deleted. Action.id=%s' % (action_db.id), extra=extra)
        return None
Ejemplo n.º 6
0
    def setUpClass(cls):
        super(TestMistralRunner, cls).setUpClass()
        runners_registrar.register_runner_types()

        for _, fixture in six.iteritems(FIXTURES['actions']):
            instance = ActionAPI(**fixture)
            Action.add_or_update(ActionAPI.to_model(instance))
Ejemplo n.º 7
0
    def test_action_with_notify_crud(self):
        runnertype = self._create_save_runnertype(metadata=False)
        saved = self._create_save_action(runnertype, metadata=False)

        # Update action with notification settings
        on_complete = NotificationSubSchema(message='Action complete.')
        saved.notify = NotificationSchema(on_complete=on_complete)
        saved = Action.add_or_update(saved)

        # Check if notification settings were set correctly.
        retrieved = Action.get_by_id(saved.id)
        self.assertEqual(retrieved.notify.on_complete.message, on_complete.message)

        # Now reset notify in action to empty and validate it's gone.
        retrieved.notify = NotificationSchema(on_complete=None)
        saved = Action.add_or_update(retrieved)
        retrieved = Action.get_by_id(saved.id)
        self.assertEqual(retrieved.notify.on_complete, None)

        # cleanup
        self._delete([retrieved])
        try:
            retrieved = Action.get_by_id(saved.id)
        except ValueError:
            retrieved = None
        self.assertIsNone(retrieved, 'managed to retrieve after failure.')
Ejemplo n.º 8
0
    def tearDownClass(cls):
        for actiondb in cls.actiondbs.values():
            Action.delete(actiondb)

        RunnerType.delete(cls.runnerdb)

        super(TestActionExecutionService, cls).tearDownClass()
Ejemplo n.º 9
0
    def setUpClass(cls):
        super(TestStreamController, cls).setUpClass()

        instance = RunnerTypeAPI(**RUNNER_TYPE_1)
        RunnerType.add_or_update(RunnerTypeAPI.to_model(instance))

        instance = ActionAPI(**ACTION_1)
        Action.add_or_update(ActionAPI.to_model(instance))
Ejemplo n.º 10
0
 def setUp(self):
     RUNNER_TYPE.id = None
     RunnerType.add_or_update(RUNNER_TYPE)
     ACTION.id = None
     ACTION.runner_type = {'name': RUNNER_TYPE.name}
     Action.add_or_update(ACTION)
     TRIGGER.id = None
     Trigger.add_or_update(TRIGGER)
Ejemplo n.º 11
0
 def setUpClass(cls):
     super(TestActionExecutionHistoryWorker, cls).setUpClass()
     runners_registrar.register_runner_types()
     action_local = ActionAPI(**copy.deepcopy(fixture.ARTIFACTS['actions']['local']))
     Action.add_or_update(ActionAPI.to_model(action_local))
     action_chain = ActionAPI(**copy.deepcopy(fixture.ARTIFACTS['actions']['chain']))
     action_chain.entry_point = fixture.PATH + '/chain.yaml'
     Action.add_or_update(ActionAPI.to_model(action_chain))
Ejemplo n.º 12
0
 def test_request_disabled_action(self):
     self.actiondb.enabled = False
     Action.add_or_update(self.actiondb)
     parameters = {'hosts': 'localhost', 'cmd': 'uname -a'}
     execution = LiveActionDB(action=ACTION_REF, parameters=parameters)
     self.assertRaises(ValueError, action_service.request, execution)
     self.actiondb.enabled = True
     Action.add_or_update(self.actiondb)
Ejemplo n.º 13
0
 def setUpClass(cls):
     super(TestMistralRunner, cls).setUpClass()
     runners_registrar.register_runner_types()
     metadata = fixture.ARTIFACTS['metadata']
     action_local = ActionAPI(**copy.deepcopy(metadata['actions']['local']))
     Action.add_or_update(ActionAPI.to_model(action_local))
     action_wkflow = ActionAPI(**copy.deepcopy(metadata['actions']['workflow-v2']))
     Action.add_or_update(ActionAPI.to_model(action_wkflow))
Ejemplo n.º 14
0
 def setUpClass(cls):
     super(TestActionExecutionHistoryWorker, cls).setUpClass()
     runners_registrar.register_runners()
     action_local = ActionAPI(**copy.deepcopy(fixture.ARTIFACTS["actions"]["local"]))
     Action.add_or_update(ActionAPI.to_model(action_local))
     action_chain = ActionAPI(**copy.deepcopy(fixture.ARTIFACTS["actions"]["chain"]))
     action_chain.entry_point = fixture.PATH + "/chain.yaml"
     Action.add_or_update(ActionAPI.to_model(action_chain))
Ejemplo n.º 15
0
 def test_register_all_actions(self):
     try:
         packs_base_path = os.path.join(tests_base.get_fixtures_path())
         all_actions_in_db = Action.get_all()
         actions_registrar.register_actions(packs_base_path=packs_base_path)
         all_actions_in_db = Action.get_all()
         self.assertTrue(len(all_actions_in_db) > 0)
     except Exception as e:
         print(str(e))
         self.fail('All actions must be registered without exceptions.')
Ejemplo n.º 16
0
    def setUpClass(cls):
        super(MistralValidationControllerTest, cls).setUpClass()

        for _, fixture in six.iteritems(FIXTURES['runners']):
            instance = RunnerTypeAPI(**fixture)
            RunnerType.add_or_update(RunnerTypeAPI.to_model(instance))

        for _, fixture in six.iteritems(FIXTURES['actions']):
            instance = ActionAPI(**fixture)
            Action.add_or_update(ActionAPI.to_model(instance))
    def setUpClass(cls):
        super(DSLTransformTestCase, cls).setUpClass()

        for _, fixture in six.iteritems(FIXTURES['runners']):
            instance = RunnerTypeAPI(**fixture)
            RunnerType.add_or_update(RunnerTypeAPI.to_model(instance))

        for _, fixture in six.iteritems(FIXTURES['actions']):
            instance = ActionAPI(**fixture)
            Action.add_or_update(ActionAPI.to_model(instance))
Ejemplo n.º 18
0
 def test_register_all_actions(self):
     try:
         packs_base_path = fixtures_loader.get_fixtures_base_path()
         all_actions_in_db = Action.get_all()
         actions_registrar.register_actions(packs_base_paths=[packs_base_path])
     except Exception as e:
         print(str(e))
         self.fail('All actions must be registered without exceptions.')
     else:
         all_actions_in_db = Action.get_all()
         self.assertTrue(len(all_actions_in_db) > 0)
Ejemplo n.º 19
0
    def setUpClass(cls):
        super(MistralValidationTest, cls).setUpClass()

        for _, fixture in six.iteritems(FIXTURES["runners"]):
            instance = RunnerTypeAPI(**fixture)
            RunnerType.add_or_update(RunnerTypeAPI.to_model(instance))

        for _, fixture in six.iteritems(FIXTURES["actions"]):
            instance = ActionAPI(**fixture)
            Action.add_or_update(ActionAPI.to_model(instance))

        cls.validator = wf_validation_utils.get_validator()
Ejemplo n.º 20
0
    def test_run(self):
        pack = 'dummy_pack_1'
        # Verify all the resources are there

        pack_dbs = Pack.query(ref=pack)
        action_dbs = Action.query(pack=pack)
        alias_dbs = ActionAlias.query(pack=pack)
        rule_dbs = Rule.query(pack=pack)
        sensor_dbs = Sensor.query(pack=pack)
        trigger_type_dbs = TriggerType.query(pack=pack)
        policy_dbs = Policy.query(pack=pack)

        config_schema_dbs = ConfigSchema.query(pack=pack)
        config_dbs = Config.query(pack=pack)

        self.assertEqual(len(pack_dbs), 1)
        self.assertEqual(len(action_dbs), 1)
        self.assertEqual(len(alias_dbs), 2)
        self.assertEqual(len(rule_dbs), 1)
        self.assertEqual(len(sensor_dbs), 3)
        self.assertEqual(len(trigger_type_dbs), 4)
        self.assertEqual(len(policy_dbs), 2)

        self.assertEqual(len(config_schema_dbs), 1)
        self.assertEqual(len(config_dbs), 1)

        # Run action
        action = self.get_action_instance()
        action.run(packs=[pack])

        # Make sure all resources have been removed from the db
        pack_dbs = Pack.query(ref=pack)
        action_dbs = Action.query(pack=pack)
        alias_dbs = ActionAlias.query(pack=pack)
        rule_dbs = Rule.query(pack=pack)
        sensor_dbs = Sensor.query(pack=pack)
        trigger_type_dbs = TriggerType.query(pack=pack)
        policy_dbs = Policy.query(pack=pack)

        config_schema_dbs = ConfigSchema.query(pack=pack)
        config_dbs = Config.query(pack=pack)

        self.assertEqual(len(pack_dbs), 0)
        self.assertEqual(len(action_dbs), 0)
        self.assertEqual(len(alias_dbs), 0)
        self.assertEqual(len(rule_dbs), 0)
        self.assertEqual(len(sensor_dbs), 0)
        self.assertEqual(len(trigger_type_dbs), 0)
        self.assertEqual(len(policy_dbs), 0)

        self.assertEqual(len(config_schema_dbs), 0)
        self.assertEqual(len(config_dbs), 0)
    def setUpClass(cls):
        super(DSLTransformTestCase, cls).setUpClass()
        runners_registrar.register_runner_types()

        action_local = ActionAPI(**copy.deepcopy(FIXTURES['actions']['local.yaml']))
        Action.add_or_update(ActionAPI.to_model(action_local))

        for action_name in ['action1', 'action2', 'action3']:
            metadata = copy.deepcopy(FIXTURES['actions']['local.yaml'])
            metadata['name'] = action_name
            metadata['pack'] = 'demo'
            action = ActionAPI(**metadata)
            Action.add_or_update(ActionAPI.to_model(action))
Ejemplo n.º 22
0
 def test_pack_name_missing(self):
     registrar = actions_registrar.ActionsRegistrar()
     action_file = os.path.join(tests_base.get_fixtures_path(),
                                'wolfpack/actions/action_3_pack_missing.json')
     registrar._register_action('dummy', action_file)
     action_name = None
     with open(action_file, 'r') as fd:
         content = json.load(fd)
         action_name = str(content['name'])
         action_db = Action.get_by_name(action_name)
         self.assertEqual(action_db.pack, 'dummy', 'Content pack must be ' +
                          'set to dummy')
         Action.delete(action_db)
Ejemplo n.º 23
0
    def test_request_disabled_action(self):
        actiondb = self.actiondbs[ACTION['name']]
        actiondb.enabled = False
        Action.add_or_update(actiondb)

        try:
            parameters = {'hosts': 'localhost', 'cmd': 'uname -a'}
            execution = LiveActionDB(action=ACTION_REF, parameters=parameters)
            self.assertRaises(ValueError, action_service.request, execution)
        except Exception as e:
            raise e
        finally:
            actiondb.enabled = True
            Action.add_or_update(actiondb)
Ejemplo n.º 24
0
 def test_pack_name_missing(self):
     registrar = actions_registrar.ActionsRegistrar()
     loader = fixtures_loader.FixturesLoader()
     action_file = loader.get_fixture_file_path_abs(
         'generic', 'actions', 'action_3_pack_missing.yaml')
     registrar._register_action('dummy', action_file)
     action_name = None
     with open(action_file, 'r') as fd:
         content = yaml.safe_load(fd)
         action_name = str(content['name'])
         action_db = Action.get_by_name(action_name)
         self.assertEqual(action_db.pack, 'dummy', 'Content pack must be ' +
                          'set to dummy')
         Action.delete(action_db)
Ejemplo n.º 25
0
    def test_register_all_actions(self):
        try:
            packs_base_path = fixtures_loader.get_fixtures_base_path()
            all_actions_in_db = Action.get_all()
            actions_registrar.register_actions(packs_base_paths=[packs_base_path])
        except Exception as e:
            print(six.text_type(e))
            self.fail('All actions must be registered without exceptions.')
        else:
            all_actions_in_db = Action.get_all()
            self.assertTrue(len(all_actions_in_db) > 0)

        # Assert metadata_file field is populated
        expected_path = 'actions/action-with-no-parameters.yaml'
        self.assertEqual(all_actions_in_db[0].metadata_file, expected_path)
Ejemplo n.º 26
0
    def post(self, action):
        """
            Create a new action.

            Handles requests:
                POST /actions/
        """
        # Perform validation
        validate_not_part_of_system_pack(action)
        action_validator.validate_action(action)

        # Write pack data files to disk (if any are provided)
        data_files = getattr(action, 'data_files', [])
        written_data_files = []
        if data_files:
            written_data_files = self._handle_data_files(pack_name=action.pack,
                                                         data_files=data_files)

        action_model = ActionAPI.to_model(action)

        LOG.debug('/actions/ POST verified ActionAPI object=%s', action)
        action_db = Action.add_or_update(action_model)
        LOG.debug('/actions/ POST saved ActionDB object=%s', action_db)

        # Dispatch an internal trigger for each written data file. This way user
        # automate comitting this files to git using StackStorm rule
        if written_data_files:
            self._dispatch_trigger_for_written_data_files(action_db=action_db,
                                                          written_data_files=written_data_files)

        extra = {'acion_db': action_db}
        LOG.audit('Action created. Action.id=%s' % (action_db.id), extra=extra)
        action_api = ActionAPI.from_model(action_db)

        return action_api
Ejemplo n.º 27
0
 def setUpClass(cls):
     super(TestActionExecutionService, cls).setUpClass()
     cls.runner = RunnerTypeAPI(**RUNNER)
     cls.runnerdb = RunnerType.add_or_update(RunnerTypeAPI.to_model(cls.runner))
     cls.action = ActionAPI(**ACTION)
     cls.actiondb = Action.add_or_update(ActionAPI.to_model(cls.action))
     cls.container = RunnerContainer()
Ejemplo n.º 28
0
    def post(self, action):
        """
            Create a new action.

            Handles requests:
                POST /actions/
        """
        if not hasattr(action, 'pack'):
            setattr(action, 'pack', DEFAULT_PACK_NAME)

        try:
            action_validator.validate_action(action)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, str(e))
            return

        # ActionsController._validate_action_parameters(action, runnertype_db)
        action_model = ActionAPI.to_model(action)

        LOG.debug('/actions/ POST verified ActionAPI object=%s', action)
        action_db = Action.add_or_update(action_model)
        LOG.debug('/actions/ POST saved ActionDB object=%s', action_db)

        extra = {'action_db': action_db}
        LOG.audit('Action created. Action.id=%s' % (action_db.id), extra=extra)
        action_api = ActionAPI.from_model(action_db)

        return action_api
Ejemplo n.º 29
0
    def _register_action(self, pack, action):
        content = self._meta_loader.load(action)
        action_ref = ResourceReference(pack=pack, name=str(content['name']))
        model = action_utils.get_action_by_ref(action_ref)
        if not model:
            model = ActionDB()
        model.name = content['name']
        model.description = content['description']
        model.enabled = content['enabled']
        model.pack = pack
        model.entry_point = content['entry_point']
        model.parameters = content.get('parameters', {})
        runner_type = str(content['runner_type'])
        valid_runner_type, runner_type_db = self._has_valid_runner_type(runner_type)
        if valid_runner_type:
            model.runner_type = {'name': runner_type_db.name}
        else:
            LOG.exception('Runner type %s doesn\'t exist.', runner_type)
            raise

        try:
            model = Action.add_or_update(model)
            LOG.audit('Action created. Action %s from %s.', model, action)
        except Exception:
            LOG.exception('Failed to write action to db %s.', model.name)
            raise
Ejemplo n.º 30
0
 def test_action_update(self):
     registrar = actions_registrar.ActionsRegistrar()
     loader = fixtures_loader.FixturesLoader()
     action_file = loader.get_fixture_file_path_abs(
         'generic', 'actions', 'action1.yaml')
     registrar._register_action('wolfpack', action_file)
     # try registering again. this should not throw errors.
     registrar._register_action('wolfpack', action_file)
     action_name = None
     with open(action_file, 'r') as fd:
         content = yaml.safe_load(fd)
         action_name = str(content['name'])
         action_db = Action.get_by_name(action_name)
         self.assertEqual(action_db.pack, 'wolfpack', 'Content pack must be ' +
                          'set to wolfpack')
         Action.delete(action_db)
Ejemplo n.º 31
0
    def post(self, action):
        """
            Create a new action.

            Handles requests:
                POST /actions/
        """

        try:
            # Perform validation
            validate_not_part_of_system_pack(action)
            action_validator.validate_action(action)
        except (ValidationError, ValueError, ValueValidationException,
                InvalidActionParameterException) as e:
            LOG.exception('Unable to create action data=%s', action)
            abort(http_client.BAD_REQUEST, str(e))
            return

        # Write pack data files to disk (if any are provided)
        data_files = getattr(action, 'data_files', [])
        written_data_files = []
        if data_files:
            written_data_files = self._handle_data_files(pack_name=action.pack,
                                                         data_files=data_files)

        action_model = ActionAPI.to_model(action)

        LOG.debug('/actions/ POST verified ActionAPI object=%s', action)
        action_db = Action.add_or_update(action_model)
        LOG.debug('/actions/ POST saved ActionDB object=%s', action_db)

        # Dispatch an internal trigger for each written data file. This way user
        # automate comitting this files to git using StackStorm rule
        if written_data_files:
            self._dispatch_trigger_for_written_data_files(
                action_db=action_db, written_data_files=written_data_files)

        extra = {'acion_db': action_db}
        LOG.audit('Action created. Action.id=%s' % (action_db.id), extra=extra)
        action_api = ActionAPI.from_model(action_db)

        return action_api
Ejemplo n.º 32
0
    def test_post_duplicate(self):
        action_ids = []

        post_resp = self.__do_post(ACTION_1)
        self.assertEqual(post_resp.status_int, 201)
        action_in_db = Action.get_by_name(ACTION_1.get('name'))
        self.assertTrue(action_in_db is not None, 'Action must be in db.')
        action_ids.append(self.__get_action_id(post_resp))

        post_resp = self.__do_post(ACTION_1, expect_errors=True)
        # Verify name conflict
        self.assertEqual(post_resp.status_int, 409)

        post_resp = self.__do_post(ACTION_10)
        action_ids.append(self.__get_action_id(post_resp))
        # Verify action with same name but different pack is written.
        self.assertEqual(post_resp.status_int, 201)

        for i in action_ids:
            self.__do_delete(i)
Ejemplo n.º 33
0
    def _create_save_action(runnertype, metadata=False):
        name = "action-1"
        pack = "wolfpack"
        ref = ResourceReference(pack=pack, name=name).ref
        created = ActionDB(
            name=name,
            description="awesomeness",
            enabled=True,
            entry_point="/tmp/action.py",
            pack=pack,
            ref=ref,
            runner_type={"name": runnertype.name},
        )

        if not metadata:
            created.parameters = {
                "p1": None,
                "p2": None,
                "p3": None,
                "p4": None
            }
        else:
            created.parameters = {
                "p1": {
                    "type": "string",
                    "required": True
                },
                "p2": {
                    "type": "number",
                    "default": 2868
                },
                "p3": {
                    "type": "boolean",
                    "default": False
                },
                "p4": {
                    "type": "string",
                    "secret": True
                },
            }
        return Action.add_or_update(created)
Ejemplo n.º 34
0
    def put(self, action_ref_or_id, action):
        action_db = self._get_by_ref_or_id(ref_or_id=action_ref_or_id)

        # Assert permissions
        action_id = action_db.id

        if not getattr(action, 'pack', None):
            action.pack = action_db.pack

        # Perform validation
        validate_not_part_of_system_pack(action)
        action_validator.validate_action(action)

        # Write pack data files to disk (if any are provided)
        data_files = getattr(action, 'data_files', [])
        written_data_files = []
        if data_files:
            written_data_files = self._handle_data_files(pack_name=action.pack,
                                                         data_files=data_files)

        try:
            action_db = ActionAPI.to_model(action)
            LOG.debug('/actions/ PUT incoming action: %s', action_db)
            action_db.id = action_id
            action_db = Action.add_or_update(action_db)
            LOG.debug('/actions/ PUT after add_or_update: %s', action_db)
        except (ValidationError, ValueError) as e:
            LOG.exception('Unable to update action data=%s', action)
            abort(http_client.BAD_REQUEST, str(e))
            return

        # Dispatch an internal trigger for each written data file. This way user
        # automate comitting this files to git using StackStorm rule
        if written_data_files:
            self._dispatch_trigger_for_written_data_files(
                action_db=action_db, written_data_files=written_data_files)

        action_api = ActionAPI.from_model(action_db)
        LOG.debug('PUT /actions/ client_result=%s', action_api)

        return action_api
Ejemplo n.º 35
0
    def setup_action_models(cls):
        pack = 'wolfpack'
        name = 'action-1'
        parameters = {
            'actionstr': {
                'type': 'string',
                'position': 1,
                'required': True
            },
            'actionint': {
                'type': 'number',
                'default': 10,
                'position': 0
            },
            'runnerdummy': {
                'type': 'string',
                'default': 'actiondummy'
            }
        }
        action_db = ActionDB(pack=pack,
                             name=name,
                             description='awesomeness',
                             enabled=True,
                             ref=ResourceReference(name=name, pack=pack).ref,
                             entry_point='',
                             runner_type={'name': 'test-runner'},
                             parameters=parameters)
        ActionDBUtilsTestCase.action_db = Action.add_or_update(action_db)

        liveaction_db = LiveActionDB()
        liveaction_db.status = 'initializing'
        liveaction_db.start_timestamp = get_datetime_utc_now()
        liveaction_db.action = ActionDBUtilsTestCase.action_db.ref
        params = {
            'actionstr': 'foo',
            'some_key_that_aint_exist_in_action_or_runner': 'bar',
            'runnerint': 555
        }
        liveaction_db.parameters = params
        ActionDBUtilsTestCase.liveaction_db = LiveAction.add_or_update(
            liveaction_db)
Ejemplo n.º 36
0
    def test_uid_is_populated_on_save(self):
        pack_1_db = PackDB(ref='test_pack',
                           name='test',
                           description='foo',
                           version='1.0.0',
                           author='dev',
                           email='*****@*****.**')
        pack_1_db = Pack.add_or_update(pack_1_db)
        pack_1_db.reload()

        self.assertEqual(pack_1_db.uid, 'pack:test_pack')

        action_1_db = ActionDB(name='local',
                               pack='core',
                               ref='core.local',
                               entry_point='',
                               runner_type={'name': 'local-shell-cmd'})
        action_1_db = Action.add_or_update(action_1_db)
        action_1_db.reload()

        self.assertEqual(action_1_db.uid, 'action:core:local')
Ejemplo n.º 37
0
def get_action_by_id(action_id):
    """
    Get Action by id.

    On error, raise StackStormDBObjectNotFoundError
    """
    action = None

    try:
        action = Action.get_by_id(action_id)
    except (ValueError, ValidationError) as e:
        LOG.warning(
            'Database lookup for action with id="%s" resulted in ' "exception: %s",
            action_id,
            e,
        )
        raise StackStormDBObjectNotFoundError(
            "Unable to find action with " 'id="%s"' % action_id
        )

    return action
Ejemplo n.º 38
0
    def setup_action_models(cls):
        action_db = ActionDB()
        action_db.name = 'action-1'
        action_db.description = 'awesomeness'
        action_db.enabled = True
        action_db.pack = 'wolfpack'
        action_db.entry_point = ''
        action_db.runner_type = {'name': 'test-runner'}
        action_db.parameters = {
            'actionstr': {
                'type': 'string',
                'position': 1,
                'required': True
            },
            'actionint': {
                'type': 'number',
                'default': 10,
                'position': 0
            },
            'runnerdummy': {
                'type': 'string',
                'default': 'actiondummy'
            }
        }
        ActionDBUtilsTestCase.action_db = Action.add_or_update(action_db)

        actionexec_db = ActionExecutionDB()
        actionexec_db.status = 'initializing'
        actionexec_db.start_timestamp = datetime.datetime.utcnow()
        actionexec_db.action = ResourceReference(
            name=ActionDBUtilsTestCase.action_db.name,
            pack=ActionDBUtilsTestCase.action_db.pack).ref
        params = {
            'actionstr': 'foo',
            'some_key_that_aint_exist_in_action_or_runner': 'bar',
            'runnerint': 555
        }
        actionexec_db.parameters = params
        ActionDBUtilsTestCase.actionexec_db = ActionExecution.add_or_update(
            actionexec_db)
Ejemplo n.º 39
0
Archivo: utils.py Proyecto: miqui/st2
def _transform_action(spec, action_key, input_key):

    if action_key not in spec or spec.get(action_key) == 'st2.action':
        return

    if spec.get(action_key) == 'st2.callback':
        raise Exception('st2.callback is deprecated.')

    # Convert parameters that are inline (i.e. action: some_action var1={$.value1} var2={$.value2})
    # and split it to action name and input dict as illustrated below.
    #
    # action: some_action
    # input:
    #   var1: $.value1
    #   var2: $.value2
    #
    # This step to separate the action name and the input parameters is required
    # to wrap them with the st2.action proxy.
    #
    # action: st2.action
    # input:
    #   ref: some_action
    #   parameters:
    #     var1: $.value1
    #     var2: $.value2
    _eval_inline_params(spec, action_key, input_key)

    action_ref = spec.get(action_key)

    if ResourceReference.is_resource_reference(action_ref):
        ref = ResourceReference.from_string_reference(ref=action_ref)
        actions = Action.query(name=ref.name, pack=ref.pack)
        action = actions.first() if actions else None
    else:
        action = None

    if action:
        spec[action_key] = 'st2.action'
        spec[input_key] = {'ref': action_ref, 'parameters': spec[input_key]}
Ejemplo n.º 40
0
    def setUpClass(cls):
        super(TestActionExecutionService, cls).setUpClass()
        cls.runner = RunnerTypeAPI(**RUNNER)
        cls.runnerdb = RunnerType.add_or_update(RunnerTypeAPI.to_model(cls.runner))

        runner_api = RunnerTypeAPI(**RUNNER_ACTION_CHAIN)
        RunnerType.add_or_update(RunnerTypeAPI.to_model(runner_api))

        cls.actions = {
            ACTION['name']: ActionAPI(**ACTION),
            ACTION_WORKFLOW['name']: ActionAPI(**ACTION_WORKFLOW),
            ACTION_OVR_PARAM['name']: ActionAPI(**ACTION_OVR_PARAM),
            ACTION_OVR_PARAM_MUTABLE['name']: ActionAPI(**ACTION_OVR_PARAM_MUTABLE),
            ACTION_OVR_PARAM_IMMUTABLE['name']: ActionAPI(**ACTION_OVR_PARAM_IMMUTABLE),
            ACTION_OVR_PARAM_BAD_ATTR['name']: ActionAPI(**ACTION_OVR_PARAM_BAD_ATTR),
            ACTION_OVR_PARAM_BAD_ATTR_NOOP['name']: ActionAPI(**ACTION_OVR_PARAM_BAD_ATTR_NOOP)
        }

        cls.actiondbs = {name: Action.add_or_update(ActionAPI.to_model(action))
                         for name, action in six.iteritems(cls.actions)}

        cls.container = RunnerContainer()
Ejemplo n.º 41
0
    def _create_save_action(runnertype, metadata=False):
        name = 'action-1'
        pack = 'wolfpack'
        ref = ResourceReference(pack=pack, name=name).ref
        created = ActionDB(name=name,
                           description='awesomeness',
                           enabled=True,
                           entry_point='/tmp/action.py',
                           pack=pack,
                           ref=ref,
                           runner_type={'name': runnertype.name})

        if not metadata:
            created.parameters = {
                'p1': None,
                'p2': None,
                'p3': None,
                'p4': None
            }
        else:
            created.parameters = {
                'p1': {
                    'type': 'string',
                    'required': True
                },
                'p2': {
                    'type': 'number',
                    'default': 2868
                },
                'p3': {
                    'type': 'boolean',
                    'default': False
                },
                'p4': {
                    'type': 'string',
                    'secret': True
                }
            }
        return Action.add_or_update(created)
Ejemplo n.º 42
0
def get_action_by_ref(ref, only_fields: Optional[List[str]] = None):
    """
    Returns the action object from db given a string ref.

    :param ref: Reference to the trigger type db object.
    :type ref: ``str``

    :param: only_field: Optional lists if fields to retrieve. If not specified, it defaults to all
                        fields.

    :rtype action: ``object``
    """
    try:
        return Action.get_by_ref(ref, only_fields=only_fields)
    except ValueError as e:
        LOG.debug(
            'Database lookup for ref="%s" resulted ' + "in exception : %s.",
            ref,
            e,
            exc_info=True,
        )
        return None
Ejemplo n.º 43
0
    def post(self, action):
        """
            Create a new action.

            Handles requests:
                POST /actions/
        """
        if not hasattr(action, 'pack'):
            setattr(action, 'pack', DEFAULT_PACK_NAME)

        # Perform validation
        validate_not_part_of_system_pack(action)
        action_validator.validate_action(action)

        # Write pack data files to disk (if any are provided)
        data_files = getattr(action, 'data_files', [])
        written_data_files = []
        if data_files:
            written_data_files = self._handle_data_files(pack_name=action.pack,
                                                         data_files=data_files)

        action_model = ActionAPI.to_model(action)

        LOG.debug('/actions/ POST verified ActionAPI object=%s', action)
        action_db = Action.add_or_update(action_model)
        LOG.debug('/actions/ POST saved ActionDB object=%s', action_db)

        # Dispatch an internal trigger for each written data file. This way user
        # automate comitting this files to git using StackStorm rule
        if written_data_files:
            self._dispatch_trigger_for_written_data_files(action_db=action_db,
                                                          written_data_files=written_data_files)

        extra = {'acion_db': action_db}
        LOG.audit('Action created. Action.id=%s' % (action_db.id), extra=extra)
        action_api = ActionAPI.from_model(action_db)

        return action_api
Ejemplo n.º 44
0
    def _register_action(self, pack, action):
        content = self._meta_loader.load(action)
        pack_field = content.get('pack', None)
        if not pack_field:
            content['pack'] = pack
            pack_field = pack
        if pack_field != pack:
            raise Exception(
                'Model is in pack "%s" but field "pack" is different: %s' %
                (pack, pack_field))

        action_api = ActionAPI(**content)
        action_api.validate()
        action_validator.validate_action(action_api)
        model = ActionAPI.to_model(action_api)

        action_ref = ResourceReference.to_string_reference(
            pack=pack, name=str(content['name']))
        existing = action_utils.get_action_by_ref(action_ref)
        if not existing:
            LOG.debug('Action %s not found. Creating new one with: %s',
                      action_ref, content)
        else:
            LOG.debug('Action %s found. Will be updated from: %s to: %s',
                      action_ref, existing, model)
            model.id = existing.id

        try:
            model = Action.add_or_update(model)
            extra = {'action_db': model}
            LOG.audit('Action updated. Action %s from %s.',
                      model,
                      action,
                      extra=extra)
        except Exception:
            LOG.exception('Failed to write action to db %s.', model.name)
            raise
Ejemplo n.º 45
0
    def put(self, action_ref_or_id, action):
        try:
            action_db = self._get_by_ref_or_id(ref_or_id=action_ref_or_id)
        except Exception as e:
            LOG.exception(e.message)
            abort(http_client.NOT_FOUND, e.message)
            return

        action_id = action_db.id

        try:
            validate_not_part_of_system_pack(action_db)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, str(e))

        if not getattr(action, 'pack', None):
            action.pack = action_db.pack

        try:
            action_validator.validate_action(action)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, str(e))
            return

        try:
            action_db = ActionAPI.to_model(action)
            action_db.id = action_id
            action_db = Action.add_or_update(action_db)
        except (ValidationError, ValueError) as e:
            LOG.exception('Unable to update action data=%s', action)
            abort(http_client.BAD_REQUEST, str(e))
            return

        action_api = ActionAPI.from_model(action_db)
        LOG.debug('PUT /actions/ client_result=%s', action_api)

        return action_api
Ejemplo n.º 46
0
    def setUp(self):
        super(ExecutionPermissionsResolverTestCase, self).setUp()

        # Create some mock users
        user_1_db = UserDB(name='custom_role_unrelated_pack_action_grant')
        user_1_db = User.add_or_update(user_1_db)
        self.users['custom_role_unrelated_pack_action_grant'] = user_1_db

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

        user_3_db = UserDB(name='custom_role_pack_action_view_grant')
        user_3_db = User.add_or_update(user_3_db)
        self.users['custom_role_pack_action_view_grant'] = user_3_db

        user_4_db = UserDB(name='custom_role_action_view_grant')
        user_4_db = User.add_or_update(user_4_db)
        self.users['custom_role_action_view_grant'] = user_4_db

        user_5_db = UserDB(name='custom_role_pack_action_execute_grant')
        user_5_db = User.add_or_update(user_5_db)
        self.users['custom_role_pack_action_execute_grant'] = user_5_db

        user_6_db = UserDB(name='custom_role_action_execute_grant')
        user_6_db = User.add_or_update(user_6_db)
        self.users['custom_role_action_execute_grant'] = user_6_db

        user_7_db = UserDB(name='custom_role_pack_action_all_grant')
        user_7_db = User.add_or_update(user_7_db)
        self.users['custom_role_pack_action_all_grant'] = user_7_db

        user_8_db = UserDB(name='custom_role_action_all_grant')
        user_8_db = User.add_or_update(user_8_db)
        self.users['custom_role_action_all_grant'] = user_8_db

        user_9_db = UserDB(name='custom_role_execution_list_grant')
        user_9_db = User.add_or_update(user_5_db)
        self.users['custom_role_execution_list_grant'] = user_9_db

        # Create some mock resources on which permissions can be granted
        action_1_db = ActionDB(pack='test_pack_2',
                               name='action1',
                               entry_point='',
                               runner_type={'name': 'run-local'})
        action_1_db = Action.add_or_update(action_1_db)
        self.resources['action_1'] = action_1_db

        runner = {'name': 'run-python'}
        liveaction = {'action': 'test_pack_2.action1'}
        status = action_constants.LIVEACTION_STATUS_REQUESTED

        action = {'uid': action_1_db.get_uid(), 'pack': 'test_pack_2'}
        exec_1_db = ActionExecutionDB(action=action,
                                      runner=runner,
                                      liveaction=liveaction,
                                      status=status)
        exec_1_db = ActionExecution.add_or_update(exec_1_db)
        self.resources['exec_1'] = exec_1_db

        # Create some mock roles with associated permission grants
        # Custom role - one grant to an unrelated pack
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['pack_1'].get_uid(),
            resource_type=ResourceType.PACK,
            permission_types=[PermissionType.ACTION_VIEW])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_unrelated_pack_action_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_unrelated_pack_action_grant'] = role_db

        # Custom role - one grant of unrelated permission type to parent action pack
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['pack_2'].get_uid(),
            resource_type=ResourceType.PACK,
            permission_types=[PermissionType.RULE_VIEW])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(
            name='custom_role_pack_action_grant_unrelated_permission',
            permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles[
            'custom_role_pack_action_grant_unrelated_permission'] = role_db

        # Custom role - one grant of "action_view" to the parent pack of the action the execution
        # belongs to
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['pack_2'].get_uid(),
            resource_type=ResourceType.PACK,
            permission_types=[PermissionType.ACTION_VIEW])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_pack_action_view_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_pack_action_view_grant'] = role_db

        # Custom role - one grant of "action_view" to the action the execution belongs to
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['action_1'].get_uid(),
            resource_type=ResourceType.ACTION,
            permission_types=[PermissionType.ACTION_VIEW])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_action_view_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_action_view_grant'] = role_db

        # Custom role - one grant of "action_execute" to the parent pack of the action the
        # execution belongs to
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['pack_2'].get_uid(),
            resource_type=ResourceType.PACK,
            permission_types=[PermissionType.ACTION_EXECUTE])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_pack_action_execute_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_pack_action_execute_grant'] = role_db

        # Custom role - one grant of "action_execute" to the the action the execution belongs to
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['action_1'].get_uid(),
            resource_type=ResourceType.ACTION,
            permission_types=[PermissionType.ACTION_EXECUTE])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_action_execute_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_action_execute_grant'] = role_db

        # Custom role - "action_all" grant on a parent action pack the execution belongs to
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['pack_2'].get_uid(),
            resource_type=ResourceType.PACK,
            permission_types=[PermissionType.ACTION_ALL])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_4_db = RoleDB(name='custom_role_pack_action_all_grant',
                           permission_grants=permission_grants)
        role_4_db = Role.add_or_update(role_4_db)
        self.roles['custom_role_pack_action_all_grant'] = role_4_db

        # Custom role - "action_all" grant on action the execution belongs to
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['action_1'].get_uid(),
            resource_type=ResourceType.ACTION,
            permission_types=[PermissionType.ACTION_ALL])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_4_db = RoleDB(name='custom_role_action_all_grant',
                           permission_grants=permission_grants)
        role_4_db = Role.add_or_update(role_4_db)
        self.roles['custom_role_action_all_grant'] = role_4_db

        # Custom role - "execution_list" grant
        grant_db = PermissionGrantDB(
            resource_uid=None,
            resource_type=None,
            permission_types=[PermissionType.EXECUTION_LIST])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_5_db = RoleDB(name='custom_role_execution_list_grant',
                           permission_grants=permission_grants)
        role_5_db = Role.add_or_update(role_5_db)
        self.roles['custom_role_execution_list_grant'] = role_5_db

        # Create some mock role assignments
        user_db = self.users['custom_role_unrelated_pack_action_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_unrelated_pack_action_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users[
            'custom_role_pack_action_grant_unrelated_permission']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.
            roles['custom_role_pack_action_grant_unrelated_permission'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_pack_action_view_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_pack_action_view_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_action_view_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_action_view_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_pack_action_execute_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_pack_action_execute_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_action_execute_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_action_execute_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_pack_action_all_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_pack_action_all_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_action_all_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_action_all_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_execution_list_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_execution_list_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)
Ejemplo n.º 47
0
    def setUp(self):
        super(InquiryPermissionsResolverTestCase, self).setUp()

        # Create some mock users
        user_1_db = UserDB(name='custom_role_inquiry_list_grant')
        user_1_db = User.add_or_update(user_1_db)
        self.users['custom_role_inquiry_list_grant'] = user_1_db

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

        user_3_db = UserDB(name='custom_role_inquiry_respond_grant')
        user_3_db = User.add_or_update(user_3_db)
        self.users['custom_role_inquiry_respond_grant'] = user_3_db

        user_4_db = UserDB(name='custom_role_inquiry_all_grant')
        user_4_db = User.add_or_update(user_4_db)
        self.users['custom_role_inquiry_all_grant'] = user_4_db

        user_5_db = UserDB(name='custom_role_inquiry_inherit')
        user_5_db = User.add_or_update(user_5_db)
        self.users['custom_role_inquiry_inherit'] = user_5_db

        # Create a workflow for testing inheritance of action_execute permission
        # to inquiry_respond permission
        wf_db = ActionDB(pack='examples',
                         name='mistral-ask-basic',
                         entry_point='',
                         runner_type={'name': 'mistral-v2'})
        wf_db = Action.add_or_update(wf_db)
        self.resources['wf'] = wf_db
        runner = {'name': 'mistral-v2'}
        liveaction = {'action': 'examples.mistral-ask-basic'}
        status = action_constants.LIVEACTION_STATUS_PAUSED

        # Spawn workflow
        action = {'uid': wf_db.get_uid(), 'pack': 'examples'}
        wf_exc_db = ActionExecutionDB(action=action,
                                      runner=runner,
                                      liveaction=liveaction,
                                      status=status)
        wf_exc_db = ActionExecution.add_or_update(wf_exc_db)

        # Create an Inquiry on which permissions can be granted
        action_1_db = ActionDB(pack='core',
                               name='ask',
                               entry_point='',
                               runner_type={'name': 'inquirer'})
        action_1_db = Action.add_or_update(action_1_db)
        self.resources['action_1'] = action_1_db
        runner = {'name': 'inquirer'}
        liveaction = {'action': 'core.ask'}
        status = action_constants.LIVEACTION_STATUS_PENDING

        # For now, Inquiries are "borrowing" the ActionExecutionDB model,
        # so we have to test with that model
        action = {'uid': action_1_db.get_uid(), 'pack': 'core'}
        inquiry_1_db = ActionExecutionDB(action=action,
                                         runner=runner,
                                         liveaction=liveaction,
                                         status=status)

        # A separate inquiry that has a parent (so we can test workflow permission inheritance)
        inquiry_2_db = ActionExecutionDB(action=action,
                                         runner=runner,
                                         liveaction=liveaction,
                                         status=status,
                                         parent=str(wf_exc_db.id))

        # A bit gross, but it's what we have to do since Inquiries
        # don't yet have their own data model
        def get_uid():
            return "inquiry"

        inquiry_1_db.get_uid = get_uid
        inquiry_2_db.get_uid = get_uid

        inquiry_1_db = ActionExecution.add_or_update(inquiry_1_db)
        inquiry_2_db = ActionExecution.add_or_update(inquiry_2_db)
        self.resources['inquiry_1'] = inquiry_1_db
        self.resources['inquiry_2'] = inquiry_2_db

        ############################################################
        # Create some mock roles with associated permission grants #
        ############################################################

        # Custom role - "inquiry_list" grant
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['inquiry_1'].get_uid(),
            resource_type=ResourceType.INQUIRY,
            permission_types=[PermissionType.INQUIRY_LIST])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_inquiry_list_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_inquiry_list_grant'] = role_db

        # Custom role - "inquiry_view" grant
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['inquiry_1'].get_uid(),
            resource_type=ResourceType.INQUIRY,
            permission_types=[PermissionType.INQUIRY_VIEW])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_inquiry_view_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_inquiry_view_grant'] = role_db

        # Custom role - "inquiry_respond" grant
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['inquiry_1'].get_uid(),
            resource_type=ResourceType.INQUIRY,
            permission_types=[PermissionType.INQUIRY_RESPOND])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_inquiry_respond_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_inquiry_respond_grant'] = role_db

        # Custom role - "inquiry_all" grant
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['inquiry_1'].get_uid(),
            resource_type=ResourceType.INQUIRY,
            permission_types=[PermissionType.INQUIRY_ALL])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_inquiry_all_grant',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_inquiry_all_grant'] = role_db

        # Custom role - inheritance grant
        grant_db = PermissionGrantDB(
            resource_uid=self.resources['wf'].get_uid(),
            resource_type=ResourceType.ACTION,
            permission_types=[PermissionType.ACTION_EXECUTE])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_db = RoleDB(name='custom_role_inquiry_inherit',
                         permission_grants=permission_grants)
        role_db = Role.add_or_update(role_db)
        self.roles['custom_role_inquiry_inherit'] = role_db

        #####################################
        # Create some mock role assignments #
        #####################################

        user_db = self.users['custom_role_inquiry_list_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_inquiry_list_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_inquiry_view_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_inquiry_view_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_inquiry_respond_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_inquiry_respond_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_inquiry_all_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_inquiry_all_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_inquiry_inherit']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name,
            role=self.roles['custom_role_inquiry_inherit'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)
Ejemplo n.º 48
0
 def setUpClass(cls):
     super(DSLTransformTestCase, cls).setUpClass()
     runners_registrar.register_runner_types()
     action_local = ActionAPI(
         **copy.deepcopy(FIXTURES['actions']['local.json']))
     Action.add_or_update(ActionAPI.to_model(action_local))
Ejemplo n.º 49
0
    def setUp(self):
        super(ActionPermissionsResolverTestCase, self).setUp()

        # Create some mock users
        user_1_db = UserDB(name='1_role_action_pack_grant')
        user_1_db = User.add_or_update(user_1_db)
        self.users['custom_role_action_pack_grant'] = user_1_db

        user_2_db = UserDB(name='1_role_action_grant')
        user_2_db = User.add_or_update(user_2_db)
        self.users['custom_role_action_grant'] = user_2_db

        user_3_db = UserDB(name='custom_role_pack_action_all_grant')
        user_3_db = User.add_or_update(user_3_db)
        self.users['custom_role_pack_action_all_grant'] = user_3_db

        user_4_db = UserDB(name='custom_role_action_all_grant')
        user_4_db = User.add_or_update(user_4_db)
        self.users['custom_role_action_all_grant'] = user_4_db

        user_5_db = UserDB(name='custom_role_action_execute_grant')
        user_5_db = User.add_or_update(user_5_db)
        self.users['custom_role_action_execute_grant'] = user_5_db

        user_6_db = UserDB(name='action_pack_action_create_grant')
        user_6_db = User.add_or_update(user_6_db)
        self.users['action_pack_action_create_grant'] = user_6_db

        user_7_db = UserDB(name='action_pack_action_all_grant')
        user_7_db = User.add_or_update(user_7_db)
        self.users['action_pack_action_all_grant'] = user_7_db

        user_8_db = UserDB(name='action_action_create_grant')
        user_8_db = User.add_or_update(user_8_db)
        self.users['action_action_create_grant'] = user_8_db

        user_9_db = UserDB(name='action_action_all_grant')
        user_9_db = User.add_or_update(user_9_db)
        self.users['action_action_all_grant'] = user_9_db

        user_10_db = UserDB(name='custom_role_action_list_grant')
        user_10_db = User.add_or_update(user_10_db)
        self.users['custom_role_action_list_grant'] = user_10_db

        # Create some mock resources on which permissions can be granted
        action_1_db = ActionDB(pack='test_pack_1', name='action1', entry_point='',
                               runner_type={'name': 'local-shell-cmd'})
        action_1_db = Action.add_or_update(action_1_db)
        self.resources['action_1'] = action_1_db

        action_2_db = ActionDB(pack='test_pack_1', name='action2', entry_point='',
                               runner_type={'name': 'local-shell-cmd'})
        action_2_db = Action.add_or_update(action_1_db)
        self.resources['action_2'] = action_2_db

        action_3_db = ActionDB(pack='test_pack_2', name='action3', entry_point='',
                               runner_type={'name': 'local-shell-cmd'})
        action_3_db = Action.add_or_update(action_3_db)
        self.resources['action_3'] = action_3_db

        # Create some mock roles with associated permission grants
        # Custom role 2 - one grant on parent pack
        # "action_view" on pack_1
        grant_db = PermissionGrantDB(resource_uid=self.resources['pack_1'].get_uid(),
                                     resource_type=ResourceType.PACK,
                                     permission_types=[PermissionType.ACTION_VIEW])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_3_db = RoleDB(name='custom_role_action_pack_grant',
                           permission_grants=permission_grants)
        role_3_db = Role.add_or_update(role_3_db)
        self.roles['custom_role_action_pack_grant'] = role_3_db

        # Custom role 4 - one grant on action
        # "action_view" on action_3
        grant_db = PermissionGrantDB(resource_uid=self.resources['action_3'].get_uid(),
                                     resource_type=ResourceType.ACTION,
                                     permission_types=[PermissionType.ACTION_VIEW])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_4_db = RoleDB(name='custom_role_action_grant', permission_grants=permission_grants)
        role_4_db = Role.add_or_update(role_4_db)
        self.roles['custom_role_action_grant'] = role_4_db

        # Custom role - "action_all" grant on a parent action pack
        grant_db = PermissionGrantDB(resource_uid=self.resources['pack_1'].get_uid(),
                                     resource_type=ResourceType.PACK,
                                     permission_types=[PermissionType.ACTION_ALL])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_4_db = RoleDB(name='custom_role_pack_action_all_grant',
                           permission_grants=permission_grants)
        role_4_db = Role.add_or_update(role_4_db)
        self.roles['custom_role_pack_action_all_grant'] = role_4_db

        # Custom role - "action_all" grant on action
        grant_db = PermissionGrantDB(resource_uid=self.resources['action_1'].get_uid(),
                                     resource_type=ResourceType.ACTION,
                                     permission_types=[PermissionType.ACTION_ALL])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_4_db = RoleDB(name='custom_role_action_all_grant', permission_grants=permission_grants)
        role_4_db = Role.add_or_update(role_4_db)
        self.roles['custom_role_action_all_grant'] = role_4_db

        # Custom role - "action_execute" on action_1
        grant_db = PermissionGrantDB(resource_uid=self.resources['action_1'].get_uid(),
                                     resource_type=ResourceType.ACTION,
                                     permission_types=[PermissionType.ACTION_EXECUTE])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_5_db = RoleDB(name='custom_role_action_execute_grant',
                           permission_grants=permission_grants)
        role_5_db = Role.add_or_update(role_5_db)
        self.roles['custom_role_action_execute_grant'] = role_5_db

        # Custom role - "action_create" grant on pack_1
        grant_db = PermissionGrantDB(resource_uid=self.resources['pack_1'].get_uid(),
                                     resource_type=ResourceType.PACK,
                                     permission_types=[PermissionType.ACTION_CREATE])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_6_db = RoleDB(name='action_pack_action_create_grant',
                           permission_grants=permission_grants)
        role_6_db = Role.add_or_update(role_6_db)
        self.roles['action_pack_action_create_grant'] = role_6_db

        # Custom role - "action_all" grant on pack_1
        grant_db = PermissionGrantDB(resource_uid=self.resources['pack_1'].get_uid(),
                                     resource_type=ResourceType.PACK,
                                     permission_types=[PermissionType.ACTION_ALL])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_7_db = RoleDB(name='action_pack_action_all_grant',
                           permission_grants=permission_grants)
        role_7_db = Role.add_or_update(role_7_db)
        self.roles['action_pack_action_all_grant'] = role_7_db

        # Custom role - "action_create" grant on action_1
        grant_db = PermissionGrantDB(resource_uid=self.resources['action_1'].get_uid(),
                                     resource_type=ResourceType.ACTION,
                                     permission_types=[PermissionType.ACTION_CREATE])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_8_db = RoleDB(name='action_action_create_grant',
                           permission_grants=permission_grants)
        role_8_db = Role.add_or_update(role_8_db)
        self.roles['action_action_create_grant'] = role_8_db

        # Custom role - "action_all" grant on action_1
        grant_db = PermissionGrantDB(resource_uid=self.resources['action_1'].get_uid(),
                                     resource_type=ResourceType.ACTION,
                                     permission_types=[PermissionType.ACTION_ALL])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_9_db = RoleDB(name='action_action_all_grant',
                           permission_grants=permission_grants)
        role_9_db = Role.add_or_update(role_9_db)
        self.roles['action_action_all_grant'] = role_9_db

        # Custom role - "action_list" grant
        grant_db = PermissionGrantDB(resource_uid=None,
                                     resource_type=None,
                                     permission_types=[PermissionType.ACTION_LIST])
        grant_db = PermissionGrant.add_or_update(grant_db)
        permission_grants = [str(grant_db.id)]
        role_10_db = RoleDB(name='custom_role_action_list_grant',
                           permission_grants=permission_grants)
        role_10_db = Role.add_or_update(role_10_db)
        self.roles['custom_role_action_list_grant'] = role_10_db

        # Create some mock role assignments
        user_db = self.users['custom_role_action_pack_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['custom_role_action_pack_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_action_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['custom_role_action_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_pack_action_all_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['custom_role_pack_action_all_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_action_all_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['custom_role_action_all_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_action_execute_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['custom_role_action_execute_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['action_pack_action_create_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['action_pack_action_create_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['action_pack_action_all_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['action_pack_action_all_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['action_action_create_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['action_action_create_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['action_action_all_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['action_action_all_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)

        user_db = self.users['custom_role_action_list_grant']
        role_assignment_db = UserRoleAssignmentDB(
            user=user_db.name, role=self.roles['custom_role_action_list_grant'].name,
            source='assignments/%s.yaml' % user_db.name)
        UserRoleAssignment.add_or_update(role_assignment_db)
Ejemplo n.º 50
0
 def setUpClass(cls):
     super(ExecutionCancellationTest, cls).setUpClass()
     runners_registrar.register_runners()
     action_local = ActionAPI(
         **copy.deepcopy(fixture.ARTIFACTS['actions']['local']))
     Action.add_or_update(ActionAPI.to_model(action_local))
Ejemplo n.º 51
0
 def _get_runner(self, action_ref):
     action = Action.get_by_ref(action_ref)
     return action['runner_type']['name']
Ejemplo n.º 52
0
 def tearDownClass(cls):
     Action.delete(cls.actiondb)
     RunnerType.delete(cls.runnerdb)
     super(TestActionExecutionService, cls).tearDownClass()
Ejemplo n.º 53
0
    def test_packs_register_endpoint(self, mock_get_packs):
        # Register resources from all packs - make sure the count values are correctly added
        # together

        # Note: We only register a couple of packs and not all on disk to speed
        # things up. Registering all the packs takes a long time.
        fixtures_base_path = get_fixtures_base_path()
        packs_base_path = os.path.join(fixtures_base_path, "packs")
        pack_names = [
            "dummy_pack_1",
            "dummy_pack_10",
        ]
        mock_return_value = {}
        for pack_name in pack_names:
            mock_return_value[pack_name] = os.path.join(
                packs_base_path, pack_name)

        mock_get_packs.return_value = mock_return_value

        resp = self.app.post_json("/v1/packs/register",
                                  {"fail_on_failure": False})

        self.assertEqual(resp.status_int, 200)
        self.assertIn("runners", resp.json)
        self.assertIn("actions", resp.json)
        self.assertIn("triggers", resp.json)
        self.assertIn("sensors", resp.json)
        self.assertIn("rules", resp.json)
        self.assertIn("rule_types", resp.json)
        self.assertIn("aliases", resp.json)
        self.assertIn("policy_types", resp.json)
        self.assertIn("policies", resp.json)
        self.assertIn("configs", resp.json)

        self.assertTrue(resp.json["actions"] >= 3)
        self.assertTrue(resp.json["configs"] >= 1)

        # Register resources from a specific pack
        resp = self.app.post_json("/v1/packs/register", {
            "packs": ["dummy_pack_1"],
            "fail_on_failure": False
        })

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json["actions"] >= 1)
        self.assertTrue(resp.json["sensors"] >= 1)
        self.assertTrue(resp.json["configs"] >= 1)

        # Verify metadata_file attribute is set
        action_dbs = Action.query(pack="dummy_pack_1")
        self.assertEqual(action_dbs[0].metadata_file, "actions/my_action.yaml")

        # Register 'all' resource types should try include any possible content for the pack
        resp = self.app.post_json(
            "/v1/packs/register",
            {
                "packs": ["dummy_pack_1"],
                "fail_on_failure": False,
                "types": ["all"]
            },
        )

        self.assertEqual(resp.status_int, 200)
        self.assertIn("runners", resp.json)
        self.assertIn("actions", resp.json)
        self.assertIn("triggers", resp.json)
        self.assertIn("sensors", resp.json)
        self.assertIn("rules", resp.json)
        self.assertIn("rule_types", resp.json)
        self.assertIn("aliases", resp.json)
        self.assertIn("policy_types", resp.json)
        self.assertIn("policies", resp.json)
        self.assertIn("configs", resp.json)

        # Registering single resource type should also cause dependent resources
        # to be registered
        # * actions -> runners
        # * rules -> rule types
        # * policies -> policy types
        resp = self.app.post_json(
            "/v1/packs/register",
            {
                "packs": ["dummy_pack_1"],
                "fail_on_failure": False,
                "types": ["actions"]
            },
        )

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json["runners"] >= 1)
        self.assertTrue(resp.json["actions"] >= 1)

        resp = self.app.post_json(
            "/v1/packs/register",
            {
                "packs": ["dummy_pack_1"],
                "fail_on_failure": False,
                "types": ["rules"]
            },
        )

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json["rule_types"] >= 1)
        self.assertTrue(resp.json["rules"] >= 1)

        resp = self.app.post_json(
            "/v1/packs/register",
            {
                "packs": ["dummy_pack_2"],
                "fail_on_failure": False,
                "types": ["policies"],
            },
        )

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json["policy_types"] >= 1)
        self.assertTrue(resp.json["policies"] >= 0)

        # Register specific type for all packs
        resp = self.app.post_json("/v1/packs/register", {
            "types": ["sensor"],
            "fail_on_failure": False
        })

        self.assertEqual(resp.status_int, 200)
        self.assertEqual(resp.json, {"sensors": 3})

        # Verify that plural name form also works
        resp = self.app.post_json("/v1/packs/register", {
            "types": ["sensors"],
            "fail_on_failure": False
        })
        self.assertEqual(resp.status_int, 200)

        # Register specific type for a single packs
        resp = self.app.post_json("/v1/packs/register", {
            "packs": ["dummy_pack_1"],
            "types": ["action"]
        })

        self.assertEqual(resp.status_int, 200)
        # 13 real plus 1 mock runner
        self.assertEqual(resp.json, {"actions": 3, "runners": 14})

        # Verify that plural name form also works
        resp = self.app.post_json("/v1/packs/register", {
            "packs": ["dummy_pack_1"],
            "types": ["actions"]
        })

        self.assertEqual(resp.status_int, 200)
        # 13 real plus 1 mock runner
        self.assertEqual(resp.json, {"actions": 3, "runners": 14})

        # Register single resource from a single pack specified multiple times - verify that
        # resources from the same pack are only registered once
        resp = self.app.post_json(
            "/v1/packs/register",
            {
                "packs": ["dummy_pack_1", "dummy_pack_1", "dummy_pack_1"],
                "types": ["actions"],
                "fail_on_failure": False,
            },
        )

        self.assertEqual(resp.status_int, 200)
        # 13 real plus 1 mock runner
        self.assertEqual(resp.json, {"actions": 3, "runners": 14})

        # Register resources from a single (non-existent pack)
        resp = self.app.post_json("/v1/packs/register",
                                  {"packs": ["doesntexist"]},
                                  expect_errors=True)

        self.assertEqual(resp.status_int, 400)
        self.assertIn('Pack "doesntexist" not found on disk:',
                      resp.json["faultstring"])

        # Fail on failure is enabled by default
        resp = self.app.post_json("/v1/packs/register", expect_errors=True)

        expected_msg = 'Failed to register pack "dummy_pack_10":'
        self.assertEqual(resp.status_int, 400)
        self.assertIn(expected_msg, resp.json["faultstring"])

        # Fail on failure (broken pack metadata)
        resp = self.app.post_json("/v1/packs/register",
                                  {"packs": ["dummy_pack_1"]},
                                  expect_errors=True)

        expected_msg = 'Referenced policy_type "action.mock_policy_error" doesnt exist'
        self.assertEqual(resp.status_int, 400)
        self.assertIn(expected_msg, resp.json["faultstring"])

        # Fail on failure (broken action metadata)
        resp = self.app.post_json("/v1/packs/register",
                                  {"packs": ["dummy_pack_15"]},
                                  expect_errors=True)

        expected_msg = "Failed to register action"
        self.assertEqual(resp.status_int, 400)
        self.assertIn(expected_msg, resp.json["faultstring"])

        expected_msg = "'stringa' is not valid under any of the given schemas"
        self.assertEqual(resp.status_int, 400)
        self.assertIn(expected_msg, resp.json["faultstring"])
Ejemplo n.º 54
0
    def _register_action(self, pack, action):
        content = self._meta_loader.load(action)
        pack_field = content.get("pack", None)
        if not pack_field:
            content["pack"] = pack
            pack_field = pack
        if pack_field != pack:
            raise Exception(
                'Model is in pack "%s" but field "pack" is different: %s' %
                (pack, pack_field))

        # Add in "metadata_file" attribute which stores path to the pack metadata file relative to
        # the pack directory
        metadata_file = content_utils.get_relative_path_to_pack_file(
            pack_ref=pack, file_path=action, use_pack_cache=True)
        content["metadata_file"] = metadata_file

        action_api = ActionAPI(**content)

        try:
            action_api.validate()
        except jsonschema.ValidationError as e:
            # We throw a more user-friendly exception on invalid parameter name
            msg = six.text_type(e)

            is_invalid_parameter_name = "does not match any of the regexes: " in msg

            if is_invalid_parameter_name:
                match = re.search("'(.+?)' does not match any of the regexes",
                                  msg)

                if match:
                    parameter_name = match.groups()[0]
                else:
                    parameter_name = "unknown"

                new_msg = (
                    'Parameter name "%s" is invalid. Valid characters for parameter name '
                    "are [a-zA-Z0-0_]." % (parameter_name))
                new_msg += "\n\n" + msg
                raise jsonschema.ValidationError(new_msg)
            raise e

        # Use in-memory cached RunnerTypeDB objects to reduce load on the database
        if self._use_runners_cache:
            runner_type_db = self._runner_type_db_cache.get(
                action_api.runner_type, None)

            if not runner_type_db:
                runner_type_db = action_validator.get_runner_model(action_api)
                self._runner_type_db_cache[
                    action_api.runner_type] = runner_type_db
        else:
            runner_type_db = None

        action_validator.validate_action(action_api,
                                         runner_type_db=runner_type_db)
        model = ActionAPI.to_model(action_api)

        action_ref = ResourceReference.to_string_reference(
            pack=pack, name=str(content["name"]))
        # NOTE: Here we only retrieve existing object to perform an upsert if it already exists in
        # the database. To do that, we only need access to the "id" attribute (and ref and pack
        # for our ActionDB abstraction). Retrieving only those fields is fast and much efficient
        # especially for actions like aws pack ones which contain a lot of parameters.
        existing = action_utils.get_action_by_ref(
            action_ref, only_fields=["id", "ref", "pack"])
        if not existing:
            LOG.debug("Action %s not found. Creating new one with: %s",
                      action_ref, content)
        else:
            LOG.debug(
                "Action %s found. Will be updated from: %s to: %s",
                action_ref,
                existing,
                model,
            )
            model.id = existing.id

        try:
            model = Action.add_or_update(model)
            extra = {"action_db": model}
            LOG.audit("Action updated. Action %s from %s.",
                      model,
                      action,
                      extra=extra)
        except Exception:
            LOG.exception("Failed to write action to db %s.", model.name)
            raise
Ejemplo n.º 55
0
    def setup_action_models(cls):
        pack = "wolfpack"
        name = "action-1"
        parameters = {
            "actionint": {
                "type": "number",
                "default": 10,
                "position": 0
            },
            "actionfloat": {
                "type": "float",
                "required": False,
                "position": 1
            },
            "actionstr": {
                "type": "string",
                "required": True,
                "position": 2
            },
            "actionbool": {
                "type": "boolean",
                "required": False,
                "position": 3
            },
            "actionarray": {
                "type": "array",
                "required": False,
                "position": 4
            },
            "actionlist": {
                "type": "list",
                "required": False,
                "position": 5
            },
            "actionobject": {
                "type": "object",
                "required": False,
                "position": 6
            },
            "actionnull": {
                "type": "null",
                "required": False,
                "position": 7
            },
            "runnerdummy": {
                "type": "string",
                "default": "actiondummy"
            },
        }
        action_db = ActionDB(
            pack=pack,
            name=name,
            description="awesomeness",
            enabled=True,
            ref=ResourceReference(name=name, pack=pack).ref,
            entry_point="",
            runner_type={"name": "test-runner"},
            parameters=parameters,
        )
        ActionDBUtilsTestCase.action_db = Action.add_or_update(action_db)

        liveaction_db = LiveActionDB()
        liveaction_db.status = "initializing"
        liveaction_db.start_timestamp = get_datetime_utc_now()
        liveaction_db.action = ActionDBUtilsTestCase.action_db.ref
        params = {
            "actionstr": "foo",
            "some_key_that_aint_exist_in_action_or_runner": "bar",
            "runnerint": 555,
        }
        liveaction_db.parameters = params
        ActionDBUtilsTestCase.liveaction_db = LiveAction.add_or_update(
            liveaction_db)
Ejemplo n.º 56
0
    def _register_action(self, pack, action):
        content = self._meta_loader.load(action)
        pack_field = content.get('pack', None)
        if not pack_field:
            content['pack'] = pack
            pack_field = pack
        if pack_field != pack:
            raise Exception(
                'Model is in pack "%s" but field "pack" is different: %s' %
                (pack, pack_field))

        action_api = ActionAPI(**content)

        try:
            action_api.validate()
        except jsonschema.ValidationError as e:
            # We throw a more user-friendly exception on invalid parameter name
            msg = str(e)

            is_invalid_parameter_name = 'does not match any of the regexes: ' in msg

            if is_invalid_parameter_name:
                match = re.search(
                    '\'(.+?)\' does not match any of the regexes', msg)

                if match:
                    parameter_name = match.groups()[0]
                else:
                    parameter_name = 'unknown'

                new_msg = (
                    'Parameter name "%s" is invalid. Valid characters for parameter name '
                    'are [a-zA-Z0-0_].' % (parameter_name))
                new_msg += '\n\n' + msg
                raise jsonschema.ValidationError(new_msg)
            raise e

        action_validator.validate_action(action_api)
        model = ActionAPI.to_model(action_api)

        action_ref = ResourceReference.to_string_reference(
            pack=pack, name=str(content['name']))
        existing = action_utils.get_action_by_ref(action_ref)
        if not existing:
            LOG.debug('Action %s not found. Creating new one with: %s',
                      action_ref, content)
        else:
            LOG.debug('Action %s found. Will be updated from: %s to: %s',
                      action_ref, existing, model)
            model.id = existing.id

        try:
            model = Action.add_or_update(model)
            extra = {'action_db': model}
            LOG.audit('Action updated. Action %s from %s.',
                      model,
                      action,
                      extra=extra)
        except Exception:
            LOG.exception('Failed to write action to db %s.', model.name)
            raise
Ejemplo n.º 57
0
    def _register_action(self, pack, action):
        content = self._meta_loader.load(action)
        pack_field = content.get('pack', None)
        if not pack_field:
            content['pack'] = pack
            pack_field = pack
        if pack_field != pack:
            raise Exception(
                'Model is in pack "%s" but field "pack" is different: %s' %
                (pack, pack_field))

        # Add in "metadata_file" attribute which stores path to the pack metadata file relative to
        # the pack directory
        metadata_file = content_utils.get_relative_path_to_pack_file(
            pack_ref=pack, file_path=action, use_pack_cache=True)
        content['metadata_file'] = metadata_file

        action_api = ActionAPI(**content)

        try:
            action_api.validate()
        except jsonschema.ValidationError as e:
            # We throw a more user-friendly exception on invalid parameter name
            msg = six.text_type(e)

            is_invalid_parameter_name = 'does not match any of the regexes: ' in msg

            if is_invalid_parameter_name:
                match = re.search(
                    '\'(.+?)\' does not match any of the regexes', msg)

                if match:
                    parameter_name = match.groups()[0]
                else:
                    parameter_name = 'unknown'

                new_msg = (
                    'Parameter name "%s" is invalid. Valid characters for parameter name '
                    'are [a-zA-Z0-0_].' % (parameter_name))
                new_msg += '\n\n' + msg
                raise jsonschema.ValidationError(new_msg)
            raise e

        # Use in-memory cached RunnerTypeDB objects to reduce load on the database
        if self._use_runners_cache:
            runner_type_db = self._runner_type_db_cache.get(
                action_api.runner_type, None)

            if not runner_type_db:
                runner_type_db = action_validator.get_runner_model(action_api)
                self._runner_type_db_cache[
                    action_api.runner_type] = runner_type_db
        else:
            runner_type_db = None

        action_validator.validate_action(action_api,
                                         runner_type_db=runner_type_db)
        model = ActionAPI.to_model(action_api)

        action_ref = ResourceReference.to_string_reference(
            pack=pack, name=str(content['name']))
        existing = action_utils.get_action_by_ref(action_ref)
        if not existing:
            LOG.debug('Action %s not found. Creating new one with: %s',
                      action_ref, content)
        else:
            LOG.debug('Action %s found. Will be updated from: %s to: %s',
                      action_ref, existing, model)
            model.id = existing.id

        try:
            model = Action.add_or_update(model)
            extra = {'action_db': model}
            LOG.audit('Action updated. Action %s from %s.',
                      model,
                      action,
                      extra=extra)
        except Exception:
            LOG.exception('Failed to write action to db %s.', model.name)
            raise
Ejemplo n.º 58
0
    def test_packs_register_endpoint(self, mock_get_packs):
        # Register resources from all packs - make sure the count values are correctly added
        # together

        # Note: We only register a couple of packs and not all on disk to speed
        # things up. Registering all the packs takes a long time.
        fixtures_base_path = get_fixtures_base_path()
        packs_base_path = os.path.join(fixtures_base_path, 'packs')
        pack_names = [
            'dummy_pack_1',
            'dummy_pack_2',
            'dummy_pack_3',
            'dummy_pack_10',
        ]
        mock_return_value = {}
        for pack_name in pack_names:
            mock_return_value[pack_name] = os.path.join(
                packs_base_path, pack_name)

        mock_get_packs.return_value = mock_return_value

        resp = self.app.post_json('/v1/packs/register',
                                  {'fail_on_failure': False})

        self.assertEqual(resp.status_int, 200)
        self.assertTrue('runners' in resp.json)
        self.assertTrue('actions' in resp.json)
        self.assertTrue('triggers' in resp.json)
        self.assertTrue('sensors' in resp.json)
        self.assertTrue('rules' in resp.json)
        self.assertTrue('rule_types' in resp.json)
        self.assertTrue('aliases' in resp.json)
        self.assertTrue('policy_types' in resp.json)
        self.assertTrue('policies' in resp.json)
        self.assertTrue('configs' in resp.json)

        self.assertTrue(resp.json['actions'] >= 3)
        self.assertTrue(resp.json['configs'] >= 1)

        # Register resources from a specific pack
        resp = self.app.post_json('/v1/packs/register', {
            'packs': ['dummy_pack_1'],
            'fail_on_failure': False
        })

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json['actions'] >= 1)
        self.assertTrue(resp.json['sensors'] >= 1)
        self.assertTrue(resp.json['configs'] >= 1)

        # Verify metadata_file attribute is set
        action_dbs = Action.query(pack='dummy_pack_1')
        self.assertEqual(action_dbs[0].metadata_file, 'actions/my_action.yaml')

        # Register 'all' resource types should try include any possible content for the pack
        resp = self.app.post_json('/v1/packs/register', {
            'packs': ['dummy_pack_1'],
            'fail_on_failure': False,
            'types': ['all']
        })

        self.assertEqual(resp.status_int, 200)
        self.assertTrue('runners' in resp.json)
        self.assertTrue('actions' in resp.json)
        self.assertTrue('triggers' in resp.json)
        self.assertTrue('sensors' in resp.json)
        self.assertTrue('rules' in resp.json)
        self.assertTrue('rule_types' in resp.json)
        self.assertTrue('aliases' in resp.json)
        self.assertTrue('policy_types' in resp.json)
        self.assertTrue('policies' in resp.json)
        self.assertTrue('configs' in resp.json)

        # Registering single resource type should also cause dependent resources
        # to be registered
        # * actions -> runners
        # * rules -> rule types
        # * policies -> policy types
        resp = self.app.post_json(
            '/v1/packs/register', {
                'packs': ['dummy_pack_1'],
                'fail_on_failure': False,
                'types': ['actions']
            })

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json['runners'] >= 1)
        self.assertTrue(resp.json['actions'] >= 1)

        resp = self.app.post_json(
            '/v1/packs/register', {
                'packs': ['dummy_pack_1'],
                'fail_on_failure': False,
                'types': ['rules']
            })

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json['rule_types'] >= 1)
        self.assertTrue(resp.json['rules'] >= 1)

        resp = self.app.post_json(
            '/v1/packs/register', {
                'packs': ['dummy_pack_2'],
                'fail_on_failure': False,
                'types': ['policies']
            })

        self.assertEqual(resp.status_int, 200)
        self.assertTrue(resp.json['policy_types'] >= 1)
        self.assertTrue(resp.json['policies'] >= 0)

        # Register specific type for all packs
        resp = self.app.post_json('/v1/packs/register', {
            'types': ['sensor'],
            'fail_on_failure': False
        })

        self.assertEqual(resp.status_int, 200)
        self.assertEqual(resp.json, {'sensors': 3})

        # Verify that plural name form also works
        resp = self.app.post_json('/v1/packs/register', {
            'types': ['sensors'],
            'fail_on_failure': False
        })
        self.assertEqual(resp.status_int, 200)

        # Register specific type for a single packs
        resp = self.app.post_json('/v1/packs/register', {
            'packs': ['dummy_pack_1'],
            'types': ['action']
        })

        self.assertEqual(resp.status_int, 200)
        self.assertEqual(resp.json, {'actions': 1, 'runners': 15})

        # Verify that plural name form also works
        resp = self.app.post_json('/v1/packs/register', {
            'packs': ['dummy_pack_1'],
            'types': ['actions']
        })

        self.assertEqual(resp.status_int, 200)
        self.assertEqual(resp.json, {'actions': 1, 'runners': 15})

        # Register single resource from a single pack specified multiple times - verify that
        # resources from the same pack are only registered once
        resp = self.app.post_json(
            '/v1/packs/register', {
                'packs': ['dummy_pack_1', 'dummy_pack_1', 'dummy_pack_1'],
                'types': ['actions'],
                'fail_on_failure': False
            })

        self.assertEqual(resp.status_int, 200)
        self.assertEqual(resp.json, {'actions': 1, 'runners': 15})

        # Register resources from a single (non-existent pack)
        resp = self.app.post_json('/v1/packs/register',
                                  {'packs': ['doesntexist']},
                                  expect_errors=True)

        self.assertEqual(resp.status_int, 400)
        self.assertTrue('Pack "doesntexist" not found on disk:' in
                        resp.json['faultstring'])

        # Fail on failure is enabled by default
        resp = self.app.post_json('/v1/packs/register', expect_errors=True)

        expected_msg = 'Failed to register pack "dummy_pack_10":'
        self.assertEqual(resp.status_int, 400)
        self.assertTrue(expected_msg in resp.json['faultstring'])

        # Fail on failure (broken pack metadata)
        resp = self.app.post_json('/v1/packs/register',
                                  {'packs': ['dummy_pack_1']},
                                  expect_errors=True)

        expected_msg = 'Referenced policy_type "action.mock_policy_error" doesnt exist'
        self.assertEqual(resp.status_int, 400)
        self.assertTrue(expected_msg in resp.json['faultstring'])

        # Fail on failure (broken action metadata)
        resp = self.app.post_json('/v1/packs/register',
                                  {'packs': ['dummy_pack_15']},
                                  expect_errors=True)

        expected_msg = 'Failed to register action'
        self.assertEqual(resp.status_int, 400)
        self.assertTrue(expected_msg in resp.json['faultstring'])

        expected_msg = '\'stringa\' is not valid under any of the given schemas'
        self.assertEqual(resp.status_int, 400)
        self.assertTrue(expected_msg in resp.json['faultstring'])
Ejemplo n.º 59
0
    def clone(self, dest_data, ref_or_id, requester_user):
        """
        Clone an action from source pack to destination pack.
        Handles requests:
            POST /actions/{ref_or_id}/clone
        """

        source_action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id)
        if not source_action_db:
            msg = "The requested source for cloning operation doesn't exists"
            abort(http_client.BAD_REQUEST, six.text_type(msg))

        extra = {"action_db": source_action_db}
        LOG.audit("Source action found. Action.id=%s" % (source_action_db.id),
                  extra=extra)

        try:
            permission_type = PermissionType.ACTION_VIEW
            rbac_utils = get_rbac_backend().get_utils_class()
            rbac_utils.assert_user_has_resource_db_permission(
                user_db=requester_user,
                resource_db=source_action_db,
                permission_type=permission_type,
            )
        except ResourceAccessDeniedError as e:
            abort(http_client.UNAUTHORIZED, six.text_type(e))

        cloned_dest_action_db = clone_action_db(
            source_action_db=source_action_db,
            dest_pack=dest_data.dest_pack,
            dest_action=dest_data.dest_action,
        )

        cloned_action_api = ActionAPI.from_model(cloned_dest_action_db)

        try:
            permission_type = PermissionType.ACTION_CREATE
            rbac_utils.assert_user_has_resource_api_permission(
                user_db=requester_user,
                resource_api=cloned_action_api,
                permission_type=permission_type,
            )
        except ResourceAccessDeniedError as e:
            abort(http_client.UNAUTHORIZED, six.text_type(e))

        dest_pack_base_path = get_pack_base_path(pack_name=dest_data.dest_pack)

        if not os.path.isdir(dest_pack_base_path):
            msg = "Destination pack '%s' doesn't exist" % (dest_data.dest_pack)
            abort(http_client.BAD_REQUEST, six.text_type(msg))

        dest_pack_base_path = get_pack_base_path(pack_name=dest_data.dest_pack)
        dest_ref = ".".join([dest_data.dest_pack, dest_data.dest_action])
        dest_action_db = self._get_by_ref(resource_ref=dest_ref)

        try:
            validate_not_part_of_system_pack_by_name(dest_data.dest_pack)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, six.text_type(e))

        if dest_action_db:
            if not dest_data.overwrite:
                msg = "The requested destination action already exists"
                abort(http_client.BAD_REQUEST, six.text_type(msg))

            try:
                permission_type = PermissionType.ACTION_DELETE
                rbac_utils.assert_user_has_resource_db_permission(
                    user_db=requester_user,
                    resource_db=dest_action_db,
                    permission_type=permission_type,
                )
                options = GenericRequestParam(remove_files=True)
                dest_metadata_file = dest_action_db["metadata_file"]
                dest_entry_point = dest_action_db["entry_point"]
                temp_sub_dir = str(uuid.uuid4())
                temp_backup_action_files(
                    dest_pack_base_path,
                    dest_metadata_file,
                    dest_entry_point,
                    temp_sub_dir,
                )
                self.delete(options, dest_ref, requester_user)
            except ResourceAccessDeniedError as e:
                abort(http_client.UNAUTHORIZED, six.text_type(e))
            except Exception as e:
                LOG.debug(
                    "Exception encountered during deleting existing destination action. "
                    "Exception was: %s",
                    e,
                )
                abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))

        try:
            post_response = self.post(cloned_action_api, requester_user)
            if post_response.status_code != http_client.CREATED:
                raise Exception("Could not add cloned action to database.")
            cloned_dest_action_db["id"] = post_response.json["id"]
            clone_action_files(
                source_action_db=source_action_db,
                dest_action_db=cloned_dest_action_db,
                dest_pack_base_path=dest_pack_base_path,
            )
            extra = {"cloned_acion_db": cloned_dest_action_db}
            LOG.audit("Action cloned. Action.id=%s" %
                      (cloned_dest_action_db.id),
                      extra=extra)
            if dest_action_db:
                remove_temp_action_files(temp_sub_dir)
            return post_response
        except PermissionError as e:
            LOG.error("No permission to clone the action. Exception was %s", e)
            delete_action_files_from_pack(
                pack_name=cloned_dest_action_db["pack"],
                entry_point=cloned_dest_action_db["entry_point"],
                metadata_file=cloned_dest_action_db["metadata_file"],
            )
            if post_response.status_code == http_client.CREATED:
                Action.delete(cloned_dest_action_db)
            if dest_action_db:
                self._restore_action(dest_action_db, dest_pack_base_path,
                                     temp_sub_dir)
            abort(http_client.FORBIDDEN, six.text_type(e))
        except Exception as e:
            LOG.error(
                "Exception encountered during cloning action. Exception was %s",
                e,
            )
            delete_action_files_from_pack(
                pack_name=cloned_dest_action_db["pack"],
                entry_point=cloned_dest_action_db["entry_point"],
                metadata_file=cloned_dest_action_db["metadata_file"],
            )
            if post_response.status_code == http_client.CREATED:
                Action.delete(cloned_dest_action_db)
            if dest_action_db:
                self._restore_action(dest_action_db, dest_pack_base_path,
                                     temp_sub_dir)

            abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
Ejemplo n.º 60
0
    def delete(self, options, ref_or_id, requester_user):
        """
        Delete an action.

        Handles requests:
            POST /actions/1?_method=delete
            DELETE /actions/1
            DELETE /actions/mypack.myaction
        """
        action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id)
        action_id = action_db.id

        permission_type = PermissionType.ACTION_DELETE
        rbac_utils = get_rbac_backend().get_utils_class()
        rbac_utils.assert_user_has_resource_db_permission(
            user_db=requester_user,
            resource_db=action_db,
            permission_type=permission_type,
        )

        try:
            validate_not_part_of_system_pack(action_db)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, six.text_type(e))

        LOG.debug(
            "DELETE /actions/ lookup with ref_or_id=%s found object: %s",
            ref_or_id,
            action_db,
        )

        pack_name = action_db["pack"]
        entry_point = action_db["entry_point"]
        metadata_file = action_db["metadata_file"]

        try:
            Action.delete(action_db)
        except Exception as e:
            LOG.error(
                'Database delete encountered exception during delete of id="%s". '
                "Exception was %s",
                action_id,
                e,
            )
            abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
            return

        if options.remove_files:
            try:
                delete_action_files_from_pack(
                    pack_name=pack_name,
                    entry_point=entry_point,
                    metadata_file=metadata_file,
                )
            except PermissionError as e:
                LOG.error("No permission to delete resource files from disk.")
                action_db.id = None
                Action.add_or_update(action_db)
                abort(http_client.FORBIDDEN, six.text_type(e))
                return
            except Exception as e:
                LOG.error(
                    "Exception encountered during deleting resource files from disk. "
                    "Exception was %s",
                    e,
                )
                action_db.id = None
                Action.add_or_update(action_db)
                abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
                return

        extra = {"action_db": action_db}
        LOG.audit("Action deleted. Action.id=%s" % (action_db.id), extra=extra)
        return Response(status=http_client.NO_CONTENT)