mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Fix escaping of quotation marks for variables (#93415)
* Prometheus: Fix escaping of quotation marks for non-regex variables * Prometheus: Fix escaping of double quotation marks for regex variables * Prometheus: Add escaping for adhoc filter label queries
This commit is contained in:
parent
228bf711f9
commit
2bfdee73e3
@ -289,6 +289,16 @@ describe('PrometheusDatasource', () => {
|
|||||||
operator: '=~',
|
operator: '=~',
|
||||||
value: `v'.*`,
|
value: `v'.*`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'k3',
|
||||||
|
operator: '=~',
|
||||||
|
value: `v".*`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'k4',
|
||||||
|
operator: '=~',
|
||||||
|
value: `\\v.*`,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
ds.query({
|
ds.query({
|
||||||
interval: '15s',
|
interval: '15s',
|
||||||
@ -298,7 +308,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
} as DataQueryRequest<PromQuery>);
|
} as DataQueryRequest<PromQuery>);
|
||||||
const [result] = fetchMockCalledWith(fetchMock);
|
const [result] = fetchMockCalledWith(fetchMock);
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
expr: `metric{job="foo", k1=~"v.*", k2=~"v\\\\'.*"} - metric{k1=~"v.*", k2=~"v\\\\'.*"}`,
|
expr: `metric{job="foo", k1=~"v.*", k2=~"v'.*", k3=~"v\\".*", k4=~"\\\\v.*"} - metric{k1=~"v.*", k2=~"v'.*", k3=~"v\\".*", k4=~"\\\\v.*"}`,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -478,8 +488,12 @@ describe('PrometheusDatasource', () => {
|
|||||||
expect(prometheusRegularEscape('cryptodepression')).toEqual('cryptodepression');
|
expect(prometheusRegularEscape('cryptodepression')).toEqual('cryptodepression');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should escape '", () => {
|
it("should not escape '", () => {
|
||||||
expect(prometheusRegularEscape("looking'glass")).toEqual("looking\\\\'glass");
|
expect(prometheusRegularEscape("looking'glass")).toEqual("looking'glass");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should escape "', () => {
|
||||||
|
expect(prometheusRegularEscape('looking"glass')).toEqual('looking\\"glass');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should escape \\', () => {
|
it('should escape \\', () => {
|
||||||
@ -487,11 +501,11 @@ describe('PrometheusDatasource', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should escape multiple characters', () => {
|
it('should escape multiple characters', () => {
|
||||||
expect(prometheusRegularEscape("'looking'glass'")).toEqual("\\\\'looking\\\\'glass\\\\'");
|
expect(prometheusRegularEscape('"looking"glass"')).toEqual('\\"looking\\"glass\\"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should escape multiple different characters', () => {
|
it('should escape multiple different characters', () => {
|
||||||
expect(prometheusRegularEscape("'loo\\king'glass'")).toEqual("\\\\'loo\\\\king\\\\'glass\\\\'");
|
expect(prometheusRegularEscape('"loo\\king"glass"')).toEqual('\\"loo\\\\king\\"glass\\"');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -500,8 +514,9 @@ describe('PrometheusDatasource', () => {
|
|||||||
expect(prometheusSpecialRegexEscape('cryptodepression')).toEqual('cryptodepression');
|
expect(prometheusSpecialRegexEscape('cryptodepression')).toEqual('cryptodepression');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should escape $^*+?.()|\\', () => {
|
it('should escape $^*+?.()|\\"', () => {
|
||||||
expect(prometheusSpecialRegexEscape("looking'glass")).toEqual("looking\\\\'glass");
|
expect(prometheusSpecialRegexEscape("looking'glass")).toEqual("looking\\\\'glass");
|
||||||
|
expect(prometheusSpecialRegexEscape('looking"glass')).toEqual('looking\\\\\\"glass');
|
||||||
expect(prometheusSpecialRegexEscape('looking{glass')).toEqual('looking\\\\{glass');
|
expect(prometheusSpecialRegexEscape('looking{glass')).toEqual('looking\\\\{glass');
|
||||||
expect(prometheusSpecialRegexEscape('looking}glass')).toEqual('looking\\\\}glass');
|
expect(prometheusSpecialRegexEscape('looking}glass')).toEqual('looking\\\\}glass');
|
||||||
expect(prometheusSpecialRegexEscape('looking[glass')).toEqual('looking\\\\[glass');
|
expect(prometheusSpecialRegexEscape('looking[glass')).toEqual('looking\\\\[glass');
|
||||||
@ -549,8 +564,8 @@ describe('PrometheusDatasource', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('and value is a string', () => {
|
describe('and value is a string', () => {
|
||||||
it('should only escape single quotes', () => {
|
it('should only escape double quotes and backslashes', () => {
|
||||||
expect(ds.interpolateQueryExpr("abc'$^*{}[]+?.()|", customVariable)).toEqual("abc\\\\'$^*{}[]+?.()|");
|
expect(ds.interpolateQueryExpr('abc\'"$^*{}[]+?.()|\\', customVariable)).toEqual('abc\'\\"$^*{}[]+?.()|\\\\');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -640,7 +640,7 @@ export class PrometheusDatasource
|
|||||||
|
|
||||||
const labelFilters: QueryBuilderLabelFilter[] = options.filters.map((f) => ({
|
const labelFilters: QueryBuilderLabelFilter[] = options.filters.map((f) => ({
|
||||||
label: f.key,
|
label: f.key,
|
||||||
value: f.value,
|
value: prometheusRegularEscape(f.value),
|
||||||
op: f.operator,
|
op: f.operator,
|
||||||
}));
|
}));
|
||||||
const expr = promQueryModeller.renderLabels(labelFilters);
|
const expr = promQueryModeller.renderLabels(labelFilters);
|
||||||
@ -672,7 +672,7 @@ export class PrometheusDatasource
|
|||||||
|
|
||||||
const labelFilters: QueryBuilderLabelFilter[] = options.filters.map((f) => ({
|
const labelFilters: QueryBuilderLabelFilter[] = options.filters.map((f) => ({
|
||||||
label: f.key,
|
label: f.key,
|
||||||
value: f.value,
|
value: prometheusRegularEscape(f.value),
|
||||||
op: f.operator,
|
op: f.operator,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -1045,9 +1045,14 @@ export function extractRuleMappingFromGroups(groups: RawRecordingRules[]): RuleQ
|
|||||||
// in language_utils.ts, but they are not exactly the same algorithm, and we found
|
// in language_utils.ts, but they are not exactly the same algorithm, and we found
|
||||||
// no way to reuse one in the another or vice versa.
|
// no way to reuse one in the another or vice versa.
|
||||||
export function prometheusRegularEscape<T>(value: T) {
|
export function prometheusRegularEscape<T>(value: T) {
|
||||||
return typeof value === 'string' ? value.replace(/\\/g, '\\\\').replace(/'/g, "\\\\'") : value;
|
return typeof value === 'string' ? value.replace(/\\/g, '\\\\').replace(/"/g, '\\"') : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prometheusSpecialRegexEscape<T>(value: T) {
|
export function prometheusSpecialRegexEscape<T>(value: T) {
|
||||||
return typeof value === 'string' ? value.replace(/\\/g, '\\\\\\\\').replace(/[$^*{}\[\]\'+?.()|]/g, '\\\\$&') : value;
|
return typeof value === 'string'
|
||||||
|
? value
|
||||||
|
.replace(/\\/g, '\\\\\\\\')
|
||||||
|
.replace(/"/g, '\\\\\\"')
|
||||||
|
.replace(/[$^*{}\[\]\'+?.()|]/g, '\\\\$&')
|
||||||
|
: value;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user