[Fleet] throw fleet error on yaml error (#210363)

## Summary

Closes https://github.com/elastic/kibana/issues/210341

Catch yaml error when updating package policies to throw a Fleet error,
this results in a 400 response code instead of 500 which caused a PD
alert in serverless.

To verify:
- add System integration, then go to Edit integration policy
- add the yaml below to Processors
- click on Save and continue
- expect a HTTP 400 error response

```
data_stream:
  dataset: test

processors:
  - add_host_metadata: \~
  - add_cloud_metadata: \~
```

<img width="2551" alt="image"
src="https://github.com/user-attachments/assets/0c839601-e278-4715-a7e9-743235e69832"
/>



### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
This commit is contained in:
Julia Bardi 2025-02-10 17:03:42 +01:00 committed by GitHub
parent bcc5389598
commit 734a63d7a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 37 additions and 15 deletions

View file

@ -476,6 +476,23 @@ paths:
'Error while compiling agent template: options.inverse is not a function'
);
});
it('should throw on invalid yaml', () => {
const template = `
{{#if condition }}\ncondition: {{condition}}\n{{/if}}\n\npaths:\n{{#each paths as |path|}}\n - {{path}}\n{{/each}}\n\nexclude_files: \n{{#each exclude_files as |exclude_files|}}\n - {{exclude_files}}\n{{/each}}\n\nmultiline:\n pattern: \"^\\\\s\"\n match: after\n\nprocessors:\n- add_locale: ~\n{{#if processors.length}}\n{{processors}}\n{{/if}}\nallow_deprecated_use: true\ntags:\n{{#if preserve_original_event}}\n - preserve_original_event\n{{/if}}\n{{#each tags as |tag|}}\n - {{tag}}\n{{/each}}\n\n{{#if ignore_older}}\nignore_older: {{ignore_older}}\n{{/if}}\n
`;
const vars = {
processors: {
type: 'yaml',
value:
'data_stream:\n dataset: test\n\nprocessors:\n - add_host_metadata: \\~\n - add_cloud_metadata: \\~',
},
};
expect(() => compileTemplate(vars, template)).toThrowError(
'YAMLException: duplicated mapping key'
);
});
});
describe('encode', () => {

View file

@ -10,6 +10,7 @@ import { load, dump } from 'js-yaml';
import type { Logger } from '@kbn/core/server';
import type { PackagePolicyConfigRecord } from '../../../../common/types';
import { PackagePolicyValidationError } from '../../../../common/errors';
import { toCompiledSecretRef } from '../../secrets';
import { PackageInvalidArchiveError } from '../../../errors';
import { appContextService } from '../..';
@ -28,23 +29,27 @@ export function compileTemplate(variables: PackagePolicyConfigRecord, templateSt
}
compiledTemplate = replaceRootLevelYamlVariables(yamlValues, compiledTemplate);
const yamlFromCompiledTemplate = load(compiledTemplate, {});
try {
const yamlFromCompiledTemplate = load(compiledTemplate, {});
// Hack to keep empty string ('') values around in the end yaml because
// `load` replaces empty strings with null
const patchedYamlFromCompiledTemplate = Object.entries(yamlFromCompiledTemplate).reduce(
(acc, [key, value]) => {
if (value === null && typeof vars[key] === 'string' && vars[key].trim() === '') {
acc[key] = '';
} else {
acc[key] = value;
}
return acc;
},
{} as { [k: string]: any }
);
// Hack to keep empty string ('') values around in the end yaml because
// `load` replaces empty strings with null
const patchedYamlFromCompiledTemplate = Object.entries(yamlFromCompiledTemplate).reduce(
(acc, [key, value]) => {
if (value === null && typeof vars[key] === 'string' && vars[key].trim() === '') {
acc[key] = '';
} else {
acc[key] = value;
}
return acc;
},
{} as { [k: string]: any }
);
return replaceVariablesInYaml(yamlValues, patchedYamlFromCompiledTemplate);
return replaceVariablesInYaml(yamlValues, patchedYamlFromCompiledTemplate);
} catch (error) {
throw new PackagePolicyValidationError(error);
}
}
function isValidKey(key: string) {