예제 #1
0
    def inspect(self, client):
        restricted_types = client.is_restricted('types')
        requested_indices = FilterString.from_string(self.indices)

        try:
            index_filter = client.create_filter_string('api/indices/get/mappings', requested_indices,
                                                       single=restricted_types)
        except MultipleIncludesError as error:
            raise PermissionError(
                'You are restricted to specific types. To retrieve field mappings, please pick a'
                ' single index from the following list: {0}'.format(', '.join(error.includes)))
        else:
            if index_filter is None:
                raise PermissionError('You are not permitted to access the mappings of the given indices.')

        if restricted_types:
            requested_types = FilterString.from_string(self.get_match('documents', ''))
            requested_index = index_filter.combined[0] if index_filter.combined else index_filter[0]
            type_filter = client.create_filter_string('api/indices/get/mappings', requested_types,
                                                      str(requested_index))
            if type_filter is None:
                raise PermissionError('You are not permitted to access the mappings of the given types.')
        else:
            type_filter = self.get_match('documents')

        if type_filter:
            self.path = '/{0}/_mapping/{1}/field/{2}'.format(index_filter, type_filter, self.fields)
        else:
            self.path = '/{0}/_mapping/field/{1}'.format(index_filter, self.fields)
예제 #2
0
    def inspect(self, client):
        if '__kibanaQueryValidator' in self.path:
            # I have _still_ no explanation for this. Please enlighten
            # me if you think this is security relevant in any way.
            if client.can('api/search/explain', '.kibana'):
                return

            raise PermissionError(self._permission_errors['api/search/explain']['indices'].format('.kibana'))

        index_filter, type_filter, _, json = self.inspect_request(
            client, FilterString.from_string(self.get_match('indices', '')),
            FilterString.from_string(self.get_match('documents', '')), json=self.json)

        if self.query.last('q', '').strip() and self.query.last('q').strip() != '*':
            if client.has_restriction(index_filter, type_filter):
                # TODO: Provide a more sophisticated solution once we've got a parser for query strings!
                raise PermissionError(
                    'You are restricted to specific fields and as such cannot utilize the query string search.')

        if not self.query.is_false('explain'):
            self._check_permission('api/search/explain', client, index_filter, type_filter)

        if index_filter:
            if type_filter:
                self.path = '/{0}/{1}/_validate/query'.format(index_filter, type_filter)
            else:
                self.path = '/{0}/_validate/query'.format(index_filter)

        if json is not None:
            self.body = self.json_encode(json)
예제 #3
0
    def inspect(self, client):
        index_filter, type_filter, source_filter, json = self.inspect_request(
            client, FilterString.from_string(self.get_match('indices', '')),
            FilterString.from_string(self.get_match('documents', '')),
            SourceFilter.from_query(self.query), self.json)

        if self.query.last('q', '').strip() and self.query.last('q').strip() != '*':
            if client.has_restriction(index_filter, type_filter):
                # TODO: Provide a more sophisticated solution once we've got a parser for query strings!
                raise PermissionError(
                    'You are restricted to specific fields and as such cannot utilize the query string search.')

        if not self.query.is_false('explain'):
            self._check_permission('api/search/explain', client, index_filter, type_filter)

        fields_filter = client.create_fields_filter('api/search/documents', index_filter, type_filter,
                                                    FieldsFilter.from_query(self.query))
        if fields_filter is None:
            raise PermissionError('You are not permitted to access any of the requested stored fields.')
        elif fields_filter:
            self.query.update(fields_filter.as_query())

        if index_filter:
            if type_filter:
                self.path = '/{0}/{1}/_search'.format(index_filter, type_filter)
            else:
                self.path = '/{0}/_search'.format(index_filter)

        self.query.discard('_source', '_source_include', '_source_exclude')
        if source_filter:
            self.query.update(source_filter.as_query())

        if json is not None:
            self.body = self.json_encode(json)
예제 #4
0
 def inspect(self, client):
     requested_indices = FilterString.from_string(self.get_match('indices', ''))
     index_filter = client.create_filter_string('api/indices/get/warmers', requested_indices)
     if index_filter is None:
         raise PermissionError('You are not permitted to access warmers of the given indices.')
     elif index_filter:
         self.path = '/{0}/_warmers/{1}'.format(index_filter, self.identifiers)
예제 #5
0
 def inspect(self, client):
     requested_indices = FilterString.from_string(self.get_match('indices', ''))
     index_filter = client.create_filter_string('api/cluster/health', requested_indices)
     if index_filter is None:
         raise PermissionError('You are not permitted to check the cluster health for the requested indices.')
     elif index_filter:
         self.path = '/_cluster/health/{0}'.format(index_filter)
예제 #6
0
    def inspect(self, client):
        restricted_types = client.is_restricted('types')
        requested_indices = FilterString.from_string(
            self.get_match('indices', ''))

        try:
            index_filter = client.create_filter_string(
                'api/indices/create/mappings',
                requested_indices,
                single=restricted_types)
        except MultipleIncludesError as error:
            raise PermissionError(
                'You are restricted to specific types. To create type mappings, please pick a'
                ' single index from the following list: {0}'.format(', '.join(
                    error.includes)))
        else:
            if index_filter is None:
                raise PermissionError(
                    'You are not permitted to create mappings in the given indices.'
                )

        if restricted_types:
            requested_index = index_filter.combined[
                0] if index_filter.combined else index_filter[0]
            if not client.can('api/indices/create/mappings',
                              str(requested_index), self.document):
                raise PermissionError(
                    'You are not permitted to create a mapping for this document type.'
                )

        if index_filter:
            self.path = '/{0}/_mappings/{1}'.format(index_filter,
                                                    self.document)
예제 #7
0
    def inspect(self, client):
        index_filter = client.create_filter_string('api/indices/get/*', FilterString.from_string(self.indices))
        if index_filter is None:
            raise PermissionError('You are not permitted to access any settings of the given index or indices.')
        elif index_filter:
            self.path = self.path.replace(self.indices, str(index_filter))

        if self.command != 'HEAD':
            keywords = [s.strip() for s in self.get_match('keywords', '').split(',') if s]
            unknown = next((kw for kw in keywords if kw not in self.index_settings), None)
            if unknown is not None:
                raise PermissionError('Unknown index setting: {0}'.format(unknown))

            permitted_settings, missing_permissions = [], {}
            for setting, permission in self.index_settings.iteritems():
                if not keywords or setting in keywords:
                    for index in index_filter.iter_patterns():
                        if client.can(permission, index):
                            permitted_settings.append(setting)
                        elif setting in keywords:
                            missing_permissions.setdefault(permission, []).append(str(index))

            if missing_permissions:
                permission_hint = ', '.join('{0} ({1})'.format(permission, ', '.join(indices))
                                            for permission, indices in missing_permissions.iteritems())
                raise PermissionError('You are missing the following permissions: {0}'.format(permission_hint))
            elif not keywords and len(permitted_settings) < len(self.index_settings):
                self.path = '/'.join((self.path.rstrip('/'), ','.join(permitted_settings)))
예제 #8
0
 def inspect(self, client):
     requested_indices = FilterString.from_string(self.get_match('indices', ''))
     index_filter = client.create_filter_string('api/indices/refresh', requested_indices)
     if index_filter is None:
         raise PermissionError('You are not permitted to refresh the given indices.')
     elif index_filter:
         self.path = '/{0}/_refresh'.format(index_filter)
예제 #9
0
 def inspect(self, client):
     requested_indices = FilterString.from_string(self.get_match('indices', ''))
     index_filter = client.create_filter_string('api/indices/get/settings', requested_indices)
     if index_filter is None:
         raise PermissionError(
             'You are not permitted to access the general settings of the given index or indices.')
     elif index_filter:
         self.path = '/{0}/_settings'.format(index_filter)
예제 #10
0
    def inspect(self, client):
        restricted_types = client.is_restricted('types')
        requested_indices = FilterString.from_string(
            self.get_match('indices', ''))

        try:
            index_filter = client.create_filter_string(
                'api/indices/get/mappings',
                requested_indices,
                single=restricted_types)
        except MultipleIncludesError as error:
            raise PermissionError(
                'You are restricted to specific types. To retrieve type mappings, please pick a'
                ' single index from the following list: {0}'.format(', '.join(
                    error.includes)))
        else:
            if index_filter is None:
                raise PermissionError(
                    'You are not permitted to access the mappings of the given indices.'
                )

        if restricted_types:
            requested_types = FilterString.from_string(
                self.get_match('documents', ''))
            requested_index = index_filter.combined[
                0] if index_filter.combined else index_filter[0]
            type_filter = client.create_filter_string(
                'api/indices/get/mappings', requested_types,
                str(requested_index))
            if type_filter is None:
                raise PermissionError(
                    'You are not permitted to access the mappings of the given types.'
                )
        else:
            type_filter = self.get_match('documents')

        if index_filter:
            if type_filter:
                if self.command == 'HEAD':
                    self.path = '/{0}/{1}'.format(index_filter, type_filter)
                else:
                    self.path = '/{0}/_mappings/{1}'.format(
                        index_filter, type_filter)
            else:
                self.path = '/{0}/_mappings'.format(index_filter)
예제 #11
0
 def inspect(self, client):
     requested_indices = FilterString.from_string(
         self.get_match('indices', ''))
     index_filter = client.create_filter_string('api/indices/refresh',
                                                requested_indices)
     if index_filter is None:
         raise PermissionError(
             'You are not permitted to refresh the given indices.')
     elif index_filter:
         self.path = '/{0}/_refresh'.format(index_filter)
예제 #12
0
 def inspect(self, client):
     requested_indices = FilterString.from_string(
         self.get_match('indices', ''))
     index_filter = client.create_filter_string('api/indices/get/settings',
                                                requested_indices)
     if index_filter is None:
         raise PermissionError(
             'You are not permitted to access the general settings of the given index or indices.'
         )
     elif index_filter:
         self.path = '/{0}/_settings'.format(index_filter)
예제 #13
0
    def inspect(self, client):
        index_filter, type_filter, source_filter, json = self.inspect_request(
            client, FilterString.from_string(self.get_match('indices', '')),
            FilterString.from_string(self.get_match('documents', '')),
            SourceFilter.from_query(self.query), self.json)

        if self.query.last('q',
                           '').strip() and self.query.last('q').strip() != '*':
            if client.has_restriction(index_filter, type_filter):
                # TODO: Provide a more sophisticated solution once we've got a parser for query strings!
                raise PermissionError(
                    'You are restricted to specific fields and as such cannot utilize the query string search.'
                )

        if not self.query.is_false('explain'):
            self._check_permission('api/search/explain', client, index_filter,
                                   type_filter)

        fields_filter = client.create_fields_filter(
            'api/search/documents', index_filter, type_filter,
            FieldsFilter.from_query(self.query))
        if fields_filter is None:
            raise PermissionError(
                'You are not permitted to access any of the requested stored fields.'
            )
        elif fields_filter:
            self.query.update(fields_filter.as_query())

        if index_filter:
            if type_filter:
                self.path = '/{0}/{1}/_search'.format(index_filter,
                                                      type_filter)
            else:
                self.path = '/{0}/_search'.format(index_filter)

        self.query.discard('_source', '_source_include', '_source_exclude')
        if source_filter:
            self.query.update(source_filter.as_query())

        if json is not None:
            self.body = self.json_encode(json)
예제 #14
0
 def inspect(self, client):
     requested_indices = FilterString.from_string(
         self.get_match('indices', ''))
     index_filter = client.create_filter_string('api/indices/get/warmers',
                                                requested_indices)
     if index_filter is None:
         raise PermissionError(
             'You are not permitted to access warmers of the given indices.'
         )
     elif index_filter:
         self.path = '/{0}/_warmers/{1}'.format(index_filter,
                                                self.identifiers)
예제 #15
0
    def inspect(self, client):
        if '__kibanaQueryValidator' in self.path:
            # I have _still_ no explanation for this. Please enlighten
            # me if you think this is security relevant in any way.
            if client.can('api/search/explain', '.kibana'):
                return

            raise PermissionError(self._permission_errors['api/search/explain']
                                  ['indices'].format('.kibana'))

        index_filter, type_filter, _, json = self.inspect_request(
            client,
            FilterString.from_string(self.get_match('indices', '')),
            FilterString.from_string(self.get_match('documents', '')),
            json=self.json)

        if self.query.last('q',
                           '').strip() and self.query.last('q').strip() != '*':
            if client.has_restriction(index_filter, type_filter):
                # TODO: Provide a more sophisticated solution once we've got a parser for query strings!
                raise PermissionError(
                    'You are restricted to specific fields and as such cannot utilize the query string search.'
                )

        if not self.query.is_false('explain'):
            self._check_permission('api/search/explain', client, index_filter,
                                   type_filter)

        if index_filter:
            if type_filter:
                self.path = '/{0}/{1}/_validate/query'.format(
                    index_filter, type_filter)
            else:
                self.path = '/{0}/_validate/query'.format(index_filter)

        if json is not None:
            self.body = self.json_encode(json)
예제 #16
0
    def inspect(self, client):
        index_filter = client.create_filter_string(
            'api/indices/get/*', FilterString.from_string(self.indices))
        if index_filter is None:
            raise PermissionError(
                'You are not permitted to access any settings of the given index or indices.'
            )
        elif index_filter:
            self.path = self.path.replace(self.indices, str(index_filter))

        if self.command != 'HEAD':
            keywords = [
                s.strip() for s in self.get_match('keywords', '').split(',')
                if s
            ]
            unknown = next(
                (kw for kw in keywords if kw not in self.index_settings), None)
            if unknown is not None:
                raise PermissionError(
                    'Unknown index setting: {0}'.format(unknown))

            permitted_settings, missing_permissions = [], {}
            for setting, permission in self.index_settings.iteritems():
                if not keywords or setting in keywords:
                    for index in index_filter.iter_patterns():
                        if client.can(permission, index):
                            permitted_settings.append(setting)
                        elif setting in keywords:
                            missing_permissions.setdefault(permission,
                                                           []).append(
                                                               str(index))

            if missing_permissions:
                permission_hint = ', '.join(
                    '{0} ({1})'.format(permission, ', '.join(indices))
                    for permission, indices in missing_permissions.iteritems())
                raise PermissionError(
                    'You are missing the following permissions: {0}'.format(
                        permission_hint))
            elif not keywords and len(permitted_settings) < len(
                    self.index_settings):
                self.path = '/'.join(
                    (self.path.rstrip('/'), ','.join(permitted_settings)))
예제 #17
0
    def inspect(self, client):
        restricted_types = client.is_restricted('types')
        requested_indices = FilterString.from_string(self.get_match('indices', ''))

        try:
            index_filter = client.create_filter_string('api/indices/create/mappings', requested_indices,
                                                       single=restricted_types)
        except MultipleIncludesError as error:
            raise PermissionError(
                'You are restricted to specific types. To create type mappings, please pick a'
                ' single index from the following list: {0}'.format(', '.join(error.includes)))
        else:
            if index_filter is None:
                raise PermissionError('You are not permitted to create mappings in the given indices.')

        if restricted_types:
            requested_index = index_filter.combined[0] if index_filter.combined else index_filter[0]
            if not client.can('api/indices/create/mappings', str(requested_index), self.document):
                raise PermissionError('You are not permitted to create a mapping for this document type.')

        if index_filter:
            self.path = '/{0}/_mappings/{1}'.format(index_filter, self.document)
예제 #18
0
    def _inspect_parser(self, client, parser, index_filter, type_filter):
        json_updated = False
        for permission in parser.permissions:
            # TODO: Context changes? Permissions are not only global anymore!
            if permission != 'api/feature/queryString':
                self._check_permission(permission, client, index_filter, type_filter)
            elif client.has_restriction(index_filter, type_filter):
                # TODO: Remove this once we've got a parser for query strings!
                raise PermissionError(
                    'You are restricted to specific fields and as such cannot utilize the query string search.')

        if client.is_restricted('indices'):
            for index in parser.indices:
                if not index_filter.matches(FilterString.from_string(index)):
                    raise RequestError(400, 'Index filter "{0}" does not match the requested scope "{1}".'
                                            ''.format(index, index_filter))

        if client.is_restricted('types'):
            for index, document_type in parser.documents:
                if index and not index_filter.matches(FilterString.from_string(index)):
                    raise RequestError(400, 'Index filter "{0}" does not match the requested scope "{1}".'
                                            ''.format(index, index_filter))
                elif not type_filter.matches(FilterString.from_string(document_type)):
                    raise RequestError(400, 'Type filter "{0}" does not match the requested scope "{1}".'
                                            ''.format(document_type, type_filter))

        if client.is_restricted('fields'):
            for index, document_type, field in parser.fields:
                if index:
                    indices = FilterString.from_string(index)
                    if not index_filter.matches(indices):
                        raise RequestError(400, 'Index filter "{0}" does not match the requested scope "{1}".'
                                                ''.format(index, index_filter))
                else:
                    indices = index_filter

                if document_type:
                    types = FilterString.from_string(document_type)
                    if not type_filter.matches(types):
                        raise RequestError(400, 'Type filter "{0}" does not match the requested scope "{1}".'
                                                ''.format(document_type, type_filter))
                else:
                    types = type_filter

                for index in indices.iter_patterns():
                    for document_type in types.iter_patterns():
                        if not client.can('api/search/documents', index, document_type, field):
                            raise PermissionError('You are not permitted to search for documents of type "{0}" in index'
                                                  ' "{1}" by using field "{2}".'.format(document_type, index, field))

            try:
                document_requests = parser.document_requests
            except AttributeError:
                pass
            else:
                for index, document_type, document_request in document_requests:
                    if index and not index_filter.matches(FilterString.from_string(index)):
                        raise RequestError(400, 'Index filter "{0}" does not match the requested scope "{1}".'
                                                ''.format(index, index_filter))
                    elif document_type and not type_filter.matches(FilterString.from_string(document_type)):
                        raise RequestError(400, 'Type filter "{0}" does not match the requested scope "{1}".'
                                                ''.format(document_type, type_filter))

                    requested_source = SourceFilter.from_json(document_request.get('_source'))
                    source_filter = client.create_source_filter('api/search/documents', index_filter,
                                                                type_filter, requested_source)
                    if source_filter is None:
                        raise PermissionError('You are either not permitted to access the document type'
                                              ' "{0}" or any of the requested fields ({1}) in index "{2}".'
                                              ''.format(document_type or type_filter, requested_source,
                                                        index or index_filter))
                    elif source_filter:
                        document_request['_source'] = source_filter.as_json()
                        json_updated = True

                    if 'fielddata_fields' in document_request:
                        requested_fielddata = FieldsFilter.from_json(document_request['fielddata_fields'])
                        fielddata_filter = client.create_fields_filter('api/search/documents', index_filter,
                                                                       type_filter, requested_fielddata)
                        if fielddata_filter is None:
                            raise PermissionError(
                                'You are not permitted to access any of the requested fielddata fields ({0}) of type'
                                ' "{1}" in index "{2}".'.format(requested_fielddata, document_type or type_filter,
                                                                index or index_filter))
                        elif fielddata_filter:
                            document_request['fielddata_fields'] = fielddata_filter.as_json()
                            json_updated = True

        return json_updated
예제 #19
0
    def _inspect_parser(self, client, parser, index_filter, type_filter):
        json_updated = False
        for permission in parser.permissions:
            # TODO: Context changes? Permissions are not only global anymore!
            if permission != 'api/feature/queryString':
                self._check_permission(permission, client, index_filter,
                                       type_filter)
            elif client.has_restriction(index_filter, type_filter):
                # TODO: Remove this once we've got a parser for query strings!
                raise PermissionError(
                    'You are restricted to specific fields and as such cannot utilize the query string search.'
                )

        if client.is_restricted('indices'):
            for index in parser.indices:
                if not index_filter.matches(FilterString.from_string(index)):
                    raise RequestError(
                        400,
                        'Index filter "{0}" does not match the requested scope "{1}".'
                        ''.format(index, index_filter))

        if client.is_restricted('types'):
            for index, document_type in parser.documents:
                if index and not index_filter.matches(
                        FilterString.from_string(index)):
                    raise RequestError(
                        400,
                        'Index filter "{0}" does not match the requested scope "{1}".'
                        ''.format(index, index_filter))
                elif not type_filter.matches(
                        FilterString.from_string(document_type)):
                    raise RequestError(
                        400,
                        'Type filter "{0}" does not match the requested scope "{1}".'
                        ''.format(document_type, type_filter))

        if client.is_restricted('fields'):
            for index, document_type, field in parser.fields:
                if index:
                    indices = FilterString.from_string(index)
                    if not index_filter.matches(indices):
                        raise RequestError(
                            400,
                            'Index filter "{0}" does not match the requested scope "{1}".'
                            ''.format(index, index_filter))
                else:
                    indices = index_filter

                if document_type:
                    types = FilterString.from_string(document_type)
                    if not type_filter.matches(types):
                        raise RequestError(
                            400,
                            'Type filter "{0}" does not match the requested scope "{1}".'
                            ''.format(document_type, type_filter))
                else:
                    types = type_filter

                for index in indices.iter_patterns():
                    for document_type in types.iter_patterns():
                        if not client.can('api/search/documents', index,
                                          document_type, field):
                            raise PermissionError(
                                'You are not permitted to search for documents of type "{0}" in index'
                                ' "{1}" by using field "{2}".'.format(
                                    document_type, index, field))

            try:
                document_requests = parser.document_requests
            except AttributeError:
                pass
            else:
                for index, document_type, document_request in document_requests:
                    if index and not index_filter.matches(
                            FilterString.from_string(index)):
                        raise RequestError(
                            400,
                            'Index filter "{0}" does not match the requested scope "{1}".'
                            ''.format(index, index_filter))
                    elif document_type and not type_filter.matches(
                            FilterString.from_string(document_type)):
                        raise RequestError(
                            400,
                            'Type filter "{0}" does not match the requested scope "{1}".'
                            ''.format(document_type, type_filter))

                    requested_source = SourceFilter.from_json(
                        document_request.get('_source'))
                    source_filter = client.create_source_filter(
                        'api/search/documents', index_filter, type_filter,
                        requested_source)
                    if source_filter is None:
                        raise PermissionError(
                            'You are either not permitted to access the document type'
                            ' "{0}" or any of the requested fields ({1}) in index "{2}".'
                            ''.format(document_type or type_filter,
                                      requested_source, index or index_filter))
                    elif source_filter:
                        document_request['_source'] = source_filter.as_json()
                        json_updated = True

                    if 'fielddata_fields' in document_request:
                        requested_fielddata = FieldsFilter.from_json(
                            document_request['fielddata_fields'])
                        fielddata_filter = client.create_fields_filter(
                            'api/search/documents', index_filter, type_filter,
                            requested_fielddata)
                        if fielddata_filter is None:
                            raise PermissionError(
                                'You are not permitted to access any of the requested fielddata fields ({0}) of type'
                                ' "{1}" in index "{2}".'.format(
                                    requested_fielddata, document_type
                                    or type_filter, index or index_filter))
                        elif fielddata_filter:
                            document_request[
                                'fielddata_fields'] = fielddata_filter.as_json(
                                )
                            json_updated = True

        return json_updated