mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 12:12:35 +08:00
Elasticsearch: Fix URL creation and allowlist for /_mapping
requests (#80970)
* Elasticsearch: Fix URL creation for mapping requests * remove leading slash by default * add comment for es route * hardcode `_mapping` * update doc
This commit is contained in:
@ -188,9 +188,10 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq
|
||||
logger := eslog.FromContext(ctx)
|
||||
// allowed paths for resource calls:
|
||||
// - empty string for fetching db version
|
||||
// - ?/_mapping for fetching index mapping
|
||||
// - /_mapping for fetching index mapping, e.g. requests going to `index/_mapping`
|
||||
// - _msearch for executing getTerms queries
|
||||
if req.Path != "" && !strings.HasSuffix(req.Path, "/_mapping") && req.Path != "_msearch" {
|
||||
// - _mapping for fetching "root" index mappings
|
||||
if req.Path != "" && !strings.HasSuffix(req.Path, "/_mapping") && req.Path != "_msearch" && req.Path != "_mapping" {
|
||||
logger.Error("Invalid resource path", "path", req.Path)
|
||||
return fmt.Errorf("invalid resource URL: %s", req.Path)
|
||||
}
|
||||
|
@ -151,6 +151,15 @@ describe('ElasticDatasource', () => {
|
||||
const lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length - 1];
|
||||
expect(lastCall[0].url).toBe(`${ELASTICSEARCH_MOCK_URL}/test-${today}/_mapping`);
|
||||
});
|
||||
|
||||
it('should call `/_mapping` with an empty index', async () => {
|
||||
const { ds, fetchMock } = getTestContext({ jsonData: { index: '' } });
|
||||
|
||||
await ds.testDatasource();
|
||||
|
||||
const lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length - 1];
|
||||
expect(lastCall[0].url).toBe(`${ELASTICSEARCH_MOCK_URL}/_mapping`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When issuing metric query with interval pattern', () => {
|
||||
|
@ -195,17 +195,24 @@ export class ElasticDatasource
|
||||
*
|
||||
* When multiple indices span the provided time range, the request is sent starting from the newest index,
|
||||
* and then going backwards until an index is found.
|
||||
*
|
||||
* @param url the url to query the index on, for example `/_mapping`.
|
||||
*/
|
||||
|
||||
private requestAllIndices(url: string, range = getDefaultTimeRange()) {
|
||||
private requestAllIndices(range = getDefaultTimeRange()) {
|
||||
let indexList = this.indexPattern.getIndexList(range.from, range.to);
|
||||
if (!Array.isArray(indexList)) {
|
||||
indexList = [this.indexPattern.getIndexForToday()];
|
||||
}
|
||||
|
||||
const indexUrlList = indexList.map((index) => index + url);
|
||||
const url = '_mapping';
|
||||
|
||||
const indexUrlList = indexList.map((index) => {
|
||||
// make sure `index` does not end with a slash
|
||||
index = index.replace(/\/$/, '');
|
||||
if (index === '') {
|
||||
return url;
|
||||
}
|
||||
|
||||
return `${index}/${url}`;
|
||||
});
|
||||
|
||||
const maxTraversals = 7; // do not go beyond one week (for a daily pattern)
|
||||
const listLen = indexUrlList.length;
|
||||
@ -708,7 +715,7 @@ export class ElasticDatasource
|
||||
nested: 'nested',
|
||||
histogram: 'number',
|
||||
};
|
||||
return this.requestAllIndices('/_mapping', range).pipe(
|
||||
return this.requestAllIndices(range).pipe(
|
||||
map((result) => {
|
||||
const shouldAddField = (obj: any, key: string) => {
|
||||
if (this.isMetadataField(key)) {
|
||||
|
@ -39,9 +39,9 @@ export function createElasticDatasource(settings: Partial<DataSourceInstanceSett
|
||||
jsonData: {
|
||||
timeField: '',
|
||||
timeInterval: '',
|
||||
index: '[test-]YYYY.MM.DD',
|
||||
...jsonData,
|
||||
},
|
||||
database: '[test-]YYYY.MM.DD',
|
||||
...rest,
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user