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)
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)
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)
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)
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)
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)
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)))
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)
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)
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)
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)
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)
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)
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)
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)
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)))
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)
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
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