コード例 #1
0
    def test_image_member_list(self):
        with mock.patch('glanceclient.v2.image_members.Controller.list',
                        return_value=self.members_image_members):
            serialized = self.plugin.serialize(self.members_image)

        # Admin context
        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search', is_admin=True
        )
        result_hit = {'_source': copy.deepcopy(serialized)}

        # Expect to see all three tenants
        self.plugin.filter_result(result_hit, fake_request.context)
        self.assertEqual(set([TENANT1, TENANT2, TENANT3]),
                         set(result_hit['_source']['members']))

        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search', is_admin=False
        )
        result_hit = {'_source': copy.deepcopy(serialized)}

        # Tenant1 can see the image but doesn't own it
        self.plugin.filter_result(result_hit, fake_request.context)
        self.assertEqual(set([TENANT1]),
                         set(result_hit['_source']['members']))

        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT2, '/v1/search', is_admin=False
        )
        result_hit = {'_source': copy.deepcopy(serialized)}

        # Tenant2 owns the image and should see all three members
        self.plugin.filter_result(result_hit, fake_request.context)
        self.assertEqual(set([TENANT1, TENANT2, TENANT3]),
                         set(result_hit['_source']['members']))
コード例 #2
0
    def test_image_member_list(self):
        with mock.patch('glanceclient.v2.image_members.Controller.list',
                        return_value=self.members_image_members):
            serialized = self.plugin.serialize(self.members_image)

        # Admin context
        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search', is_admin=True
        )
        result_hit = {'_source': copy.deepcopy(serialized)}

        # Expect to see all three tenants
        self.plugin.filter_result(result_hit, fake_request.context)
        self.assertEqual(set([TENANT1, TENANT2, TENANT3]),
                         set(result_hit['_source']['members']))

        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search', is_admin=False
        )
        result_hit = {'_source': copy.deepcopy(serialized)}

        # Tenant1 can see the image but doesn't own it
        self.plugin.filter_result(result_hit, fake_request.context)
        self.assertEqual(set([TENANT1]),
                         set(result_hit['_source']['members']))

        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT2, '/v1/search', is_admin=False
        )
        result_hit = {'_source': copy.deepcopy(serialized)}

        # Tenant2 owns the image and should see all three members
        self.plugin.filter_result(result_hit, fake_request.context)
        self.assertEqual(set([TENANT1, TENANT2, TENANT3]),
                         set(result_hit['_source']['members']))
コード例 #3
0
    def test_facets_all_projects(self):
        # For non admins, all_projects should have no effect
        mock_engine = mock.Mock()
        self.plugin.engine = mock_engine

        # Don't really care about the return values
        mock_engine.search.return_value = {'aggregations': {}}

        fake_request = unit_test_utils.get_fake_request(USER1,
                                                        TENANT1,
                                                        '/v1/search/facets',
                                                        is_admin=False)

        self.plugin.get_facets(fake_request.context, all_projects=True)

        expected_agg_query_filter = {
            'filtered': {
                'filter': {
                    'and': [{
                        'term': {
                            ROLE_USER_FIELD: 'user'
                        }
                    }, {
                        'term': {
                            'tenant_id': TENANT1
                        }
                    }]
                }
            }
        }

        # Call args are a tuple (name, posargs, kwargs)
        search_call = mock_engine.search.mock_calls[0]
        search_call_body = search_call[2]['body']
        self.assertEqual(set(['aggs', 'query']), set(search_call_body.keys()))

        # The aggregation query's tested elsewhere, just check the query filter
        self.assertEqual(expected_agg_query_filter, search_call_body['query'])

        # Admins can request all_projects
        fake_request = unit_test_utils.get_fake_request(USER1,
                                                        TENANT1,
                                                        '/v1/search/facets',
                                                        is_admin=True)

        self.plugin.get_facets(fake_request.context, all_projects=True)

        # Test the SECOND call to the mock
        search_call = mock_engine.search.mock_calls[1]
        search_call_body = search_call[2]['body']

        # We don't expect any filter query here, just the aggregations.
        self.assertEqual(set(['aggs', 'query']), set(search_call_body.keys()))
コード例 #4
0
    def test_facets_all_projects(self):
        # For non admins, all_projects should have no effect
        mock_engine = mock.Mock()
        self.plugin.engine = mock_engine

        # Don't really care about the return values
        mock_engine.search.return_value = {
            'aggregations': {}
        }

        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search/facets', is_admin=False
        )

        self.plugin.get_facets(fake_request.context, all_projects=True)

        expected_agg_query_filter = {
            'filtered': {
                'filter': {
                    'and': [
                        {'term': {ROLE_USER_FIELD: 'user'}},
                        {'term': {'tenant_id': TENANT1}}
                    ]
                }
            }
        }

        # Call args are a tuple (name, posargs, kwargs)
        search_call = mock_engine.search.mock_calls[0]
        search_call_body = search_call[2]['body']
        self.assertEqual(set(['aggs', 'query']), set(search_call_body.keys()))

        # The aggregation query's tested elsewhere, just check the query filter
        self.assertEqual(expected_agg_query_filter, search_call_body['query'])

        # Admins can request all_projects
        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search/facets', is_admin=True
        )

        self.plugin.get_facets(fake_request.context, all_projects=True)

        # Test the SECOND call to the mock
        search_call = mock_engine.search.mock_calls[1]
        search_call_body = search_call[2]['body']

        # We don't expect any filter query here, just the aggregations.
        self.assertEqual(set(['aggs', 'query']), set(search_call_body.keys()))
コード例 #5
0
    def test_protected_properties(self):
        with mock.patch(nova_server_getter, return_value=self.instance1):
            serialized = self.plugin.serialize(self.instance1.id)

        elasticsearch_results = {
            "hits": {
                "hits": [
                    {
                        "_source": copy.deepcopy(serialized),
                        "_type": self.plugin.get_document_type(),
                        "_index": self.plugin.get_index_name(),
                    }
                ]
            }
        }

        protected_fields = (u"OS-EXT-SRV-ATTR:host", u"OS-EXT-SRV-ATTR:hypervisor_hostname")

        fake_request = unit_test_utils.get_fake_request(USER1, TENANT1, "/v1/search", is_admin=True)
        self.plugin.filter_result(elasticsearch_results["hits"]["hits"][0], fake_request.context)

        # Result should contain all the fields
        single_result = elasticsearch_results["hits"]["hits"][0]["_source"]
        self.assertEqual(serialized, single_result)
        for field in protected_fields:
            self.assertTrue(field in single_result)

        # Refresh the mock results since they can be modified in-place
        elasticsearch_results = {
            "hits": {
                "hits": [
                    {
                        "_source": copy.deepcopy(serialized),
                        "_type": self.plugin.get_document_type(),
                        "_index": self.plugin.get_index_name(),
                    }
                ]
            }
        }
        # Make the same request as a non-admin
        fake_request = unit_test_utils.get_fake_request(USER1, TENANT1, "/v1/search", is_admin=False)

        self.plugin.filter_result(elasticsearch_results["hits"]["hits"][0], fake_request.context)

        single_result = elasticsearch_results["hits"]["hits"][0]["_source"]

        for field in protected_fields:
            self.assertFalse(field in single_result)
コード例 #6
0
    def test_facets(self):
        request = unit_test_utils.get_fake_request()
        doc_types = ["OS::Glance::Image", "OS::Nova::Server"]
        gf_path = 'searchlight.elasticsearch.plugins.base.IndexBase.get_facets'
        with mock.patch(gf_path) as mock_facets:
            mock_facets.return_value = [{"name": "fake", "type": "string"}], 0

            default_response = self.search_controller.facets(
                request, doc_type=doc_types)

            expected = {
                "OS::Nova::Server": {
                    "doc_count": 0,
                    "facets": [{"name": "fake", "type": "string"}]
                },
                "OS::Glance::Image": {
                    "doc_count": 0,
                    "facets": [{"name": "fake", "type": "string"}]
                }
            }
            self.assertEqual(expected, default_response)

            totals_only_response = self.search_controller.facets(
                request, doc_type=doc_types, include_fields=False)

            expected = {"OS::Nova::Server": {"doc_count": 0},
                        "OS::Glance::Image": {"doc_count": 0}}
            self.assertEqual(expected, totals_only_response)
コード例 #7
0
    def test_policy_all_disallowed(self):
        request = unit_test_utils.get_fake_request(is_admin=False)
        search_deserializer = search.RequestDeserializer(
            utils.get_search_plugins(), policy_enforcer=self.enforcer)

        types = ['OS::Glance::Image']
        self.enforcer.add_rules(
            policy.policy.Rules.from_dict({
                'resource:OS::Glance::Image': '!',
                'resource:OS::Nova::Server': '!',
            }))

        expected_message = (
            "There are no resource types accessible to you to serve "
            "your request. You do not have access to the following "
            "resource types: OS::Glance::Image")
        self.assertRaisesRegex(webob.exc.HTTPForbidden, expected_message,
                               search_deserializer._filter_types_by_policy,
                               request.context, types)

        types = ['OS::Glance::Image', 'OS::Nova::Server']
        expected_message = (
            "There are no resource types accessible to you to serve "
            "your request. You do not have access to the following "
            "resource types: OS::Glance::Image, OS::Nova::Server")
        self.assertRaisesRegex(webob.exc.HTTPForbidden, expected_message,
                               search_deserializer._filter_types_by_policy,
                               request.context, types)
コード例 #8
0
    def test_facets_no_mapping(self):
        mock_engine = mock.Mock()
        self.plugin.engine = mock_engine

        fake_request = unit_test_utils.get_fake_request(USER1,
                                                        TENANT1,
                                                        '/v1/search/facets',
                                                        is_admin=True)

        mock_engine.search.return_value = {
            'aggregations': {
                'status': {
                    'buckets': []
                },
                'image.id': {
                    'doc_count': 0
                }
            }
        }

        facets = self.plugin.get_facets(fake_request.context)

        status_facet = list(filter(lambda f: f['name'] == 'status', facets))[0]
        image_facet = list(filter(lambda f: f['name'] == 'image.id',
                                  facets))[0]
        expected_status = {'name': 'status', 'options': [], 'type': 'string'}
        expected_image = {
            'name': 'image.id',
            'options': [],
            'type': 'string',
            'resource_type': 'OS::Glance::Image'
        }

        self.assertEqual(expected_status, status_facet)
        self.assertEqual(expected_image, image_facet)
コード例 #9
0
 def test_rbac_filter(self):
     fake_request = unit_test_utils.get_fake_request(USER1,
                                                     TENANT1,
                                                     '/v1/search',
                                                     is_admin=False)
     rbac_terms = self.plugin._get_rbac_field_filters(fake_request.context)
     self.assertEqual([{
         'bool': {
             'should': [{
                 'term': {
                     'tenant_id': TENANT1
                 }
             }, {
                 'terms': {
                     'members': [TENANT1, '*']
                 }
             }, {
                 'term': {
                     'router:external': True
                 }
             }, {
                 'term': {
                     'shared': True
                 }
             }]
         }
     }], rbac_terms)
コード例 #10
0
    def test_facets(self):
        fake_request = unit_test_utils.get_fake_request(USER1, TENANT1, "/v1/search/facets", is_admin=False)

        mock_engine = mock.Mock()
        self.plugin.engine = mock_engine

        mock_engine.search.return_value = {
            "aggregations": {
                "status": {"buckets": [{"key": "pending", "doc_count": 2}]},
                "type": {"buckets": [{"key": "PRIMARY", "doc_count": 2}]},
            }
        }

        facets = self.plugin.get_facets(fake_request.context)

        status_facet = list(filter(lambda f: f["name"] == "status", facets))[0]
        expected_status = {"name": "status", "options": [{"key": "pending", "doc_count": 2}], "type": "string"}
        self.assertEqual(expected_status, status_facet)

        expected_agg_query = {
            "aggs": dict(unit_test_utils.simple_facet_field_agg(name) for name in ("status", "type")),
            "query": {"filtered": {"filter": {"and": [{"term": {"project_id": TENANT1}}]}}},
        }
        mock_engine.search.assert_called_with(
            index=self.plugin.get_index_name(),
            doc_type=self.plugin.get_document_type(),
            body=expected_agg_query,
            ignore_unavailable=True,
            search_type="count",
        )
コード例 #11
0
ファイル: test_api_policy.py プロジェクト: sjmc7/searchlight
    def test_policy_all_disallowed(self):
        request = unit_test_utils.get_fake_request(is_admin=False)
        search_deserializer = search.RequestDeserializer(
            utils.get_search_plugins(),
            policy_enforcer=self.enforcer)

        types = ['OS::Glance::Image']
        self.enforcer.add_rules(policy.policy.Rules.from_dict({
            'resource:OS::Glance::Image': '!',
            'resource:OS::Nova::Server': '!',
        }))

        expected_message = (
            "There are no resource types accessible to you to serve "
            "your request. You do not have access to the following "
            "resource types: OS::Glance::Image")
        self.assertRaisesRegex(
            webob.exc.HTTPForbidden, expected_message,
            search_deserializer._filter_types_by_policy,
            request.context, types)

        types = ['OS::Glance::Image', 'OS::Nova::Server']
        expected_message = (
            "There are no resource types accessible to you to serve "
            "your request. You do not have access to the following "
            "resource types: OS::Glance::Image, OS::Nova::Server")
        self.assertRaisesRegex(
            webob.exc.HTTPForbidden, expected_message,
            search_deserializer._filter_types_by_policy,
            request.context, types)
コード例 #12
0
    def test_resource_policy_allows_admin(self):
        request = unit_test_utils.get_fake_request(is_admin=True)
        search_deserializer = search.RequestDeserializer(
            utils.get_search_plugins(),
            policy_enforcer=self.enforcer)
        types = ['OS::Glance::Image', 'OS::Nova::Server']

        self.enforcer.add_rules(policy.policy.Rules.from_dict({
            'resource:OS::Glance::Image:allow': 'role:admin',
            'resource:OS::Nova::Server:query': 'role:admin'
        }))

        request = unit_test_utils.get_fake_request(is_admin=True)
        filtered_types = search_deserializer._filter_types_by_policy(
            request.context, types, "query")
        self.assertEqual(types, filtered_types)
コード例 #13
0
    def test_empty_request(self):
        """Tests that ALL registered resource types are searched"""
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({}))

        output = self.deserializer.search(request)
        self.assertEqual(['searchlight-search'], output['index'])

        types = [
            'OS::Designate::RecordSet',
            'OS::Designate::Zone',
            'OS::Glance::Image',
            'OS::Glance::Metadef',
            'OS::Ironic::Chassis',
            'OS::Ironic::Node',
            'OS::Ironic::Port',
            'OS::Nova::Flavor',
            'OS::Nova::Server',
            'OS::Nova::ServerGroup',
            'OS::Nova::Hypervisor',
            'OS::Neutron::FloatingIP',
            'OS::Neutron::Net',
            'OS::Neutron::Port',
            'OS::Neutron::Subnet',
            'OS::Neutron::Router',
            'OS::Neutron::SecurityGroup',
            'OS::Cinder::Volume',
            'OS::Cinder::Snapshot'
        ]

        self.assertEqual(['searchlight-search'], output['index'])
        self.assertEqual(sorted(types), sorted(output['doc_type']))
コード例 #14
0
ファイル: test_plugin.py プロジェクト: sebrandon1/searchlight
    def test_filter_result(self):
        """Verify that any highlighted query results will filter out
           the ROLE_USER_FIELD field.
        """
        request = unit_test_utils.get_fake_request(is_admin=True)
        mock_engine = mock.Mock()
        simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine)

        # Verify with ROLE_USER_FIELD
        hit = {"_source": {"owner": "<em>admin</em>"},
               "highlight": {
                   "owner": "<em>admin</em>",
                   "__searchlight-user-role": "<em>admin</em>"}}

        simple_plugin.filter_result(hit, request.context)
        self.assertNotIn('__searchlight-user-role', hit['highlight'])

        # Verify without ROLE_USER_FIELD
        hit = {"_source": {"owner": "<em>admin</em>"},
               "highlight": {
                   "owner": "<em>admin</em>"}}

        original_hit = copy.deepcopy(hit)
        simple_plugin.filter_result(hit, request.context)
        self.assertEqual(original_hit, hit)
コード例 #15
0
    def test_create_multiple(self):
        actions = [
            _image_fixture('create', '1'),
            _image_fixture('create', '2', data={'name': 'image-2'}),
        ]

        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'actions': actions,
        }))

        output = self.deserializer.index(request)
        expected = {
            'actions': [
                {
                    '_id': '1',
                    '_index': 'searchlight',
                    '_op_type': 'create',
                    '_source': {'disk_format': 'raw', 'name': 'image-1'},
                    '_type': 'OS::Glance::Image'
                },
                {
                    '_id': '2',
                    '_index': 'searchlight',
                    '_op_type': 'create',
                    '_source': {'disk_format': 'raw', 'name': 'image-2'},
                    '_type': 'OS::Glance::Image'
                },
            ],
            'default_index': None,
            'default_type': None
        }
        self.assertEqual(expected, output)
コード例 #16
0
    def test_multiple_sort(self):
        """Test multiple sort fields"""
        request = unit_test_utils.get_fake_request()
        request.body = six.b(
            jsonutils.dumps({
                'query': {
                    'match_all': {}
                },
                'sort': [
                    'status', {
                        'created_at': 'desc'
                    }, {
                        'members': {
                            'order': 'asc',
                            'mode': 'max'
                        }
                    }
                ]
            }))

        output = self.deserializer.search(request)
        expected = [
            'status', {
                'created_at': 'desc'
            }, {
                'members': {
                    'order': 'asc',
                    'mode': 'max'
                }
            }
        ]
        self.assertEqual(expected, output['query']['sort'])
コード例 #17
0
    def test_plugins_info_not_found(self):
        request = unit_test_utils.get_fake_request()
        repo = searchlight.elasticsearch.CatalogSearchRepo
        repo.plugins_info = mock.Mock(side_effect=exception.NotFound)

        self.assertRaises(webob.exc.HTTPNotFound,
                          self.search_controller.plugins_info, request)
コード例 #18
0
    def test_plugins_info_internal_server_error(self):
        request = unit_test_utils.get_fake_request()
        repo = searchlight.elasticsearch.CatalogSearchRepo
        repo.plugins_info = mock.Mock(side_effect=Exception)

        self.assertRaises(webob.exc.HTTPInternalServerError,
                          self.search_controller.plugins_info, request)
コード例 #19
0
    def test_global_aggregation_not_allowed(self):
        """The 'global' aggregation type bypasses the search query (thus
        bypassing RBAC). This is Bad, so we won't allow it. It can only occur
        as a top level aggregation.
        """
        request = unit_test_utils.get_fake_request()

        aggs = {
            'cheating_rbac': {
                'global': {},
                'aggregations': {
                    'name': {
                        'terms': {
                            'field': 'name'
                        }
                    }
                }
            }
        }
        request.body = six.b(
            jsonutils.dumps({
                'type': ['OS::Glance::Metadef'],
                'query': {
                    'match_all': {}
                },
                'aggregations': aggs
            }))

        self.assertRaises(webob.exc.HTTPForbidden, self.deserializer.search,
                          request)
コード例 #20
0
    def test_delete_multiple(self):
        action_1 = _image_fixture('delete', '1')
        action_1.pop('data')
        action_2 = _image_fixture('delete', '2')
        action_2.pop('data')

        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'actions': [action_1, action_2],
        }))

        output = self.deserializer.index(request)
        expected = {
            'actions': [
                {
                    '_id': '1',
                    '_index': 'searchlight',
                    '_op_type': 'delete',
                    '_source': {},
                    '_type': 'OS::Glance::Image'
                },
                {
                    '_id': '2',
                    '_index': 'searchlight',
                    '_op_type': 'delete',
                    '_source': {},
                    '_type': 'OS::Glance::Image'
                },
            ],
            'default_index': None,
            'default_type': None
        }
        self.assertEqual(expected, output)
コード例 #21
0
    def test_search_aggregations(self):
        request = unit_test_utils.get_fake_request()
        with mock.patch(REPO_SEARCH, return_value={}) as mock_search:
            query = {
                "query": {
                    "match_all": {}
                },
                "aggs": {
                    "test": {
                        "terms": {
                            "field": "some_field"
                        }
                    }
                }
            }
            index_name = "searchlight"
            limit = 10
            offset = 0
            doc_type = "OS::Glance::Image"

            self.search_controller.search(request,
                                          query,
                                          index_name,
                                          doc_type,
                                          offset,
                                          limit,
                                          version=True)

            mock_search.assert_called_once_with(index_name,
                                                doc_type,
                                                query,
                                                offset,
                                                limit,
                                                ignore_unavailable=True,
                                                version=True)
コード例 #22
0
    def test_nested_object_facets(self):
        """Check 'nested' and 'object' types are treated the same for facets"""
        mock_engine = mock.Mock()
        plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine)
        fake_request = unit_test_utils.get_fake_request(
            'a', 'b', '/v1/search/facets', is_admin=True
        )

        mock_engine.search.return_value = {
            "hits": {"total": 1}
        }

        fake_mapping = {
            "properties": {
                "nested": {
                    "type": "nested",
                    "properties": {"inner": {"type": "string"}}
                },
                "object": {
                    "type": "object",
                    "properties": {"inner": {"type": "string"}}
                }
            }
        }
        with mock.patch.object(plugin, 'get_mapping',
                               return_value=fake_mapping):
            facets, _ = plugin.get_facets(fake_request.context)
            facets = sorted(facets, key=operator.itemgetter("name"))
            expected = [
                {"name": "nested.inner", "type": "string", "nested": True},
                {"name": "object.inner", "type": "string", "nested": False},
            ]

            self.assertEqual(expected, facets)
コード例 #23
0
    def test_rbac_non_admin(self):
        """Test that a non-admin request results in an RBACed query"""
        request = unit_test_utils.get_fake_request(is_admin=False)
        request.body = jsonutils.dumps({
            'query': {
                'match_all': {}
            },
            'type': 'OS::Nova::Server',
        }).encode("latin-1")
        output = self.deserializer.search(request)
        tenant_id = '6838eb7b-6ded-dead-beef-b344c77fe8df'

        nova_rbac_filter = {
            'indices': {
                'query': {
                    'bool': {
                        'filter': {
                            'bool': {
                                'must': {
                                    'type': {
                                        'value': 'OS::Nova::Server'
                                    }
                                },
                                'should': [{
                                    'term': {
                                        'tenant_id': tenant_id
                                    }
                                }],
                                'minimum_should_match': 1
                            }
                        }
                    }
                },
                'index': 'searchlight-search',
                'no_match_query': 'none'
            }
        }

        role_field = searchlight.elasticsearch.ROLE_USER_FIELD
        expected_query = {
            'query': {
                'bool': {
                    'filter': {
                        'bool': {
                            'must': {
                                'term': {
                                    role_field: 'user'
                                }
                            },
                            'should': [nova_rbac_filter],
                            'minimum_should_match': 1
                        }
                    },
                    'must': {
                        'match_all': {}
                    }
                }
            }
        }
        self.assertEqual(expected_query, output['query'])
コード例 #24
0
    def test_plugins_info(self):
        request = unit_test_utils.get_fake_request()
        expected = {
            "plugins": [
                {
                    "index": "searchlight",
                    "type": "OS::Designate::RecordSet",
                    "name": "OS::Designate::RecordSet"
                },
                {
                    "index": "searchlight",
                    "type": "OS::Designate::Zone",
                    "name": "OS::Designate::Zone"
                },
                {
                    "index": "searchlight", "type": "OS::Glance::Image",
                    "name": "OS::Glance::Image"
                },
                {
                    "index": "searchlight", "type": "OS::Glance::Metadef",
                    "name": "OS::Glance::Metadef"
                },
                {
                    "index": "searchlight", "type": "OS::Nova::Server",
                    "name": "OS::Nova::Server"
                }
            ]
        }

        actual = self.search_controller.plugins_info(request)
        self.assertEqual(sorted(expected), sorted(actual))
コード例 #25
0
    def test_filter_result(self):
        """Verify that any highlighted query results will filter out
           the ROLE_USER_FIELD field.
        """
        request = unit_test_utils.get_fake_request(is_admin=True)
        mock_engine = mock.Mock()
        simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine)

        # Verify with ROLE_USER_FIELD
        hit = {
            "_source": {
                "owner": "<em>admin</em>"
            },
            "highlight": {
                "owner": "<em>admin</em>",
                "__searchlight-user-role": "<em>admin</em>"
            }
        }

        simple_plugin.filter_result(hit, request.context)
        self.assertNotIn('__searchlight-user-role', hit['highlight'])

        # Verify without ROLE_USER_FIELD
        hit = {
            "_source": {
                "owner": "<em>admin</em>"
            },
            "highlight": {
                "owner": "<em>admin</em>"
            }
        }

        original_hit = copy.deepcopy(hit)
        simple_plugin.filter_result(hit, request.context)
        self.assertEqual(original_hit, hit)
コード例 #26
0
    def test_search_policy_check(self, _):
        request = unit_test_utils.get_fake_request()
        with mock.patch.object(self.search_controller.policy,
                               'enforce') as mock_enforce:

            self.search_controller.search(request, query={"match_all": {}})
            mock_enforce.assert_called_with(request.context, 'query', {})
コード例 #27
0
 def test_metadef_rbac(self):
     """Test metadefs RBAC query terms"""
     fake_request = unit_test_utils.get_fake_request(
         USER1, TENANT1, '/v1/search'
     )
     rbac_filter = self.plugin.get_query_filters(fake_request.context)
     expected_fragment = {
         "indices": {
             "index": "searchlight-search",
             "no_match_query": "none",
             "query": {
                 "bool": {
                     "filter": {
                         "bool": {
                             "must": {
                                 "type": {"value": "OS::Glance::Metadef"}
                             },
                             "should": [
                                 {"term": {"owner": TENANT1}},
                                 {"term": {"visibility": "public"}},
                             ],
                             "minimum_should_match": 1
                         }
                     }
                 }
             }
         }
     }
     self.assertEqual(expected_fragment, rbac_filter)
コード例 #28
0
    def test_image_rbac(self):
        """Test the image plugin RBAC query terms"""
        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search'
        )
        rbac_query_fragment = self.plugin.get_query_filters(
            fake_request.context)
        expected_fragment = {
            "indices": {
                "index": "searchlight-search",
                "no_match_filter": "none",
                "filter": {
                    "and": [
                        {
                            "type": {"value": "OS::Glance::Image"}
                        },
                        {
                            "or": [
                                {"term": {"owner": TENANT1}},
                                {"term": {"visibility": "public"}},
                                {"term": {"members": TENANT1}}
                            ]
                        }
                    ]
                },
            }
        }

        self.assertEqual(expected_fragment, rbac_query_fragment)
コード例 #29
0
    def test_image_rbac(self):
        """Test the image plugin RBAC query terms"""
        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search'
        )
        rbac_query_fragment = self.plugin.get_rbac_filter(fake_request.context)
        expected_fragment = [{
            "indices": {
                "index": "searchlight",
                "no_match_filter": "none",
                "filter": {
                    "and": [
                        {
                            "or": [
                                {"term": {"owner": TENANT1}},
                                {"term": {"visibility": "public"}},
                                {"term": {"members": TENANT1}}
                            ]
                        },
                        {
                            "type": {"value": "OS::Glance::Image"}
                        },
                    ]
                },
            }
        }]

        self.assertEqual(expected_fragment, rbac_query_fragment)
コード例 #30
0
 def test_rbac_filters(self):
     fake_request = unit_test_utils.get_fake_request(
         USER1, TENANT1, '/v1/search', is_admin=False
     )
     self.assertEqual(
         [{"term": {"project_id": TENANT1}}],
         self.plugin._get_rbac_field_filters(fake_request.context))
コード例 #31
0
    def test_image_rbac(self):
        """Test the image plugin RBAC query terms"""
        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search'
        )
        rbac_query_fragment = self.plugin.get_query_filters(
            fake_request.context)
        expected_fragment = {
            "indices": {
                "index": "searchlight-search",
                "no_match_query": "none",
                "query": {
                    "bool": {
                        "filter": {
                            "bool": {
                                "must": {
                                    "type": {"value": "OS::Glance::Image"}
                                },
                                "should": [
                                    {"term": {"owner": TENANT1}},
                                    {"term": {"visibility": "public"}},
                                    {"term": {"members": TENANT1}}
                                ],
                                'minimum_should_match': 1
                            }
                        }
                    }
                },
            }
        }

        self.assertEqual(expected_fragment, rbac_query_fragment)
コード例 #32
0
    def test_facets_no_mapping(self):
        mock_engine = mock.Mock()
        self.plugin.engine = mock_engine

        fake_request = unit_test_utils.get_fake_request(
            USER1, TENANT1, '/v1/search/facets', is_admin=True
        )

        mock_engine.search.return_value = {
            'aggregations': {
                'status': {'buckets': []},
                'image.id': {'doc_count': 0}
            }
        }

        facets = self.plugin.get_facets(fake_request.context)

        status_facet = list(filter(lambda f: f['name'] == 'status',
                                   facets))[0]
        image_facet = list(filter(lambda f: f['name'] == 'image.id',
                                  facets))[0]
        expected_status = {'name': 'status', 'options': [], 'type': 'string'}
        expected_image = {'name': 'image.id', 'options': [], 'type': 'string'}

        self.assertEqual(expected_status, status_facet)
        self.assertEqual(expected_image, image_facet)
コード例 #33
0
ファイル: test_plugin.py プロジェクト: sebrandon1/searchlight
    def test_nested_object_facets(self):
        """Check 'nested' and 'object' types are treated the same for facets"""
        mock_engine = mock.Mock()
        plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine)
        fake_request = unit_test_utils.get_fake_request(
            'a', 'b', '/v1/search/facets', is_admin=True
        )

        mock_engine.search.return_value = {
            "hits": {"total": 1}
        }

        fake_mapping = {
            "properties": {
                "nested": {
                    "type": "nested",
                    "properties": {"inner": {"type": "string"}}
                },
                "object": {
                    "type": "object",
                    "properties": {"inner": {"type": "string"}}
                }
            }
        }
        with mock.patch.object(plugin, 'get_mapping',
                               return_value=fake_mapping):
            facets, _ = plugin.get_facets(fake_request.context)
            facets = sorted(facets, key=operator.itemgetter("name"))
            expected = [
                {"name": "nested.inner", "type": "string", "nested": True},
                {"name": "object.inner", "type": "string", "nested": False},
            ]

            self.assertEqual(expected, facets)
コード例 #34
0
ファイル: test_search.py プロジェクト: gongwayne/Openstack
    def test_search_policy_check(self, _):
        request = unit_test_utils.get_fake_request()
        with mock.patch.object(self.search_controller.policy,
                               'enforce') as mock_enforce:

            self.search_controller.search(request, query={"match_all": {}})
            mock_enforce.assert_called_with(request.context, 'query', {})
コード例 #35
0
 def test_rbac_filter(self):
     fake_request = unit_test_utils.get_fake_request(USER1,
                                                     TENANT1,
                                                     '/v1/search',
                                                     is_admin=False)
     rbac_terms = self.plugin._get_rbac_field_filters(fake_request.context)
     self.assertEqual([{"term": {"id": AUTH_PREFIX + TENANT1}}], rbac_terms)
コード例 #36
0
    def test_default_facet_options(self):
        request = unit_test_utils.get_fake_request(path='/v1/search/facets')
        output = self.deserializer.facets(request)

        expected = {'index_name': None, 'doc_type': None,
                    'all_projects': False, 'limit_terms': 0}
        self.assertEqual(expected, output)
コード例 #37
0
ファイル: test_plugin.py プロジェクト: sebrandon1/searchlight
 def test_facets(self):
     """If you have a weak constitution, we may want to avert your eyes
        now. We want to verify that the "exclude_options" parameter for
        facets will not result in any aggregation in the Elasticsearch
        query. The actual ES query is buried in the bowels of Searchlight.
        Instead of trying to call it directly through the searchcontroller
        and mock mutliple levels of Servers/Requests/Catalogs/etc we will
        go directly to the IndexBase call.
     """
     request = unit_test_utils.get_fake_request(is_admin=True)
     mock_engine = mock.Mock()
     simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine)
     mock_engine.search.return_value = {"hits": {"total": 0}}
     simple_plugin._get_facet_terms(fields={},
                                    request_context=request.context,
                                    all_projects=False, limit_terms=False,
                                    exclude_options=True)
     # Verify there is no aggregation when searching Elasticsearch.
     body = {'query': {
             'filtered': {'filter': {'and':
                          [{'term': {
                            '__searchlight-user-role': 'admin'}}]}}}
             }
     mock_engine.search.assert_called_with(body=body,
                                           doc_type='fake-simple',
                                           ignore_unavailable=True,
                                           index='searchlight-search',
                                           size=0)
コード例 #38
0
 def test_rbac_filter_admin_role(self):
     fake_request = unit_test_utils.get_fake_request(
         USER1, TENANT1, '/v1/search', is_admin=True
     )
     rbac_terms = self.plugin._get_rbac_field_filters(fake_request.context)
     expected_rbac = [
         {
             "or": [
                 {
                     'term': {'tenant_id': TENANT1}
                 },
                 {
                     'has_parent': {
                         'type': self.plugin.parent_plugin_type(),
                         'query': {
                             "bool": {
                                 "should": [
                                     {'term': {'shared': True}},
                                     {'term': {'router:external': True}}
                                 ]
                             }
                         }
                     }
                 }
             ]
         }
     ]
     self.assertEqual(expected_rbac, rbac_terms)
コード例 #39
0
    def test_plugins_info(self):
        request = unit_test_utils.get_fake_request()
        expected = {
            "plugins": [{
                "index": "searchlight-search",
                "type": "OS::Designate::RecordSet",
                "name": "OS::Designate::RecordSet"
            }, {
                "index": "searchlight-search",
                "type": "OS::Designate::Zone",
                "name": "OS::Designate::Zone"
            }, {
                "index": "searchlight-search",
                "type": "OS::Glance::Image",
                "name": "OS::Glance::Image"
            }, {
                "index": "searchlight-search",
                "type": "OS::Glance::Metadef",
                "name": "OS::Glance::Metadef"
            }, {
                "index": "searchlight-search",
                "type": "OS::Nova::Server",
                "name": "OS::Nova::Server"
            }]
        }

        # Simulate policy filtering
        doc_types = [p['name'] for p in expected['plugins']]
        actual = self.search_controller.plugins_info(request, doc_types)
        self.assertEqual(['plugins'], list(actual.keys()))

        self.assertEqual(
            sorted(expected['plugins'], key=operator.itemgetter('name')),
            sorted(actual['plugins'], key=operator.itemgetter('name')))
コード例 #40
0
    def test_invalid_type(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'type': 'invalid',
        }))

        self.assertRaises(webob.exc.HTTPBadRequest, self.deserializer.index,
                          request)
コード例 #41
0
 def test_facet_policy(self):
     request = unit_test_utils.get_fake_request()
     search_repo = mock.Mock()
     with mock.patch.object(self.enforcer, 'enforce') as mock_enforce:
         repo = policy.CatalogSearchRepoProxy(search_repo, request.context,
                                              self.enforcer)
         repo.facets()
         mock_enforce.assert_called_with(request.context, 'facets', {})
コード例 #42
0
ファイル: test_search.py プロジェクト: gongwayne/Openstack
    def test_forbidden_self(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'self': {},
        }))

        self.assertRaises(webob.exc.HTTPForbidden, self.deserializer.search,
                          request)
コード例 #43
0
    def test_forbidden_schema(self):
        request = unit_test_utils.get_fake_request()
        request.body = jsonutils.dumps({
            'schema': {},
        }).encode("latin-1")

        self.assertRaises(webob.exc.HTTPForbidden, self.deserializer.search,
                          request)
コード例 #44
0
    def test_empty_operation_type(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'actions': [_image_fixture('', '1')]
        }))

        self.assertRaises(webob.exc.HTTPBadRequest, self.deserializer.index,
                          request)
コード例 #45
0
    def test_single_index(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'index': 'searchlight-search',
        }))

        output = self.deserializer.search(request)
        self.assertEqual(['searchlight-search'], output['index'])
コード例 #46
0
 def test_context_policy_target(self):
     request = unit_test_utils.get_fake_request()
     expected = {
         'user_id': unit_test_utils.SOMEUSER,
         'project_id': unit_test_utils.SOMETENANT,
         'tenant_id': unit_test_utils.SOMETENANT
     }
     self.assertEqual(expected, request.context.policy_target)
コード例 #47
0
    def test_forbidden_self(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'self': {},
        }))

        self.assertRaises(webob.exc.HTTPForbidden, self.deserializer.search,
                          request)
コード例 #48
0
    def test_create_invalid_index(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'actions': [_image_fixture('create', index='invalid')]
        }))

        self.assertRaises(webob.exc.HTTPBadRequest, self.deserializer.index,
                          request)
コード例 #49
0
    def test_create_missing_doc_type(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'actions': [_image_fixture('create', '1', doc_type=None)]
        }))

        self.assertRaises(webob.exc.HTTPBadRequest, self.deserializer.index,
                          request)
コード例 #50
0
ファイル: test_search.py プロジェクト: gongwayne/Openstack
    def test_single_index(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'index': 'searchlight-search',
        }))

        output = self.deserializer.search(request)
        self.assertEqual(['searchlight-search'], output['index'])
コード例 #51
0
    def test_missing_actions(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'default_type': 'OS::Glance::Image'
        }))

        self.assertRaises(webob.exc.HTTPBadRequest, self.deserializer.index,
                          request)
コード例 #52
0
 def test_search_version(self):
     request = unit_test_utils.get_fake_request(is_admin=True)
     request.body = six.b(jsonutils.dumps({
         'query': {'match_all': {}},
         'version': True
     }))
     output = self.deserializer.search(request)
     self.assertEqual(True, output['version'])
コード例 #53
0
    def test_rbac_filter(self):
        fake_request = unit_test_utils.get_fake_request(USER1,
                                                        TENANT1,
                                                        '/v1/search',
                                                        is_admin=False)
        rbac_terms = self.plugin._get_rbac_field_filters(fake_request.context)

        expected = [{"term": {"tenant_id": TENANT1}}]
        self.assertEqual(expected, rbac_terms)
コード例 #54
0
    def test_single_type(self):
        request = unit_test_utils.get_fake_request()
        request.body = six.b(jsonutils.dumps({
            'type': 'OS::Glance::Image',
        }))

        output = self.deserializer.search(request)
        self.assertEqual(['searchlight-search'], output['index'])
        self.assertEqual(['OS::Glance::Image'], output['doc_type'])
コード例 #55
0
    def test_admin_or_owner(self):
        """Since this a commonly used rule, check that it works"""
        self.enforcer.add_rules(
            policy.policy.Rules.from_dict({
                'admin_or_owner': 'role:admin or project_id:%(project_id)s',
                'test_rule': 'rule:admin_or_owner'
            }))

        request = unit_test_utils.get_fake_request(is_admin=False)
        self.assertTrue(
            self.enforcer.check(request.context, 'test_rule',
                                request.context.policy_target))

        request = unit_test_utils.get_fake_request(is_admin=False)
        self.assertFalse(self.enforcer.check(request.context, 'test_rule', {}))

        request = unit_test_utils.get_fake_request(is_admin=True)
        self.assertTrue(self.enforcer.check(request.context, 'test_rule', {}))
コード例 #56
0
    def test_fields_exclude_rbac(self):
        """Test various forms for source_exclude"""
        role_field = searchlight.elasticsearch.ROLE_USER_FIELD
        request = unit_test_utils.get_fake_request()
        request.body = six.b(
            jsonutils.dumps({
                'type': ['OS::Glance::Metadef'],
                'query': {
                    'match_all': {}
                },
                '_source': {
                    'exclude': ['something', 'other thing']
                }
            }))
        output = self.deserializer.search(request)
        self.assertEqual([role_field, 'something', 'other thing'],
                         output['_source_exclude'])

        # Test with a single field
        request.body = six.b(
            jsonutils.dumps({
                'type': ['OS::Glance::Metadef'],
                'query': {
                    'match_all': {}
                },
                '_source': {
                    'exclude': "something"
                }
            }))
        output = self.deserializer.search(request)
        self.assertEqual([role_field, 'something'], output['_source_exclude'])

        # Test with a single field
        request.body = six.b(
            jsonutils.dumps({
                'type': ['OS::Glance::Metadef'],
                'query': {
                    'match_all': {}
                },
                '_source': "includeme"
            }))
        output = self.deserializer.search(request)
        self.assertEqual([role_field], output['_source_exclude'])
        self.assertEqual("includeme", output['_source_include'])

        # Test with a single field
        request.body = six.b(
            jsonutils.dumps({
                'type': ['OS::Glance::Metadef'],
                'query': {
                    'match_all': {}
                },
                '_source': ["includeme", "andme"]
            }))
        output = self.deserializer.search(request)
        self.assertEqual([role_field], output['_source_exclude'])
        self.assertEqual(["includeme", "andme"], output['_source_include'])