[Fleet] Validate package policy on create or update APIs (#123261) (#123394)

(cherry picked from commit d7dbf15919)

Co-authored-by: Nicolas Chaulet <nicolas.chaulet@elastic.co>
This commit is contained in:
Kibana Machine 2022-01-19 14:45:42 -05:00 committed by GitHub
parent fcbf74937d
commit 2ae242d4e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 197 additions and 24 deletions

View file

@ -157,8 +157,10 @@ class PackagePolicyService {
);
}
}
validatePackagePolicyOrThrow(packagePolicy, pkgInfo);
const registryPkgInfo = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version);
inputs = await this._compilePackagePolicyInputs(
registryPkgInfo,
pkgInfo,
@ -392,6 +394,8 @@ class PackagePolicyService {
pkgVersion: packagePolicy.package.version,
});
validatePackagePolicyOrThrow(packagePolicy, pkgInfo);
const registryPkgInfo = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version);
inputs = await this._compilePackagePolicyInputs(
registryPkgInfo,
@ -865,6 +869,31 @@ class PackagePolicyService {
}
}
function validatePackagePolicyOrThrow(packagePolicy: NewPackagePolicy, pkgInfo: PackageInfo) {
const validationResults = validatePackagePolicy(packagePolicy, pkgInfo, safeLoad);
if (validationHasErrors(validationResults)) {
const responseFormattedValidationErrors = Object.entries(getFlattenedObject(validationResults))
.map(([key, value]) => ({
key,
message: value,
}))
.filter(({ message }) => !!message);
if (responseFormattedValidationErrors.length) {
throw new PackagePolicyValidationError(
i18n.translate('xpack.fleet.packagePolicyInvalidError', {
defaultMessage: 'Package policy is invalid: {errors}',
values: {
errors: responseFormattedValidationErrors
.map(({ key, message }) => `${key}: ${message}`)
.join('\n'),
},
})
);
}
}
}
function assignStreamIdToInput(packagePolicyId: string, input: NewPackagePolicyInput) {
return {
...input,
@ -1314,29 +1343,7 @@ export function preconfigurePackageInputs(
inputs,
};
const validationResults = validatePackagePolicy(resultingPackagePolicy, packageInfo, safeLoad);
if (validationHasErrors(validationResults)) {
const responseFormattedValidationErrors = Object.entries(getFlattenedObject(validationResults))
.map(([key, value]) => ({
key,
message: value,
}))
.filter(({ message }) => !!message);
if (responseFormattedValidationErrors.length) {
throw new PackagePolicyValidationError(
i18n.translate('xpack.fleet.packagePolicyInvalidError', {
defaultMessage: 'Package policy is invalid: {errors}',
values: {
errors: responseFormattedValidationErrors
.map(({ key, message }) => `${key}: ${message}`)
.join('\n'),
},
})
);
}
}
validatePackagePolicyOrThrow(resultingPackagePolicy, packageInfo);
return resultingPackagePolicy;
}

View file

@ -0,0 +1,16 @@
- name: data_stream.type
type: constant_keyword
description: >
Data stream type.
- name: data_stream.dataset
type: constant_keyword
description: >
Data stream dataset.
- name: data_stream.namespace
type: constant_keyword
description: >
Data stream namespace.
- name: '@timestamp'
type: date
description: >
Event timestamp.

View file

@ -0,0 +1,15 @@
title: Test stream
type: logs
streams:
- input: test_input
vars:
- name: test_var_required
type: string
title: Test Var
required: true
show_user: true
- name: test_var
type: string
title: Test Var
required: false
show_user: true

View file

@ -0,0 +1,5 @@
# filetest
This package contains randomly collected files from other packages to be used in API integration tests.
It also serves as an example how to serve a package from the fixtures directory with the package registry docker container. For this, also see the `x-pack/test/fleet_api_integration/config.ts` how the `test_packages` directory is mounted into the docker container, and `x-pack/test/fleet_api_integration/apis/fixtures/package_registry_config.yml` how to pass the directory to the registry.

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
<g fill="none" fill-rule="evenodd">
<path fill="#F04E98" d="M29,32.0001 L15.935,9.4321 C13.48,5.1941 7,6.9351 7,11.8321 L7,52.1681 C7,57.0651 13.48,58.8061 15.935,54.5671 L29,32.0001 Z"/>
<path fill="#FA744E" d="M34.7773,32.0001 L33.3273,34.5051 L20.2613,57.0731 C19.8473,57.7871 19.3533,58.4271 18.8023,59.0001 L34.9273,59.0001 C38.7073,59.0001 42.2213,57.0601 44.2363,53.8611 L58.0003,32.0001 L34.7773,32.0001 Z"/>
<path fill="#343741" d="M44.2363,10.1392 C42.2213,6.9402 38.7073,5.0002 34.9273,5.0002 L18.8023,5.0002 C19.3533,5.5732 19.8473,6.2122 20.2613,6.9272 L33.3273,29.4942 L34.7773,32.0002 L58.0003,32.0002 L44.2363,10.1392 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 750 B

View file

@ -0,0 +1,41 @@
format_version: 1.0.0
name: with_required_variables
title: Package with variables
description: This is a package.
version: 0.1.0
categories: []
# Options are experimental, beta, ga
release: beta
# The package type. The options for now are [integration, solution], more type might be added in the future.
# The default type is integration and will be set if empty.
type: integration
license: basic
# This package can be removed
removable: true
requirement:
elasticsearch:
versions: ">7.7.0"
kibana:
versions: ">7.7.0"
screenshots:
- src: "/img/screenshots/metricbeat_dashboard.png"
title: "metricbeat dashboard"
size: "1855x949"
type: "image/png"
icons:
- src: "/img/logo.svg"
size: "16x16"
type: "image/svg+xml"
policy_templates:
- name: with_required_variables
title: Package Policy Upgrade
description: Test Package for Upgrading Package Policies
inputs:
- type: test_input
title: Test Input
description: Test Input
enabled: true

View file

@ -324,5 +324,80 @@ export default function (providerContext: FtrProviderContext) {
})
.expect(400);
});
it('should return a 400 with required variables not provided', async function () {
const { body } = await supertest
.post(`/api/fleet/package_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'pacakge-policy-required-variables-test-456',
description: '',
namespace: 'default',
policy_id: agentPolicyId,
enabled: true,
output_id: '',
inputs: [
{
enabled: true,
streams: [
{
data_stream: {
dataset: 'with_required_variables.log',
type: 'logs',
},
enabled: true,
vars: {},
},
],
type: 'test_input',
},
],
package: {
name: 'with_required_variables',
version: '0.1.0',
},
})
.expect(400);
expect(body.message).contain('Package policy is invalid');
});
it('should work with required variables provided', async function () {
await supertest
.post(`/api/fleet/package_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'pacakge-policy-required-variables-test-123',
description: '',
namespace: 'default',
policy_id: agentPolicyId,
enabled: true,
output_id: '',
inputs: [
{
enabled: true,
streams: [
{
data_stream: {
dataset: 'with_required_variables.log',
type: 'logs',
},
enabled: true,
vars: {
test_var_required: {
value: 'I am required',
},
},
},
],
type: 'test_input',
},
],
package: {
name: 'with_required_variables',
version: '0.1.0',
},
})
.expect(200);
});
});
}

View file

@ -841,6 +841,7 @@ export default function (providerContext: FtrProviderContext) {
policy_template: 'package_policy_upgrade',
type: 'test_input_new_2',
enabled: true,
vars: {},
streams: [
{
id: 'test-package_policy_upgrade-xxxx',
@ -850,6 +851,12 @@ export default function (providerContext: FtrProviderContext) {
dataset: 'package_policy_upgrade.test_stream_new_2',
},
vars: {
test_input_new_2_var_1: {
value: 'Test input value 1',
},
test_input_new_2_var_2: {
value: 'Test input value 2',
},
test_var_new_2_var_1: {
value: 'Test value 1',
},
@ -867,7 +874,6 @@ export default function (providerContext: FtrProviderContext) {
version: '0.5.0-restructure-inputs',
},
});
packagePolicyId = packagePolicyResponse.item.id;
});