mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Cloud Posture] Rename and modify dataYml to runtimeCfg (#138248)
This commit is contained in:
parent
c54d91f1a4
commit
cb5f9d5d12
10 changed files with 69 additions and 78 deletions
|
@ -43,13 +43,5 @@ export const INTERNAL_FEATURE_FLAGS = {
|
|||
export const CSP_RULE_SAVED_OBJECT_TYPE = 'csp_rule';
|
||||
export const CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE = 'csp-rule-template';
|
||||
|
||||
export const CLOUDBEAT_VANILLA = 'cloudbeat/vanilla'; // Integration input
|
||||
export const INTEGRATION_CIS_K8S = 'cis_k8s'; // rule template benchmark id
|
||||
|
||||
export const CLOUDBEAT_EKS = 'cloudbeat/eks'; // Integration input
|
||||
export const INTEGRATION_CIS_EKS = 'cis_eks'; // rule template benchmark id
|
||||
|
||||
export const CIS_INTEGRATION_INPUTS_MAP = {
|
||||
[CLOUDBEAT_VANILLA]: INTEGRATION_CIS_K8S,
|
||||
[CLOUDBEAT_EKS]: INTEGRATION_CIS_EKS,
|
||||
} as const;
|
||||
export const CLOUDBEAT_VANILLA = 'cloudbeat/cis_k8s'; // Integration input
|
||||
export const CLOUDBEAT_EKS = 'cloudbeat/cis_eks'; // Integration input
|
||||
|
|
|
@ -6,13 +6,11 @@
|
|||
*/
|
||||
import { schema as rt, TypeOf } from '@kbn/config-schema';
|
||||
|
||||
export const benchmarkIdSchema = rt.oneOf([rt.literal('cis_k8s'), rt.literal('cis_eks')]);
|
||||
|
||||
export const cspRuleMetadataSchema = rt.object({
|
||||
audit: rt.string(),
|
||||
benchmark: rt.object({
|
||||
name: rt.string(),
|
||||
id: benchmarkIdSchema,
|
||||
id: rt.string(),
|
||||
version: rt.string(),
|
||||
}),
|
||||
default_value: rt.maybe(rt.string()),
|
||||
|
|
|
@ -5,12 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { schema as rt, TypeOf } from '@kbn/config-schema';
|
||||
import { benchmarkIdSchema } from './csp_rule_metadata';
|
||||
|
||||
// cspRulesConfigSchema has to match the 'DataYaml' struct in https://github.com/elastic/cloudbeat/blob/main/config/config.go#L45-L51
|
||||
// cspRulesConfigSchema has to match the 'RuntimeCfg' struct in https://github.com/elastic/cloudbeat/blob/main/config/config.go#L45-L51
|
||||
export const cspRulesConfigSchema = rt.object({
|
||||
data_yaml: rt.object({
|
||||
activated_rules: rt.recordOf(benchmarkIdSchema, rt.arrayOf(rt.string())),
|
||||
runtime_cfg: rt.object({
|
||||
activated_rules: rt.recordOf(rt.string(), rt.arrayOf(rt.string())),
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { CIS_INTEGRATION_INPUTS_MAP } from '../../../common/constants';
|
||||
import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../../common/constants';
|
||||
|
||||
export type InputType = keyof typeof CIS_INTEGRATION_INPUTS_MAP;
|
||||
export type InputType = typeof CLOUDBEAT_EKS | typeof CLOUDBEAT_VANILLA;
|
||||
|
||||
interface Props {
|
||||
type: InputType;
|
||||
|
@ -29,14 +29,14 @@ interface Props {
|
|||
|
||||
const kubeDeployOptions: Array<EuiComboBoxOptionOption<InputType>> = [
|
||||
{
|
||||
value: 'cloudbeat/vanilla',
|
||||
value: CLOUDBEAT_VANILLA,
|
||||
label: i18n.translate(
|
||||
'xpack.csp.createPackagePolicy.stepConfigure.integrationSettingsSection.vanillaKubernetesDeploymentOption',
|
||||
{ defaultMessage: 'Unmanaged Kubernetes' }
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'cloudbeat/eks',
|
||||
value: CLOUDBEAT_EKS,
|
||||
label: i18n.translate(
|
||||
'xpack.csp.createPackagePolicy.stepConfigure.integrationSettingsSection.eksKubernetesDeploymentOption',
|
||||
{ defaultMessage: 'EKS (Elastic Kubernetes Service)' }
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import type { NewPackagePolicy } from '@kbn/fleet-plugin/public';
|
||||
import type { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import { BenchmarkId } from '../../../common/types';
|
||||
import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../../common/constants';
|
||||
|
||||
export const getCspNewPolicyMock = (type: BenchmarkId = 'cis_k8s'): NewPackagePolicy => ({
|
||||
name: 'some-cloud_security_posture-policy',
|
||||
|
@ -17,7 +18,7 @@ export const getCspNewPolicyMock = (type: BenchmarkId = 'cis_k8s'): NewPackagePo
|
|||
output_id: '',
|
||||
inputs: [
|
||||
{
|
||||
type: 'cloudbeat/vanilla',
|
||||
type: CLOUDBEAT_VANILLA,
|
||||
policy_template: 'kspm',
|
||||
enabled: type === 'cis_k8s',
|
||||
streams: [
|
||||
|
@ -31,7 +32,7 @@ export const getCspNewPolicyMock = (type: BenchmarkId = 'cis_k8s'): NewPackagePo
|
|||
],
|
||||
},
|
||||
{
|
||||
type: 'cloudbeat/eks',
|
||||
type: CLOUDBEAT_EKS,
|
||||
policy_template: 'kspm',
|
||||
enabled: type === 'cis_eks',
|
||||
streams: [
|
||||
|
@ -62,7 +63,7 @@ export const getCspNewPolicyMock = (type: BenchmarkId = 'cis_k8s'): NewPackagePo
|
|||
version: '0.0.21',
|
||||
},
|
||||
vars: {
|
||||
dataYaml: {
|
||||
runtimeCfg: {
|
||||
type: 'yaml',
|
||||
},
|
||||
},
|
||||
|
@ -100,7 +101,7 @@ export const getCspPolicyMock = (type: BenchmarkId = 'cis_k8s'): PackagePolicy =
|
|||
enabled: true,
|
||||
},
|
||||
],
|
||||
type: 'cloudbeat/vanilla',
|
||||
type: CLOUDBEAT_VANILLA,
|
||||
enabled: type === 'cis_k8s',
|
||||
},
|
||||
{
|
||||
|
@ -126,7 +127,7 @@ export const getCspPolicyMock = (type: BenchmarkId = 'cis_k8s'): PackagePolicy =
|
|||
enabled: false,
|
||||
},
|
||||
],
|
||||
type: 'cloudbeat/eks',
|
||||
type: CLOUDBEAT_EKS,
|
||||
enabled: type === 'cis_eks',
|
||||
},
|
||||
],
|
||||
|
|
|
@ -125,8 +125,8 @@ describe('create CSP rules with post package create callback', () => {
|
|||
|
||||
// Both enabled falls back to default
|
||||
mockPackagePolicy.inputs = [
|
||||
{ type: 'cloudbeat/vanilla', enabled: true, streams: [] },
|
||||
{ type: 'cloudbeat/eks', enabled: true, streams: [] },
|
||||
{ type: 'cloudbeat/cis_k8s', enabled: true, streams: [] },
|
||||
{ type: 'cloudbeat/cis_eks', enabled: true, streams: [] },
|
||||
];
|
||||
const type = getBenchmarkInputType(mockPackagePolicy.inputs);
|
||||
expect(type).toMatch('cis_k8s');
|
||||
|
@ -137,8 +137,8 @@ describe('create CSP rules with post package create callback', () => {
|
|||
|
||||
// None enabled falls back to default
|
||||
mockPackagePolicy.inputs = [
|
||||
{ type: 'cloudbeat/vanilla', enabled: false, streams: [] },
|
||||
{ type: 'cloudbeat/eks', enabled: false, streams: [] },
|
||||
{ type: 'cloudbeat/cis_k8s', enabled: false, streams: [] },
|
||||
{ type: 'cloudbeat/cis_eks', enabled: false, streams: [] },
|
||||
];
|
||||
const type = getBenchmarkInputType(mockPackagePolicy.inputs);
|
||||
expect(type).toMatch('cis_k8s');
|
||||
|
@ -149,8 +149,8 @@ describe('create CSP rules with post package create callback', () => {
|
|||
|
||||
// Single EKS selected
|
||||
mockPackagePolicy.inputs = [
|
||||
{ type: 'cloudbeat/eks', enabled: true, streams: [] },
|
||||
{ type: 'cloudbeat/vanilla', enabled: false, streams: [] },
|
||||
{ type: 'cloudbeat/cis_eks', enabled: true, streams: [] },
|
||||
{ type: 'cloudbeat/cis_k8s', enabled: false, streams: [] },
|
||||
];
|
||||
const typeEks = getBenchmarkInputType(mockPackagePolicy.inputs);
|
||||
expect(typeEks).toMatch('cis_eks');
|
||||
|
@ -161,8 +161,8 @@ describe('create CSP rules with post package create callback', () => {
|
|||
|
||||
// Single k8s selected
|
||||
mockPackagePolicy.inputs = [
|
||||
{ type: 'cloudbeat/eks', enabled: false, streams: [] },
|
||||
{ type: 'cloudbeat/vanilla', enabled: true, streams: [] },
|
||||
{ type: 'cloudbeat/cis_eks', enabled: false, streams: [] },
|
||||
{ type: 'cloudbeat/cis_k8s', enabled: true, streams: [] },
|
||||
];
|
||||
const typeK8s = getBenchmarkInputType(mockPackagePolicy.inputs);
|
||||
expect(typeK8s).toMatch('cis_k8s');
|
||||
|
|
|
@ -20,30 +20,27 @@ import {
|
|||
import { createCspRuleSearchFilterByPackagePolicy } from '../../common/utils/helpers';
|
||||
import {
|
||||
CLOUDBEAT_VANILLA,
|
||||
CIS_INTEGRATION_INPUTS_MAP,
|
||||
CSP_RULE_SAVED_OBJECT_TYPE,
|
||||
CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE,
|
||||
} from '../../common/constants';
|
||||
import type { CspRule, CspRuleTemplate } from '../../common/schemas';
|
||||
import type { BenchmarkId } from '../../common/types';
|
||||
|
||||
type CloudbeatInputType = keyof typeof CIS_INTEGRATION_INPUTS_MAP;
|
||||
|
||||
const getBenchmarkTypeFilter = (type: BenchmarkId): string =>
|
||||
`${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`;
|
||||
|
||||
const isEnabledBenchmarkInputType = (input: PackagePolicyInput) =>
|
||||
input.type in CIS_INTEGRATION_INPUTS_MAP && !!input.enabled;
|
||||
const isEnabledBenchmarkInputType = (input: PackagePolicyInput) => !!input.type && input.enabled;
|
||||
|
||||
export const getBenchmarkInputType = (inputs: PackagePolicy['inputs']): BenchmarkId => {
|
||||
const enabledInputs = inputs.filter(isEnabledBenchmarkInputType);
|
||||
|
||||
// Use the only enabled input
|
||||
if (enabledInputs.length === 1)
|
||||
return CIS_INTEGRATION_INPUTS_MAP[enabledInputs[0].type as CloudbeatInputType];
|
||||
if (enabledInputs.length === 1) {
|
||||
return getInputType(enabledInputs[0].type);
|
||||
}
|
||||
|
||||
// Use the the default input for multiple/none selected
|
||||
return CIS_INTEGRATION_INPUTS_MAP[CLOUDBEAT_VANILLA];
|
||||
// Use the default benchmark id for multiple/none selected
|
||||
return getInputType(CLOUDBEAT_VANILLA);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -142,3 +139,8 @@ const generateRulesFromTemplates = (
|
|||
policy_id: policyId,
|
||||
},
|
||||
}));
|
||||
|
||||
const getInputType = (inputType: string): string => {
|
||||
// Get the last part of the input type, input type structure: cloudbeat/<benchmark_id>
|
||||
return inputType.split('/')[1];
|
||||
};
|
||||
|
|
|
@ -241,7 +241,7 @@ describe('Cloud Security Posture Plugin', () => {
|
|||
|
||||
const packageMock = createPackagePolicyMock();
|
||||
packageMock.package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME;
|
||||
packageMock.vars = { dataYaml: { type: 'foo' } };
|
||||
packageMock.vars = { runtimeCfg: { type: 'foo' } };
|
||||
|
||||
const packagePolicyPostCreateCallbacks: PostPackagePolicyPostCreateCallback[] = [];
|
||||
fleetMock.registerExternalCallback.mockImplementation((...args) => {
|
||||
|
@ -272,8 +272,8 @@ describe('Cloud Security Posture Plugin', () => {
|
|||
);
|
||||
if (fleetMock.packagePolicyService.update.mock.calls.length) {
|
||||
expect(updatedPackagePolicy).toHaveProperty('vars');
|
||||
expect(updatedPackagePolicy.vars).toHaveProperty('dataYaml');
|
||||
expect(updatedPackagePolicy.vars!.dataYaml).toHaveProperty('value');
|
||||
expect(updatedPackagePolicy.vars).toHaveProperty('runtimeCfg');
|
||||
expect(updatedPackagePolicy.vars!.runtimeCfg).toHaveProperty('value');
|
||||
}
|
||||
}
|
||||
expect(fleetMock.packagePolicyService.update).toHaveBeenCalledTimes(1);
|
||||
|
|
|
@ -134,7 +134,7 @@ describe('Update rules configuration API', () => {
|
|||
};
|
||||
const cspConfig = await createRulesConfig(cspRules as SavedObjectsFindResponse<CspRule>);
|
||||
expect(cspConfig).toMatchObject({
|
||||
data_yaml: { activated_rules: { cis_k8s: ['cis_1_1_1', 'cis_1_1_3'] } },
|
||||
runtime_cfg: { activated_rules: { cis_k8s: ['cis_1_1_1', 'cis_1_1_3'] } },
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -177,24 +177,24 @@ describe('Update rules configuration API', () => {
|
|||
],
|
||||
};
|
||||
const cspConfig = await createRulesConfig(cspRules as SavedObjectsFindResponse<CspRule>);
|
||||
expect(cspConfig).toMatchObject({ data_yaml: { activated_rules: { cis_k8s: [] } } });
|
||||
expect(cspConfig).toMatchObject({ runtime_cfg: { activated_rules: {} } });
|
||||
});
|
||||
|
||||
it('validate adding new dataYaml to package policy instance', async () => {
|
||||
it('validate adding new runtimeCfg to package policy instance', async () => {
|
||||
const packagePolicy = createPackagePolicyMock();
|
||||
packagePolicy.vars = { dataYaml: { type: 'yaml' } };
|
||||
packagePolicy.vars = { runtimeCfg: { type: 'yaml' } };
|
||||
|
||||
const dataYaml = 'data_yaml:\n activated_rules:\n cis_k8s:\n - 1.1.1\n - 1.1.2\n';
|
||||
const updatedPackagePolicy = setVarToPackagePolicy(packagePolicy, dataYaml);
|
||||
expect(updatedPackagePolicy.vars).toEqual({ dataYaml: { type: 'yaml', value: dataYaml } });
|
||||
const runtimeCfg = 'runtime_cfg:\n activated_rules:\n cis_k8s:\n - 1.1.1\n - 1.1.2\n';
|
||||
const updatedPackagePolicy = setVarToPackagePolicy(packagePolicy, runtimeCfg);
|
||||
expect(updatedPackagePolicy.vars).toEqual({ runtimeCfg: { type: 'yaml', value: runtimeCfg } });
|
||||
});
|
||||
|
||||
it('validate adding new dataYaml to package policy instance when it not exists on source', async () => {
|
||||
it('validate adding new runtimeCfg to package policy instance when it not exists on source', async () => {
|
||||
const packagePolicy = createPackagePolicyMock();
|
||||
|
||||
const dataYaml = 'data_yaml:\n activated_rules:\n cis_k8s:\n - 1.1.1\n - 1.1.2\n';
|
||||
const updatedPackagePolicy = setVarToPackagePolicy(packagePolicy, dataYaml);
|
||||
expect(updatedPackagePolicy.vars).toEqual({ dataYaml: { type: 'yaml', value: dataYaml } });
|
||||
const runtimeCfg = 'runtime_cfg:\n activated_rules:\n cis_k8s:\n - 1.1.1\n - 1.1.2\n';
|
||||
const updatedPackagePolicy = setVarToPackagePolicy(packagePolicy, runtimeCfg);
|
||||
expect(updatedPackagePolicy.vars).toEqual({ runtimeCfg: { type: 'yaml', value: runtimeCfg } });
|
||||
});
|
||||
|
||||
it('verify that the API for updating package policy was invoked', async () => {
|
||||
|
@ -254,7 +254,7 @@ describe('Update rules configuration API', () => {
|
|||
mockSoClient.find.mockResolvedValueOnce(cspRules as SavedObjectsFindResponse<CspRule>);
|
||||
|
||||
const mockPackagePolicy = createPackagePolicyMock();
|
||||
mockPackagePolicy.vars = { dataYaml: { type: 'foo' } };
|
||||
mockPackagePolicy.vars = { runtimeCfg: { type: 'foo' } };
|
||||
const packagePolicyId1 = chance.guid();
|
||||
mockPackagePolicy.id = packagePolicyId1;
|
||||
|
||||
|
@ -268,8 +268,8 @@ describe('Update rules configuration API', () => {
|
|||
user
|
||||
);
|
||||
|
||||
expect(updatePackagePolicy.vars!.dataYaml).toHaveProperty('value');
|
||||
expect(updatePackagePolicy.vars!.dataYaml).toMatchObject({ type: 'yaml' });
|
||||
expect(updatePackagePolicy.vars!.runtimeCfg).toHaveProperty('value');
|
||||
expect(updatePackagePolicy.vars!.runtimeCfg).toMatchObject({ type: 'yaml' });
|
||||
expect(mockPackagePolicyService.update).toBeCalledTimes(1);
|
||||
expect(mockPackagePolicyService.update.mock.calls[0][2]).toEqual(packagePolicyId1);
|
||||
});
|
||||
|
@ -322,7 +322,7 @@ describe('Update rules configuration API', () => {
|
|||
const packagePolicyId1 = chance.guid();
|
||||
const user = null;
|
||||
mockPackagePolicy.id = packagePolicyId1;
|
||||
mockPackagePolicy.vars = { foo: {}, dataYaml: { type: 'yaml' } };
|
||||
mockPackagePolicy.vars = { foo: {}, runtimeCfg: { type: 'yaml' } };
|
||||
|
||||
mockPackagePolicyService.update.mockImplementation(
|
||||
(
|
||||
|
@ -375,7 +375,7 @@ describe('Update rules configuration API', () => {
|
|||
};
|
||||
mockSoClient.find.mockResolvedValueOnce(cspRules as SavedObjectsFindResponse<CspRule>);
|
||||
|
||||
mockPackagePolicy.vars = { dataYaml: { type: 'yaml' } };
|
||||
mockPackagePolicy.vars = { runtimeCfg: { type: 'yaml' } };
|
||||
|
||||
await updateAgentConfiguration(
|
||||
mockPackagePolicyService,
|
||||
|
|
|
@ -66,22 +66,21 @@ export const getCspRules = (
|
|||
};
|
||||
|
||||
const getEnabledRulesByBenchmark = (rules: SavedObjectsFindResponse<CspRule>['saved_objects']) =>
|
||||
rules.reduce<CspRulesConfiguration['data_yaml']['activated_rules']>(
|
||||
(benchmarks, rule) => {
|
||||
const benchmark = benchmarks[rule.attributes.metadata.benchmark.id];
|
||||
if (!rule.attributes.enabled || !benchmark) return benchmarks;
|
||||
rules.reduce<CspRulesConfiguration['runtime_cfg']['activated_rules']>((benchmarks, rule) => {
|
||||
const benchmark = rule.attributes.metadata.benchmark.id;
|
||||
if (!rule.attributes.enabled || !benchmark) return benchmarks;
|
||||
if (!benchmarks[benchmark]) {
|
||||
benchmarks[benchmark] = [];
|
||||
}
|
||||
|
||||
benchmark.push(rule.attributes.metadata.rego_rule_id);
|
||||
|
||||
return benchmarks;
|
||||
},
|
||||
{ cis_k8s: [], cis_eks: [] }
|
||||
);
|
||||
benchmarks[benchmark].push(rule.attributes.metadata.rego_rule_id);
|
||||
return benchmarks;
|
||||
}, {});
|
||||
|
||||
export const createRulesConfig = (
|
||||
cspRules: SavedObjectsFindResponse<CspRule>
|
||||
): CspRulesConfiguration => ({
|
||||
data_yaml: {
|
||||
runtime_cfg: {
|
||||
activated_rules: getEnabledRulesByBenchmark(cspRules.saved_objects),
|
||||
},
|
||||
});
|
||||
|
@ -92,15 +91,15 @@ export const convertRulesConfigToYaml = (config: CspRulesConfiguration): string
|
|||
|
||||
export const setVarToPackagePolicy = (
|
||||
packagePolicy: PackagePolicy,
|
||||
dataYaml: string
|
||||
runtimeCfg: string
|
||||
): PackagePolicy => {
|
||||
const configFile: PackagePolicyConfigRecord = {
|
||||
dataYaml: { type: 'yaml', value: dataYaml },
|
||||
runtimeCfg: { type: 'yaml', value: runtimeCfg },
|
||||
};
|
||||
const updatedPackagePolicy = produce(packagePolicy, (draft) => {
|
||||
unset(draft, 'id');
|
||||
if (draft.vars) {
|
||||
draft.vars.dataYaml = configFile.dataYaml;
|
||||
draft.vars.runtimeCfg = configFile.runtimeCfg;
|
||||
} else {
|
||||
draft.vars = configFile;
|
||||
}
|
||||
|
@ -117,8 +116,8 @@ export const updateAgentConfiguration = async (
|
|||
): Promise<PackagePolicy> => {
|
||||
const cspRules = await getCspRules(soClient, packagePolicy);
|
||||
const rulesConfig = createRulesConfig(cspRules);
|
||||
const dataYaml = convertRulesConfigToYaml(rulesConfig);
|
||||
const updatedPackagePolicy = setVarToPackagePolicy(packagePolicy, dataYaml);
|
||||
const runtimeCfg = convertRulesConfigToYaml(rulesConfig);
|
||||
const updatedPackagePolicy = setVarToPackagePolicy(packagePolicy, runtimeCfg);
|
||||
const options = { user: user ? user : undefined };
|
||||
return packagePolicyService.update(
|
||||
soClient,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue