Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fleet] Automatically quote vars that start with asterisks or ampersands #126919

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions x-pack/plugins/fleet/common/services/validate_package_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,29 +260,6 @@ export const validatePackagePolicyConfig = (
})
);
}
if (varDef.type === 'text' && parsedValue && Array.isArray(parsedValue)) {
const invalidStrings = parsedValue.filter((cand) => /^[*&]/.test(cand));
// only show one error if multiple strings in array are invalid
if (invalidStrings.length > 0) {
errors.push(
i18n.translate('xpack.fleet.packagePolicyValidation.quoteStringErrorMessage', {
defaultMessage:
'Strings starting with special YAML characters like * or & need to be enclosed in double quotes.',
})
);
}
}
}

if (varDef.type === 'text' && parsedValue && !Array.isArray(parsedValue)) {
if (/^[*&]/.test(parsedValue)) {
errors.push(
i18n.translate('xpack.fleet.packagePolicyValidation.quoteStringErrorMessage', {
defaultMessage:
'Strings starting with special YAML characters like * or & need to be enclosed in double quotes.',
})
);
}
}

if (
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/common/types/models/epm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export interface RegistryDataStreamPrivileges {
indices?: string[];
}

export type RegistryVarType = 'integer' | 'bool' | 'password' | 'text' | 'yaml' | 'string';
export type RegistryVarType = 'integer' | 'bool' | 'password' | 'text' | 'yaml';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this because it looks like it was intended to be removed in https://github.com/elastic/kibana/pull/94174/files but wasn't (I think this was an accident)

cc @jen-huang

export enum RegistryVarsEntryKeys {
name = 'name',
title = 'title',
Expand Down
44 changes: 44 additions & 0 deletions x-pack/plugins/fleet/server/services/epm/agent/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,48 @@ paths:
'Error while compiling agent template: options.inverse is not a function'
);
});

it('should escape string values when necessary', () => {
const stringTemplate = `
my-package:
asterisk: {{asterisk}}
leadingasterisk: {{leadingasterisk}}
middleasterisk: {{middleasterisk}}
trailingasterisk: {{trailingasterisk}}
ampersand: {{ampersand}}
leadingampersand: {{leadingampersand}}
middleampersand: {{middleampersand}}
trailingampersand: {{trailingampersand}}`;

// List of special chars that may lead to YAML parsing errors when not quoted.
// See YAML specification section 5.3 Indicator characters
// https://yaml.org/spec/1.2/spec.html#id2772075
// Currently only escaping leading * and &
const vars = {
asterisk: { value: '*', type: 'text' },
leadingasterisk: { value: '*blah', type: 'text' },
middleasterisk: { value: 'blah*blah', type: 'text' },
trailingasterisk: { value: 'blah*', type: 'text' },
ampersand: { value: '&', type: 'text' },
leadingampersand: { value: '&blah', type: 'text' },
middleampersand: { value: 'blah&blah', type: 'text' },
trailingampersand: { value: 'blah&', type: 'text' },
};

const targetOutput = {
'my-package': {
asterisk: '*',
leadingasterisk: '*blah',
middleasterisk: 'blah*blah',
trailingasterisk: 'blah*',
ampersand: '&',
leadingampersand: '&blah',
middleampersand: 'blah&blah',
trailingampersand: 'blah&',
},
};

const output = compileTemplate(vars, stringTemplate);
expect(output).toEqual(targetOutput);
});
});
14 changes: 14 additions & 0 deletions x-pack/plugins/fleet/server/services/epm/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ function replaceVariablesInYaml(yamlVariables: { [k: string]: any }, yaml: any)
return yaml;
}

const maybeEscapeString = (value: string) => {
// Quote strings that start with special characters
if (/^[*&]/.test(value)) {
return `"${value}"`;
}
return value;
};

function buildTemplateVariables(variables: PackagePolicyConfigRecord, templateStr: string) {
const yamlValues: { [k: string]: any } = {};
const vars = Object.entries(variables).reduce((acc, [key, recordEntry]) => {
Expand All @@ -90,6 +98,12 @@ function buildTemplateVariables(variables: PackagePolicyConfigRecord, templateSt
const yamlKeyPlaceholder = `##${key}##`;
varPart[lastKeyPart] = recordEntry.value ? `"${yamlKeyPlaceholder}"` : null;
yamlValues[yamlKeyPlaceholder] = recordEntry.value ? safeLoad(recordEntry.value) : null;
} else if (recordEntry.type && recordEntry.type === 'text' && recordEntry.value?.length) {
if (Array.isArray(recordEntry.value)) {
varPart[lastKeyPart] = recordEntry.value.map((value: string) => maybeEscapeString(value));
} else {
varPart[lastKeyPart] = maybeEscapeString(recordEntry.value);
}
} else {
varPart[lastKeyPart] = recordEntry.value;
}
Expand Down