From 509be27f2e7f1665fde5b623025b3e4cbf84355d Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 6 Dec 2022 17:20:08 +0200 Subject: [PATCH 01/23] Working version - before running tests --- .../cloud_security_posture/common/types.ts | 9 +-- .../common/utils/helpers.ts | 8 ++- .../public/common/navigation/constants.ts | 3 +- .../pages/benchmarks/benchmarks_table.tsx | 7 +- .../public/pages/rules/rules_container.tsx | 9 +-- .../public/pages/rules/use_csp_rules.ts | 16 +++-- .../fixtures/csp_benchmark_integration.ts | 10 ++- .../fleet_integration/fleet_integration.ts | 23 +++---- .../routes/benchmarks/benchmarks.test.ts | 4 +- .../server/routes/benchmarks/benchmarks.ts | 68 +++++-------------- .../server/saved_objects/mappings.ts | 8 +++ 11 files changed, 69 insertions(+), 96 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index 2421e22b8b5d7..ab60d51ea28e5 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -90,18 +90,13 @@ interface CspSetupInstalledStatus extends BaseCspSetupStatus { export type CspSetupStatus = CspSetupInstalledStatus | CspSetupNotInstalledStatus; -export interface CspRulesStatus { - all: number; - enabled: number; - disabled: number; -} - export type AgentPolicyStatus = Pick & { agents: number }; export interface Benchmark { package_policy: PackagePolicy; agent_policy: AgentPolicyStatus; - rules: CspRulesStatus; + benchmark_id: BenchmarkId; + number_of_rules: number; } export type BenchmarkId = CspRuleMetadata['benchmark']['id']; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 6d5dcd454a1c0..9de9d425f440e 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -6,7 +6,9 @@ */ import { Truthy } from 'lodash'; -import { CSP_RULE_SAVED_OBJECT_TYPE } from '../constants'; +import { PackagePolicyInput } from '@kbn/fleet-plugin/common'; +import { CSP_RULE_SAVED_OBJECT_TYPE, CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../constants'; +import { BenchmarkId } from '../types'; /** * @example @@ -35,3 +37,7 @@ export const createCspRuleSearchFilterByPackagePolicy = ({ `${CSP_RULE_SAVED_OBJECT_TYPE}.attributes.package_policy_id: "${packagePolicyId}"${ policyId ? ` AND ${CSP_RULE_SAVED_OBJECT_TYPE}.attributes.policy_id: "${policyId}"` : '' }`; +export const getBenchmarkTypeFilter = (type: BenchmarkId): string => + `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`; +export const isEnabledBenchmarkInputType = (input: PackagePolicyInput) => + !!input.type && input.enabled; diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts index 7de2479600074..aa7d1b3157181 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts @@ -44,10 +44,11 @@ export const cloudPosturePages: Record = { }, }; +// CR - Do we wish to keep the packagePolicyId and the policyId in the URL? export const benchmarksNavigation: Record = { rules: { name: NAV_ITEMS_NAMES.RULES, - path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/benchmarks/:packagePolicyId/:policyId/rules`, + path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/benchmarks/:packagePolicyId/:policyId/:benchmarkId/rules`, id: 'cloud_security_posture-benchmarks-rules', }, }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx index d1c92ab40a72f..28b02513f1ff1 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx @@ -44,19 +44,21 @@ const IntegrationButtonLink = ({ packageName, policyId, packagePolicyId, + benchmarkId, }: { packageName: string; packagePolicyId: string; policyId: string; + benchmarkId: string; }) => { const { application } = useKibana().services; - return ( @@ -76,6 +78,7 @@ const BENCHMARKS_TABLE_COLUMNS: Array> = [ packageName={packageName} packagePolicyId={benchmark.package_policy.id} policyId={benchmark.package_policy.policy_id} + benchmarkId={benchmark.benchmark_id} /> ), truncateText: true, @@ -83,7 +86,7 @@ const BENCHMARKS_TABLE_COLUMNS: Array> = [ 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.INTEGRATION_NAME, }, { - field: 'rules.enabled', + field: 'number_of_rules', name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.rulesColumnTitle', { defaultMessage: 'Rules', }), diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx index 534d3d2f34237..8e3a6d9052341 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx @@ -9,7 +9,7 @@ import { EuiPanel, EuiSpacer } from '@elastic/eui'; import { useParams } from 'react-router-dom'; import { extractErrorMessage, - createCspRuleSearchFilterByPackagePolicy, + getBenchmarkTypeFilter, isNonNullable, } from '../../../common/utils/helpers'; import { RulesTable } from './rules_table'; @@ -65,17 +65,14 @@ const getPage = (data: readonly RuleSavedObject[], { page, perPage }: RulesQuery const MAX_ITEMS_PER_PAGE = 10000; -export type PageUrlParams = Record<'policyId' | 'packagePolicyId', string>; +export type PageUrlParams = Record<'policyId' | 'packagePolicyId' | 'benchmarkId', string>; export const RulesContainer = () => { const params = useParams(); const [selectedRuleId, setSelectedRuleId] = useState(null); const { pageSize, setPageSize } = usePageSize(LOCAL_STORAGE_PAGE_SIZE_RULES_KEY); const [rulesQuery, setRulesQuery] = useState({ - filter: createCspRuleSearchFilterByPackagePolicy({ - packagePolicyId: params.packagePolicyId, - policyId: params.policyId, - }), + filter: getBenchmarkTypeFilter(params.benchmarkId), search: '', page: 0, perPage: pageSize || 10, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts index ad299d72be0e3..621bedfb8d1a3 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts @@ -7,11 +7,14 @@ import { useQuery } from '@tanstack/react-query'; import { FunctionKeys } from 'utility-types'; import type { SavedObjectsFindOptions, SimpleSavedObject } from '@kbn/core/public'; -import { CSP_RULE_SAVED_OBJECT_TYPE } from '../../../common/constants'; -import type { CspRule } from '../../../common/schemas'; +import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants'; +import { CspRuleTemplate } from '../../../common/schemas'; import { useKibana } from '../../common/hooks/use_kibana'; -export type RuleSavedObject = Omit, FunctionKeys>; +export type RuleSavedObject = Omit< + SimpleSavedObject, + FunctionKeys +>; export type RulesQuery = Required< Pick @@ -20,10 +23,9 @@ export type RulesQueryResult = ReturnType; export const useFindCspRules = ({ search, page, perPage, filter }: RulesQuery) => { const { savedObjects } = useKibana().services; - - return useQuery([CSP_RULE_SAVED_OBJECT_TYPE, { search, page, perPage }], () => - savedObjects.client.find({ - type: CSP_RULE_SAVED_OBJECT_TYPE, + return useQuery([CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, { search, page, perPage }], () => + savedObjects.client.find({ + type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, search: search ? `"${search}"*` : '', searchFields: ['metadata.name.text'], page: 1, diff --git a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts index 496b73f7bbef0..8d7105377627f 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts @@ -55,13 +55,11 @@ export const createCspBenchmarkIntegrationFixture = ({ name: chance.sentence(), agents: chance.integer({ min: 0 }), }, - rules = { - all: chance.integer(), - enabled: chance.integer(), - disabled: chance.integer(), - }, + number_of_rules, + benchmark_id, }: CreateCspBenchmarkIntegrationFixtureInput = {}): Benchmark => ({ package_policy, agent_policy, - rules, + number_of_rules, + benchmark_id, }); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index fbea07836f5b2..e3532ad21525e 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -5,20 +5,20 @@ * 2.0. */ import type { + ISavedObjectsRepository, + Logger, SavedObjectsBulkCreateObject, + SavedObjectsClientContract, SavedObjectsFindResponse, SavedObjectsFindResult, - ISavedObjectsRepository, - SavedObjectsClientContract, - Logger, } from '@kbn/core/server'; -import { - PackagePolicy, - DeletePackagePoliciesResponse, - PackagePolicyInput, -} from '@kbn/fleet-plugin/common'; +import { DeletePackagePoliciesResponse, PackagePolicy } from '@kbn/fleet-plugin/common'; import { DeepReadonly } from 'utility-types'; -import { createCspRuleSearchFilterByPackagePolicy } from '../../common/utils/helpers'; +import { + createCspRuleSearchFilterByPackagePolicy, + getBenchmarkTypeFilter, + isEnabledBenchmarkInputType, +} from '../../common/utils/helpers'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, CLOUDBEAT_VANILLA, @@ -28,11 +28,6 @@ import { import type { CspRule, CspRuleTemplate } from '../../common/schemas'; import type { BenchmarkId } from '../../common/types'; -const getBenchmarkTypeFilter = (type: BenchmarkId): string => - `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`; - -const isEnabledBenchmarkInputType = (input: PackagePolicyInput) => !!input.type && input.enabled; - export const getBenchmarkInputType = (inputs: PackagePolicy['inputs']): BenchmarkId => { const enabledInputs = inputs.filter(isEnabledBenchmarkInputType); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index 49c392d724c25..5445af918c7e0 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -14,7 +14,7 @@ import { getCspPackagePolicies, getCspAgentPolicies, } from '../../lib/fleet_util'; -import { defineGetBenchmarksRoute, addPackagePolicyCspRules } from './benchmarks'; +import { defineGetBenchmarksRoute, getRulesCountForPolicy } from './benchmarks'; import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; import { @@ -274,7 +274,7 @@ describe('benchmarks API', () => { ], } as unknown as SavedObjectsFindResponse); - const cspRulesStatus = await addPackagePolicyCspRules(mockSoClient, packagePolicy); + const cspRulesStatus = await getRulesCountForPolicy(mockSoClient, packagePolicy); expect(cspRulesStatus).toEqual({ all: 3, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index dec553cee6f75..1e05ab272dce1 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -4,21 +4,19 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { AgentPolicy, PackagePolicy } from '@kbn/fleet-plugin/common'; +import { getBenchmarkInputType } from '../../fleet_integration/fleet_integration'; +import { CspRuleTemplate } from '../../../common/schemas'; +import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { BENCHMARKS_ROUTE_PATH, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, - CSP_RULE_SAVED_OBJECT_TYPE, } from '../../../common/constants'; import { benchmarksQueryParamsSchema } from '../../../common/schemas/benchmark'; -import type { Benchmark, CspRulesStatus } from '../../../common/types'; -import type { CspRule } from '../../../common/schemas'; -import { - createCspRuleSearchFilterByPackagePolicy, - isNonNullable, -} from '../../../common/utils/helpers'; +import type { Benchmark } from '../../../common/types'; +import { getBenchmarkTypeFilter, isNonNullable } from '../../../common/utils/helpers'; import { CspRouter } from '../../types'; import { getAgentStatusesByAgentPolicies, @@ -26,52 +24,21 @@ import { getCspAgentPolicies, getCspPackagePolicies, } from '../../lib/fleet_util'; +import { BenchmarkId } from '../../../common/types'; export const PACKAGE_POLICY_SAVED_OBJECT_TYPE = 'ingest-package-policies'; -export interface RulesStatusAggregation { - enabled_status: { - doc_count: number; - }; -} - -export const getCspRulesStatus = ( +export const getRulesCountForPolicy = async ( soClient: SavedObjectsClientContract, - packagePolicy: PackagePolicy -): Promise> => { - const cspRules = soClient.find({ - type: CSP_RULE_SAVED_OBJECT_TYPE, - filter: createCspRuleSearchFilterByPackagePolicy({ - packagePolicyId: packagePolicy.id, - policyId: packagePolicy.policy_id, - }), - aggs: { - enabled_status: { - filter: { - term: { - [`${CSP_RULE_SAVED_OBJECT_TYPE}.attributes.enabled`]: true, - }, - }, - }, - }, + benchmarkName: BenchmarkId +): Promise => { + const rules = await soClient.find({ + type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, + filter: getBenchmarkTypeFilter(benchmarkName), perPage: 0, }); - return cspRules; -}; - -export const addPackagePolicyCspRules = async ( - soClient: SavedObjectsClientContract, - packagePolicy: PackagePolicy -): Promise => { - const rules = await getCspRulesStatus(soClient, packagePolicy); - const packagePolicyRules = { - all: rules.total, - enabled: rules.aggregations?.enabled_status.doc_count || 0, - disabled: rules.total - (rules.aggregations?.enabled_status.doc_count || 0), - }; - - return packagePolicyRules; + return rules.total; }; const createBenchmarks = ( @@ -94,17 +61,18 @@ const createBenchmarks = ( .filter(isNonNullable) ?? []; const benchmarks = cspPackagesOnAgent.map(async (cspPackage) => { - const cspRulesStatus = await addPackagePolicyCspRules(soClient, cspPackage); + const benchmarkId = getBenchmarkInputType(cspPackage.inputs); + const rulesCount = await getRulesCountForPolicy(soClient, benchmarkId); const agentPolicyStatus = { id: agentPolicy.id, name: agentPolicy.name, agents: agentStatusByAgentPolicyId[agentPolicy.id].total, }; - return { package_policy: cspPackage, agent_policy: agentPolicyStatus, - rules: cspRulesStatus, + number_of_rules: rulesCount, + benchmark_id: benchmarkId, }; }); diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts index 829392deaf4e9..f0b21b1cb9806 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts @@ -46,6 +46,14 @@ export const cspRuleTemplateSavedObjectMapping: SavedObjectsTypeMappingDefinitio metadata: { type: 'object', properties: { + name: { + type: 'keyword', + fields: { + text: { + type: 'text', + }, + }, + }, benchmark: { type: 'object', properties: { From d36ffc61dfc9c449c4ab82851af4e4c7df15c0ea Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 6 Dec 2022 18:04:31 +0200 Subject: [PATCH 02/23] Fixing the benchmark tests --- .../server/routes/benchmarks/benchmarks.test.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index 5445af918c7e0..b1506b16f9eb5 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -259,8 +259,8 @@ describe('benchmarks API', () => { }); describe('test addPackagePolicyCspRules', () => { - it('should filter enabled rules', async () => { - const packagePolicy = createPackagePolicyMock(); + it('should return the total number and filtered by the relevant benchmark', async () => { + const benchmark = 'cis_k8s'; mockSoClient.find.mockResolvedValueOnce({ aggregations: { enabled_status: { doc_count: 2 } }, page: 1, @@ -274,13 +274,11 @@ describe('benchmarks API', () => { ], } as unknown as SavedObjectsFindResponse); - const cspRulesStatus = await getRulesCountForPolicy(mockSoClient, packagePolicy); + const cspRulesStatus = await getRulesCountForPolicy(mockSoClient, benchmark); - expect(cspRulesStatus).toEqual({ - all: 3, - enabled: 2, - disabled: 1, - }); + const expectedFilter = `csp-rule-template.attributes.metadata.benchmark.id: "${benchmark}"`; + expect(mockSoClient.find.mock.calls[0][0].filter).toEqual(expectedFilter); + expect(cspRulesStatus).toEqual(3); }); }); }); From 92c248a4ec5eae451da355afe3e3efea3b76a05e Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 6 Dec 2022 18:47:04 +0200 Subject: [PATCH 03/23] Remove posthook for creation of the csp rules --- .../common/utils/helpers.ts | 10 +- .../fleet_integration.test.ts | 115 +--------------- .../fleet_integration/fleet_integration.ts | 128 ++---------------- .../cloud_security_posture/server/plugin.ts | 15 +- 4 files changed, 28 insertions(+), 240 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 9de9d425f440e..7385839687092 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -7,7 +7,11 @@ import { Truthy } from 'lodash'; import { PackagePolicyInput } from '@kbn/fleet-plugin/common'; -import { CSP_RULE_SAVED_OBJECT_TYPE, CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../constants'; +import { + CLOUD_SECURITY_POSTURE_PACKAGE_NAME, + CSP_RULE_SAVED_OBJECT_TYPE, + CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, +} from '../constants'; import { BenchmarkId } from '../types'; /** @@ -39,5 +43,9 @@ export const createCspRuleSearchFilterByPackagePolicy = ({ }`; export const getBenchmarkTypeFilter = (type: BenchmarkId): string => `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`; + export const isEnabledBenchmarkInputType = (input: PackagePolicyInput) => !!input.type && input.enabled; + +export const isCspPackage = (packageName?: string) => + packageName === CLOUD_SECURITY_POSTURE_PACKAGE_NAME; diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts index 65caec79fec73..d779b8083af6d 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts @@ -5,121 +5,10 @@ * 2.0. */ -import { - loggingSystemMock, - savedObjectsClientMock, - savedObjectsRepositoryMock, -} from '@kbn/core/server/mocks'; -import { - ISavedObjectsRepository, - SavedObjectsClientContract, - SavedObjectsFindResponse, -} from '@kbn/core/server'; -import { createPackagePolicyMock, deletePackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; -import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../common/constants'; -import { - getBenchmarkInputType, - onPackagePolicyPostCreateCallback, - removeCspRulesInstancesCallback, -} from './fleet_integration'; +import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; +import { getBenchmarkInputType } from './fleet_integration'; describe('create CSP rules with post package create callback', () => { - let logger: ReturnType; - let mockSoClient: jest.Mocked; - let savedObjectRepositoryMock: jest.Mocked; - const ruleAttributes = { - id: '41308bcdaaf665761478bb6f0d745a5c', - name: 'Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Automated)', - tags: ['CIS', 'Kubernetes', 'CIS 1.1.1', 'Master Node Configuration Files'], - description: - 'Ensure that the API server pod specification file has permissions of `644` or more restrictive.\n', - rationale: - 'The API server pod specification file controls various parameters that set the behavior of the API server. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.\n', - default_value: 'By default, the `kube-apiserver.yaml` file has permissions of `640`.\n', - impact: 'None\n', - remediation: - 'Run the below command (based on the file location on your system) on the\nmaster node.\nFor example,\n```\nchmod 644 /etc/kubernetes/manifests/kube-apiserver.yaml\n```\n', - benchmark: { - name: 'CIS Kubernetes V1.20', - version: 'v1.0.0', - id: 'cis_k8s', - }, - enabled: true, - rego_rule_id: 'cis_1_2_2', - }; - - beforeEach(() => { - logger = loggingSystemMock.createLogger(); - mockSoClient = savedObjectsClientMock.create(); - }); - it('should create stateful rules based on rule template', async () => { - const mockPackagePolicy = createPackagePolicyMock(); - mockPackagePolicy.package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; - mockSoClient.find.mockResolvedValueOnce({ - saved_objects: [ - { - type: 'csp-rule-template', - id: 'csp_rule_template-41308bcdaaf665761478bb6f0d745a5c', - attributes: { ...ruleAttributes }, - }, - ], - pit_id: undefined, - } as unknown as SavedObjectsFindResponse); - - await onPackagePolicyPostCreateCallback(logger, mockPackagePolicy, mockSoClient); - - expect(mockSoClient.bulkCreate.mock.calls[0][0]).toMatchObject([ - { - type: 'csp_rule', - attributes: { - ...ruleAttributes, - package_policy_id: mockPackagePolicy.id, - policy_id: mockPackagePolicy.policy_id, - }, - }, - ]); - }); - - it('validate that all rules templates are fetched', async () => { - const mockPackagePolicy = createPackagePolicyMock(); - mockPackagePolicy.package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; - mockSoClient.find.mockResolvedValueOnce({ - saved_objects: [ - { - type: 'csp-rule-template', - id: 'csp_rule_template-41308bcdaaf665761478bb6f0d745a5c', - attributes: { ...ruleAttributes }, - }, - ], - pit_id: undefined, - } as unknown as SavedObjectsFindResponse); - await onPackagePolicyPostCreateCallback(logger, mockPackagePolicy, mockSoClient); - - expect(mockSoClient.find.mock.calls[0][0]).toMatchObject({ perPage: 10000 }); - }); - - it('validate that all rules templates are deleted', async () => { - savedObjectRepositoryMock = savedObjectsRepositoryMock.create(); - const mockDeletePackagePolicy = deletePackagePolicyMock(); - savedObjectRepositoryMock.find.mockResolvedValueOnce({ - saved_objects: [ - { - type: 'csp-rule-template', - id: 'csp_rule_template-41308bcdaaf665761478bb6f0d745a5c', - attributes: { ...ruleAttributes }, - }, - ], - pit_id: undefined, - } as unknown as SavedObjectsFindResponse); - await removeCspRulesInstancesCallback( - mockDeletePackagePolicy[0], - savedObjectRepositoryMock, - logger - ); - - expect(savedObjectRepositoryMock.find.mock.calls[0][0]).toMatchObject({ perPage: 10000 }); - }); - it('get default integration type from inputs with multiple enabled types', () => { const mockPackagePolicy = createPackagePolicyMock(); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index e3532ad21525e..9ff70ab709965 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -4,103 +4,12 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { - ISavedObjectsRepository, - Logger, - SavedObjectsBulkCreateObject, - SavedObjectsClientContract, - SavedObjectsFindResponse, - SavedObjectsFindResult, -} from '@kbn/core/server'; -import { DeletePackagePoliciesResponse, PackagePolicy } from '@kbn/fleet-plugin/common'; -import { DeepReadonly } from 'utility-types'; -import { - createCspRuleSearchFilterByPackagePolicy, - getBenchmarkTypeFilter, - isEnabledBenchmarkInputType, -} from '../../common/utils/helpers'; -import { - CLOUD_SECURITY_POSTURE_PACKAGE_NAME, - CLOUDBEAT_VANILLA, - 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'; - -export const getBenchmarkInputType = (inputs: PackagePolicy['inputs']): BenchmarkId => { - const enabledInputs = inputs.filter(isEnabledBenchmarkInputType); - - // Use the only enabled input - if (enabledInputs.length === 1) { - return getInputType(enabledInputs[0].type); - } - - // Use the default benchmark id for multiple/none selected - return getInputType(CLOUDBEAT_VANILLA); -}; - -/** - * Callback to handle creation of PackagePolicies in Fleet - */ -export const onPackagePolicyPostCreateCallback = async ( - logger: Logger, - packagePolicy: PackagePolicy, - savedObjectsClient: SavedObjectsClientContract -): Promise => { - const benchmarkType = getBenchmarkInputType(packagePolicy.inputs); - - // Create csp-rules from the generic asset - const existingRuleTemplates: SavedObjectsFindResponse = - await savedObjectsClient.find({ - type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - perPage: 10000, - filter: getBenchmarkTypeFilter(benchmarkType), - }); - - if (existingRuleTemplates.total === 0) { - logger.warn(`expected CSP rule templates to exists for type: ${benchmarkType}`); - return; - } - - const cspRules = generateRulesFromTemplates( - packagePolicy.id, - packagePolicy.policy_id, - existingRuleTemplates.saved_objects - ); - - try { - await savedObjectsClient.bulkCreate(cspRules); - logger.info(`Generated CSP rules for package ${packagePolicy.policy_id}`); - } catch (e) { - logger.error('failed to generate rules out of template'); - logger.error(e); - } -}; - -/** - * Callback to handle deletion of PackagePolicies in Fleet - */ -export const removeCspRulesInstancesCallback = async ( - deletedPackagePolicy: DeepReadonly, - soClient: ISavedObjectsRepository, - logger: Logger -): Promise => { - try { - const { saved_objects: cspRules }: SavedObjectsFindResponse = await soClient.find({ - type: CSP_RULE_SAVED_OBJECT_TYPE, - filter: createCspRuleSearchFilterByPackagePolicy({ - packagePolicyId: deletedPackagePolicy.id, - policyId: deletedPackagePolicy.policy_id, - }), - perPage: 10000, - }); - await Promise.all(cspRules.map((rule) => soClient.delete(CSP_RULE_SAVED_OBJECT_TYPE, rule.id))); - } catch (e) { - logger.error(`Failed to delete CSP rules after delete package ${deletedPackagePolicy.id}`); - logger.error(e); - } -}; +import type { ISavedObjectsRepository, Logger, SavedObjectsFindResponse } from '@kbn/core/server'; +import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { BenchmarkId } from '../../common/types'; +import { isEnabledBenchmarkInputType } from '../../common/utils/helpers'; +import type { CspRule } from '../../common/schemas'; +import { CLOUDBEAT_VANILLA, CSP_RULE_SAVED_OBJECT_TYPE } from '../../common/constants'; export const isCspPackageInstalled = async ( soClient: ISavedObjectsRepository, @@ -122,24 +31,17 @@ export const isCspPackageInstalled = async ( return false; } }; +export const getBenchmarkInputType = (inputs: PackagePolicy['inputs']): BenchmarkId => { + const enabledInputs = inputs.filter(isEnabledBenchmarkInputType); -export const isCspPackage = (packageName?: string) => - packageName === CLOUD_SECURITY_POSTURE_PACKAGE_NAME; - -const generateRulesFromTemplates = ( - packagePolicyId: string, - policyId: string, - cspRuleTemplates: Array> -): Array> => - cspRuleTemplates.map((template) => ({ - type: CSP_RULE_SAVED_OBJECT_TYPE, - attributes: { - ...template.attributes, - package_policy_id: packagePolicyId, - policy_id: policyId, - }, - })); + // Use the only enabled input + if (enabledInputs.length === 1) { + return getInputType(enabledInputs[0].type); + } + // Use the default benchmark id for multiple/none selected + return getInputType(CLOUDBEAT_VANILLA); +}; const getInputType = (inputType: string): string => { // Get the last part of the input type, input type structure: cloudbeat/ return inputType.split('/')[1]; diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 465825e46a80e..8a24b6a4b174f 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -24,6 +24,7 @@ import type { TaskManagerSetupContract, TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; +import { isCspPackage } from '../common/utils/helpers'; import { isSubscriptionAllowed } from '../common/utils/subscription'; import type { CspServerPluginSetup, @@ -36,12 +37,7 @@ import { setupRoutes } from './routes/setup_routes'; import { setupSavedObjects } from './saved_objects'; import { initializeCspIndices } from './create_indices/create_indices'; import { initializeCspTransforms } from './create_transforms/create_transforms'; -import { - isCspPackage, - isCspPackageInstalled, - onPackagePolicyPostCreateCallback, - removeCspRulesInstancesCallback, -} from './fleet_integration/fleet_integration'; +import { isCspPackageInstalled } from './fleet_integration/fleet_integration'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../common/constants'; import { removeFindingsStatsTask, @@ -135,11 +131,6 @@ export class CspPlugin ): Promise => { if (isCspPackage(packagePolicy.package?.name)) { await this.initialize(core, plugins.taskManager); - - const soClient = (await context.core).savedObjects.client; - await onPackagePolicyPostCreateCallback(this.logger, packagePolicy, soClient); - - return packagePolicy; } return packagePolicy; @@ -152,8 +143,6 @@ export class CspPlugin for (const deletedPackagePolicy of deletedPackagePolicies) { if (isCspPackage(deletedPackagePolicy.package?.name)) { const soClient = core.savedObjects.createInternalRepository(); - await removeCspRulesInstancesCallback(deletedPackagePolicy, soClient, this.logger); - const isPackageExists = await isCspPackageInstalled(soClient, this.logger); if (isPackageExists) { From 4c53652e0c4c19861263722d901010be3aa19643 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Wed, 7 Dec 2022 15:52:03 +0200 Subject: [PATCH 04/23] Revert benchmark in URL --- .../public/common/navigation/constants.ts | 3 +-- .../public/pages/benchmarks/benchmarks_table.tsx | 4 ---- .../public/pages/rules/rules_container.tsx | 9 ++++++--- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts index aa7d1b3157181..7de2479600074 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts @@ -44,11 +44,10 @@ export const cloudPosturePages: Record = { }, }; -// CR - Do we wish to keep the packagePolicyId and the policyId in the URL? export const benchmarksNavigation: Record = { rules: { name: NAV_ITEMS_NAMES.RULES, - path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/benchmarks/:packagePolicyId/:policyId/:benchmarkId/rules`, + path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/benchmarks/:packagePolicyId/:policyId/rules`, id: 'cloud_security_posture-benchmarks-rules', }, }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx index 28b02513f1ff1..8cbec56384084 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx @@ -44,12 +44,10 @@ const IntegrationButtonLink = ({ packageName, policyId, packagePolicyId, - benchmarkId, }: { packageName: string; packagePolicyId: string; policyId: string; - benchmarkId: string; }) => { const { application } = useKibana().services; return ( @@ -58,7 +56,6 @@ const IntegrationButtonLink = ({ path: generatePath(benchmarksNavigation.rules.path, { packagePolicyId, policyId, - benchmarkId, }), })} > @@ -78,7 +75,6 @@ const BENCHMARKS_TABLE_COLUMNS: Array> = [ packageName={packageName} packagePolicyId={benchmark.package_policy.id} policyId={benchmark.package_policy.policy_id} - benchmarkId={benchmark.benchmark_id} /> ), truncateText: true, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx index 8e3a6d9052341..534d3d2f34237 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx @@ -9,7 +9,7 @@ import { EuiPanel, EuiSpacer } from '@elastic/eui'; import { useParams } from 'react-router-dom'; import { extractErrorMessage, - getBenchmarkTypeFilter, + createCspRuleSearchFilterByPackagePolicy, isNonNullable, } from '../../../common/utils/helpers'; import { RulesTable } from './rules_table'; @@ -65,14 +65,17 @@ const getPage = (data: readonly RuleSavedObject[], { page, perPage }: RulesQuery const MAX_ITEMS_PER_PAGE = 10000; -export type PageUrlParams = Record<'policyId' | 'packagePolicyId' | 'benchmarkId', string>; +export type PageUrlParams = Record<'policyId' | 'packagePolicyId', string>; export const RulesContainer = () => { const params = useParams(); const [selectedRuleId, setSelectedRuleId] = useState(null); const { pageSize, setPageSize } = usePageSize(LOCAL_STORAGE_PAGE_SIZE_RULES_KEY); const [rulesQuery, setRulesQuery] = useState({ - filter: getBenchmarkTypeFilter(params.benchmarkId), + filter: createCspRuleSearchFilterByPackagePolicy({ + packagePolicyId: params.packagePolicyId, + policyId: params.policyId, + }), search: '', page: 0, perPage: pageSize || 10, From 7b626e6308ce6bca02c27be61d044eb1ddc7e4a3 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Wed, 7 Dec 2022 18:03:24 +0200 Subject: [PATCH 05/23] fixing tests --- .../public/pages/rules/rules_container.tsx | 11 ++------ .../public/pages/rules/use_csp_rules.ts | 28 +++++++++++++------ .../server/plugin.test.ts | 4 +-- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx index 534d3d2f34237..080c0f7055141 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx @@ -7,11 +7,7 @@ import React, { useState, useMemo } from 'react'; import { EuiPanel, EuiSpacer } from '@elastic/eui'; import { useParams } from 'react-router-dom'; -import { - extractErrorMessage, - createCspRuleSearchFilterByPackagePolicy, - isNonNullable, -} from '../../../common/utils/helpers'; +import { extractErrorMessage, isNonNullable } from '../../../common/utils/helpers'; import { RulesTable } from './rules_table'; import { RulesTableHeader } from './rules_table_header'; import { @@ -72,10 +68,7 @@ export const RulesContainer = () => { const [selectedRuleId, setSelectedRuleId] = useState(null); const { pageSize, setPageSize } = usePageSize(LOCAL_STORAGE_PAGE_SIZE_RULES_KEY); const [rulesQuery, setRulesQuery] = useState({ - filter: createCspRuleSearchFilterByPackagePolicy({ - packagePolicyId: params.packagePolicyId, - policyId: params.policyId, - }), + filter: params.packagePolicyId, search: '', page: 0, perPage: pageSize || 10, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts index 621bedfb8d1a3..cf03d2d67e5ef 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts @@ -7,6 +7,9 @@ import { useQuery } from '@tanstack/react-query'; import { FunctionKeys } from 'utility-types'; import type { SavedObjectsFindOptions, SimpleSavedObject } from '@kbn/core/public'; +import { NewPackagePolicy, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; +import { getBenchmarkTypeFilter } from '../../../common/utils/helpers'; +import { getBenchmarkInputType } from '../../../server/fleet_integration/fleet_integration'; import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { CspRuleTemplate } from '../../../common/schemas'; import { useKibana } from '../../common/hooks/use_kibana'; @@ -23,15 +26,22 @@ export type RulesQueryResult = ReturnType; export const useFindCspRules = ({ search, page, perPage, filter }: RulesQuery) => { const { savedObjects } = useKibana().services; + return useQuery([CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, { search, page, perPage }], () => - savedObjects.client.find({ - type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - search: search ? `"${search}"*` : '', - searchFields: ['metadata.name.text'], - page: 1, - sortField: 'metadata.name', - perPage, - filter, - }) + savedObjects.client + .get(PACKAGE_POLICY_SAVED_OBJECT_TYPE, filter) + .then((res) => { + const benchmarkId = getBenchmarkInputType(res.attributes.inputs); + + return savedObjects.client.find({ + type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, + search: search ? `"${search}"*` : '', + searchFields: ['metadata.name.text'], + page: 1, + sortField: 'metadata.name', + perPage, + filter: getBenchmarkTypeFilter(benchmarkId), + }); + }) ); }; diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts index 88495704bccd9..3d8b3fe5d49a6 100644 --- a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts @@ -334,8 +334,8 @@ describe('Cloud Security Posture Plugin', () => { for (const cb of packagePolicyPostDeleteCallbacks) { await cb(deletedPackagePolicyMock); } - expect(repositoryFindMock).toHaveBeenCalledTimes(2); - expect(spy).toHaveBeenCalledTimes(1); + expect(repositoryFindMock).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(0); }); }); }); From ed194fff1ab9f883290781e3b1a694c31ae205cc Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Wed, 7 Dec 2022 19:15:59 +0200 Subject: [PATCH 06/23] After the first self review --- .../cloud_security_posture/common/types.ts | 1 - .../common/utils/helpers.ts | 4 ++-- .../public/pages/rules/rules_container.tsx | 17 ++++++++++------- .../public/pages/rules/use_csp_rules.ts | 7 +++++-- .../fleet_integration/fleet_integration.ts | 14 ++++++++------ .../server/plugin.test.ts | 2 +- .../cloud_security_posture/server/plugin.ts | 2 +- 7 files changed, 27 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index ab60d51ea28e5..b1b30ffc5297a 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -95,7 +95,6 @@ export type AgentPolicyStatus = Pick & { agents: num export interface Benchmark { package_policy: PackagePolicy; agent_policy: AgentPolicyStatus; - benchmark_id: BenchmarkId; number_of_rules: number; } diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 7385839687092..586374a8832fb 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -6,7 +6,7 @@ */ import { Truthy } from 'lodash'; -import { PackagePolicyInput } from '@kbn/fleet-plugin/common'; +import { NewPackagePolicyInput, PackagePolicyInput } from '@kbn/fleet-plugin/common'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, CSP_RULE_SAVED_OBJECT_TYPE, @@ -44,7 +44,7 @@ export const createCspRuleSearchFilterByPackagePolicy = ({ export const getBenchmarkTypeFilter = (type: BenchmarkId): string => `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`; -export const isEnabledBenchmarkInputType = (input: PackagePolicyInput) => +export const isEnabledBenchmarkInputType = (input: PackagePolicyInput | NewPackagePolicyInput) => !!input.type && input.enabled; export const isCspPackage = (packageName?: string) => diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx index 080c0f7055141..1f0d4ae84be9e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx @@ -68,18 +68,21 @@ export const RulesContainer = () => { const [selectedRuleId, setSelectedRuleId] = useState(null); const { pageSize, setPageSize } = usePageSize(LOCAL_STORAGE_PAGE_SIZE_RULES_KEY); const [rulesQuery, setRulesQuery] = useState({ - filter: params.packagePolicyId, + filter: '', search: '', page: 0, perPage: pageSize || 10, }); - const { data, status, error } = useFindCspRules({ - filter: rulesQuery.filter, - search: rulesQuery.search, - page: 1, - perPage: MAX_ITEMS_PER_PAGE, - }); + const { data, status, error } = useFindCspRules( + { + filter: rulesQuery.filter, + search: rulesQuery.search, + page: 1, + perPage: MAX_ITEMS_PER_PAGE, + }, + params.packagePolicyId + ); const rulesPageData = useMemo( () => getRulesPageData({ data, error, status }, rulesQuery), diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts index cf03d2d67e5ef..3f7e6a3ae8e2c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts @@ -24,12 +24,15 @@ export type RulesQuery = Required< >; export type RulesQueryResult = ReturnType; -export const useFindCspRules = ({ search, page, perPage, filter }: RulesQuery) => { +export const useFindCspRules = ( + { search, page, perPage, filter }: RulesQuery, + packagePolicyId: string +) => { const { savedObjects } = useKibana().services; return useQuery([CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, { search, page, perPage }], () => savedObjects.client - .get(PACKAGE_POLICY_SAVED_OBJECT_TYPE, filter) + .get(PACKAGE_POLICY_SAVED_OBJECT_TYPE, packagePolicyId) .then((res) => { const benchmarkId = getBenchmarkInputType(res.attributes.inputs); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index 9ff70ab709965..f87a079cd696c 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -5,11 +5,11 @@ * 2.0. */ import type { ISavedObjectsRepository, Logger, SavedObjectsFindResponse } from '@kbn/core/server'; -import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { NewPackagePolicy, PackagePolicy } from '@kbn/fleet-plugin/common'; import { BenchmarkId } from '../../common/types'; import { isEnabledBenchmarkInputType } from '../../common/utils/helpers'; import type { CspRule } from '../../common/schemas'; -import { CLOUDBEAT_VANILLA, CSP_RULE_SAVED_OBJECT_TYPE } from '../../common/constants'; +import { CLOUDBEAT_VANILLA, CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../common/constants'; export const isCspPackageInstalled = async ( soClient: ISavedObjectsRepository, @@ -19,19 +19,21 @@ export const isCspPackageInstalled = async ( try { const { saved_objects: postDeleteRules }: SavedObjectsFindResponse = await soClient.find({ - type: CSP_RULE_SAVED_OBJECT_TYPE, + type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, }); - if (!postDeleteRules.length) { + if (postDeleteRules.length > 0) { return true; } - return false; + return true; } catch (e) { logger.error(e); return false; } }; -export const getBenchmarkInputType = (inputs: PackagePolicy['inputs']): BenchmarkId => { +export const getBenchmarkInputType = ( + inputs: PackagePolicy['inputs'] | NewPackagePolicy['inputs'] +): BenchmarkId => { const enabledInputs = inputs.filter(isEnabledBenchmarkInputType); // Use the only enabled input diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts index 3d8b3fe5d49a6..8d3e323a75081 100644 --- a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts @@ -335,7 +335,7 @@ describe('Cloud Security Posture Plugin', () => { await cb(deletedPackagePolicyMock); } expect(repositoryFindMock).toHaveBeenCalledTimes(1); - expect(spy).toHaveBeenCalledTimes(0); + expect(spy).toHaveBeenCalledTimes(1); }); }); }); diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 8a24b6a4b174f..6e39cb50f8fe7 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -145,7 +145,7 @@ export class CspPlugin const soClient = core.savedObjects.createInternalRepository(); const isPackageExists = await isCspPackageInstalled(soClient, this.logger); - if (isPackageExists) { + if (!isPackageExists) { await this.uninstallResources(plugins.taskManager, this.logger); } } From ff75c8e6622be5bcc77f0d50f1300c651fd8a0e0 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Mon, 19 Dec 2022 12:18:01 +0200 Subject: [PATCH 07/23] Replacing isCspExist code by using fleet --- .../common/utils/helpers.ts | 17 +------------- .../fleet_integration/fleet_integration.ts | 22 +++++++++---------- .../cloud_security_posture/server/plugin.ts | 7 +++--- .../server/routes/benchmarks/benchmarks.ts | 1 - 4 files changed, 15 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 586374a8832fb..37b8c51108ae1 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -7,12 +7,7 @@ import { Truthy } from 'lodash'; import { NewPackagePolicyInput, PackagePolicyInput } from '@kbn/fleet-plugin/common'; -import { - CLOUD_SECURITY_POSTURE_PACKAGE_NAME, - CSP_RULE_SAVED_OBJECT_TYPE, - CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, -} from '../constants'; -import { BenchmarkId } from '../types'; +import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../constants'; /** * @example @@ -31,16 +26,6 @@ export const extractErrorMessage = (e: unknown, defaultMessage = 'Unknown Error' return defaultMessage; // TODO: i18n }; -export const createCspRuleSearchFilterByPackagePolicy = ({ - packagePolicyId, - policyId, -}: { - packagePolicyId: string; - policyId?: string; -}): string => - `${CSP_RULE_SAVED_OBJECT_TYPE}.attributes.package_policy_id: "${packagePolicyId}"${ - policyId ? ` AND ${CSP_RULE_SAVED_OBJECT_TYPE}.attributes.policy_id: "${policyId}"` : '' - }`; export const getBenchmarkTypeFilter = (type: BenchmarkId): string => `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`; diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index f87a079cd696c..7b8de6ec7a0dd 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -4,28 +4,26 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { ISavedObjectsRepository, Logger, SavedObjectsFindResponse } from '@kbn/core/server'; +import type { Logger } from '@kbn/core/server'; import { NewPackagePolicy, PackagePolicy } from '@kbn/fleet-plugin/common'; +import { PackageService } from '@kbn/fleet-plugin/server'; import { BenchmarkId } from '../../common/types'; import { isEnabledBenchmarkInputType } from '../../common/utils/helpers'; -import type { CspRule } from '../../common/schemas'; -import { CLOUDBEAT_VANILLA, CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../common/constants'; +import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, CLOUDBEAT_VANILLA } from '../../common/constants'; export const isCspPackageInstalled = async ( - soClient: ISavedObjectsRepository, + packageService: PackageService, logger: Logger ): Promise => { // TODO: check if CSP package installed via the Fleet API try { - const { saved_objects: postDeleteRules }: SavedObjectsFindResponse = - await soClient.find({ - type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - }); + const installation = await packageService.asInternalUser.getInstallation( + CLOUD_SECURITY_POSTURE_PACKAGE_NAME + ); - if (postDeleteRules.length > 0) { - return true; - } - return true; + if (installation) return true; + + return false; } catch (e) { logger.error(e); return false; diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 6e39cb50f8fe7..dc4295715efec 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -142,9 +142,10 @@ export class CspPlugin async (deletedPackagePolicies: DeepReadonly) => { for (const deletedPackagePolicy of deletedPackagePolicies) { if (isCspPackage(deletedPackagePolicy.package?.name)) { - const soClient = core.savedObjects.createInternalRepository(); - const isPackageExists = await isCspPackageInstalled(soClient, this.logger); - + const isPackageExists = await isCspPackageInstalled( + plugins.fleet.packageService, + this.logger + ); if (!isPackageExists) { await this.uninstallResources(plugins.taskManager, this.logger); } diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index 1e05ab272dce1..26190b56d35f5 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -72,7 +72,6 @@ const createBenchmarks = ( package_policy: cspPackage, agent_policy: agentPolicyStatus, number_of_rules: rulesCount, - benchmark_id: benchmarkId, }; }); From d2bc4bfa3bdec09ed2b0961dfdf94ce596c401b9 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Mon, 19 Dec 2022 20:11:17 +0200 Subject: [PATCH 08/23] Working version --- .../common/utils/helpers.ts | 6 ++++- .../fleet_integration/fleet_integration.ts | 24 +++++++++++-------- .../cloud_security_posture/server/plugin.ts | 4 +++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 37b8c51108ae1..9adb80764b2e1 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -7,7 +7,11 @@ import { Truthy } from 'lodash'; import { NewPackagePolicyInput, PackagePolicyInput } from '@kbn/fleet-plugin/common'; -import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../constants'; +import { + CLOUD_SECURITY_POSTURE_PACKAGE_NAME, + CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, +} from '../constants'; +import { BenchmarkId } from '../types'; /** * @example diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index 7b8de6ec7a0dd..a360c8c305e70 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -5,25 +5,29 @@ * 2.0. */ import type { Logger } from '@kbn/core/server'; -import { NewPackagePolicy, PackagePolicy } from '@kbn/fleet-plugin/common'; -import { PackageService } from '@kbn/fleet-plugin/server'; +import { + NewPackagePolicy, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, + PackagePolicy, +} from '@kbn/fleet-plugin/common'; +import { PackagePolicyClient } from '@kbn/fleet-plugin/server'; +import { SavedObjectsClientContract } from '@kbn/core/server'; import { BenchmarkId } from '../../common/types'; import { isEnabledBenchmarkInputType } from '../../common/utils/helpers'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, CLOUDBEAT_VANILLA } from '../../common/constants'; export const isCspPackageInstalled = async ( - packageService: PackageService, + packagePolicyClient: PackagePolicyClient, + soClient: SavedObjectsClientContract, logger: Logger ): Promise => { - // TODO: check if CSP package installed via the Fleet API try { - const installation = await packageService.asInternalUser.getInstallation( - CLOUD_SECURITY_POSTURE_PACKAGE_NAME - ); + const { total, _ } = await packagePolicyClient.list(soClient, { + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${CLOUD_SECURITY_POSTURE_PACKAGE_NAME}`, + page: 1, + }); - if (installation) return true; - - return false; + return total > 0; } catch (e) { logger.error(e); return false; diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index dc4295715efec..547d46110427d 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -142,8 +142,10 @@ export class CspPlugin async (deletedPackagePolicies: DeepReadonly) => { for (const deletedPackagePolicy of deletedPackagePolicies) { if (isCspPackage(deletedPackagePolicy.package?.name)) { + const soClient = core.savedObjects.createInternalRepository(); const isPackageExists = await isCspPackageInstalled( - plugins.fleet.packageService, + plugins.fleet.packagePolicyService, + soClient, this.logger ); if (!isPackageExists) { From 122cd8aedfcf71666baf4aa23972e28c55c0860e Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Mon, 19 Dec 2022 20:44:33 +0200 Subject: [PATCH 09/23] Fixing tests --- .../server/plugin.test.ts | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts index 8d3e323a75081..e68713fa4ac28 100644 --- a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts @@ -22,6 +22,7 @@ import { CspServerPluginStartDeps } from './types'; import { createFleetAuthzMock, Installation, + ListResult, PackagePolicy, UpdatePackagePolicy, } from '@kbn/fleet-plugin/common'; @@ -274,13 +275,19 @@ describe('Cloud Security Posture Plugin', () => { ); expect(updatedPackagePolicy).toEqual(packageMock); } + expect(fleetMock.packagePolicyService.update).toHaveBeenCalledTimes(0); }); it('should uninstall resources when package is removed', async () => { - fleetMock.packageService.asInternalUser.getInstallation.mockImplementationOnce( - async (): Promise => { - return; + fleetMock.packagePolicyService.list.mockImplementationOnce( + async (): Promise> => { + return { + items: [], + total: 0, + page: 1, + perPage: 1, + }; } ); @@ -295,29 +302,48 @@ describe('Cloud Security Posture Plugin', () => { }); const coreStart = coreMock.createStart(); - const repositoryFindMock = coreStart.savedObjects.createInternalRepository() - .find as jest.Mock; - - repositoryFindMock.mockReturnValueOnce( - Promise.resolve({ - saved_objects: [ - { - type: 'csp-rule-template', - id: 'csp_rule_template-41308bcdaaf665761478bb6f0d745a5c', - benchmark: { - id: 'cis_k8s', - }, - }, - ], - }) - ); + const context = coreMock.createPluginInitializerContext(); + plugin = new CspPlugin(context); + const spy = jest.spyOn(plugin, 'uninstallResources').mockImplementation(); + + // Act + await plugin.start(coreStart, mockPlugins); + await mockPlugins.fleet.fleetSetupCompleted(); + + // Assert + expect(fleetMock.packageService.asInternalUser.getInstallation).toHaveBeenCalledTimes(1); + + expect(packagePolicyPostDeleteCallbacks.length).toBeGreaterThan(0); - repositoryFindMock.mockReturnValueOnce( - Promise.resolve({ - saved_objects: [], - }) + for (const cb of packagePolicyPostDeleteCallbacks) { + await cb(deletedPackagePolicyMock); + } + expect(fleetMock.packagePolicyService.list).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(1); + }); + it('should not uninstall resources when another package exists', async () => { + fleetMock.packagePolicyService.list.mockImplementationOnce( + async (): Promise> => { + return { + items: [createPackagePolicyMock()], + total: 1, + page: 1, + perPage: 1, + }; + } ); + const deletedPackagePolicyMock = deletePackagePolicyMock(); + deletedPackagePolicyMock[0].package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; + + const packagePolicyPostDeleteCallbacks: PostPackagePolicyDeleteCallback[] = []; + fleetMock.registerExternalCallback.mockImplementation((...args) => { + if (args[0] === 'postPackagePolicyDelete') { + packagePolicyPostDeleteCallbacks.push(args[1]); + } + }); + + const coreStart = coreMock.createStart(); const context = coreMock.createPluginInitializerContext(); plugin = new CspPlugin(context); const spy = jest.spyOn(plugin, 'uninstallResources').mockImplementation(); @@ -334,8 +360,8 @@ describe('Cloud Security Posture Plugin', () => { for (const cb of packagePolicyPostDeleteCallbacks) { await cb(deletedPackagePolicyMock); } - expect(repositoryFindMock).toHaveBeenCalledTimes(1); - expect(spy).toHaveBeenCalledTimes(1); + expect(fleetMock.packagePolicyService.list).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(0); }); }); }); From 997d53c8d7d3110c854f0a0f5425538137f3aa51 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 20 Dec 2022 11:12:39 +0200 Subject: [PATCH 10/23] Fixing tests --- .../server/plugin.test.ts | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts index e68713fa4ac28..d28b96c70baa7 100644 --- a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts @@ -82,26 +82,6 @@ describe('Cloud Security Posture Plugin', () => { }; const contextMock = coreMock.createCustomRequestHandlerContext(mockRouteContext); - const findMock = mockRouteContext.core.savedObjects.client.find as jest.Mock; - findMock.mockReturnValue( - Promise.resolve({ - saved_objects: [ - { - type: 'csp_rule', - attributes: { - enabled: false, - metadata: { - rego_rule_id: 'cis_1_1_1', - benchmark: { id: 'cis_k8s' }, - }, - }, - }, - ], - total: 1, - per_page: 10, - page: 1, - }) - ); let plugin: CspPlugin; From e6e42be71e39e6a8ea708ca3f14130c8b0a7fe73 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 20 Dec 2022 13:22:10 +0200 Subject: [PATCH 11/23] Updating test with test cases --- .../server/plugin.test.ts | 115 ++++++------------ 1 file changed, 40 insertions(+), 75 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts index d28b96c70baa7..2b72d1e1cef10 100644 --- a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts @@ -259,89 +259,54 @@ describe('Cloud Security Posture Plugin', () => { expect(fleetMock.packagePolicyService.update).toHaveBeenCalledTimes(0); }); - it('should uninstall resources when package is removed', async () => { - fleetMock.packagePolicyService.list.mockImplementationOnce( - async (): Promise> => { - return { - items: [], - total: 0, - page: 1, - perPage: 1, - }; - } - ); + it.each` + total | items | expectedNumberOfCallsToUninstallResources + ${1} | ${[createPackagePolicyMock()]} | ${0} + ${0} | ${[]} | ${1} + `( + 'should uninstall resources when package is removed', + async ({ total, items, expectedNumberOfCallsToUninstallResources }) => { + fleetMock.packagePolicyService.list.mockImplementationOnce( + async (): Promise> => { + return { + items, + total, + page: 1, + perPage: 1, + }; + } + ); - const deletedPackagePolicyMock = deletePackagePolicyMock(); - deletedPackagePolicyMock[0].package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; + const deletedPackagePolicyMock = deletePackagePolicyMock(); + deletedPackagePolicyMock[0].package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; - const packagePolicyPostDeleteCallbacks: PostPackagePolicyDeleteCallback[] = []; - fleetMock.registerExternalCallback.mockImplementation((...args) => { - if (args[0] === 'postPackagePolicyDelete') { - packagePolicyPostDeleteCallbacks.push(args[1]); - } - }); + const packagePolicyPostDeleteCallbacks: PostPackagePolicyDeleteCallback[] = []; + fleetMock.registerExternalCallback.mockImplementation((...args) => { + if (args[0] === 'postPackagePolicyDelete') { + packagePolicyPostDeleteCallbacks.push(args[1]); + } + }); - const coreStart = coreMock.createStart(); - const context = coreMock.createPluginInitializerContext(); - plugin = new CspPlugin(context); - const spy = jest.spyOn(plugin, 'uninstallResources').mockImplementation(); + const coreStart = coreMock.createStart(); + const context = coreMock.createPluginInitializerContext(); + plugin = new CspPlugin(context); + const spy = jest.spyOn(plugin, 'uninstallResources').mockImplementation(); - // Act - await plugin.start(coreStart, mockPlugins); - await mockPlugins.fleet.fleetSetupCompleted(); - - // Assert - expect(fleetMock.packageService.asInternalUser.getInstallation).toHaveBeenCalledTimes(1); + // Act + await plugin.start(coreStart, mockPlugins); + await mockPlugins.fleet.fleetSetupCompleted(); - expect(packagePolicyPostDeleteCallbacks.length).toBeGreaterThan(0); - - for (const cb of packagePolicyPostDeleteCallbacks) { - await cb(deletedPackagePolicyMock); - } - expect(fleetMock.packagePolicyService.list).toHaveBeenCalledTimes(1); - expect(spy).toHaveBeenCalledTimes(1); - }); - it('should not uninstall resources when another package exists', async () => { - fleetMock.packagePolicyService.list.mockImplementationOnce( - async (): Promise> => { - return { - items: [createPackagePolicyMock()], - total: 1, - page: 1, - perPage: 1, - }; - } - ); + // Assert + expect(fleetMock.packageService.asInternalUser.getInstallation).toHaveBeenCalledTimes(1); - const deletedPackagePolicyMock = deletePackagePolicyMock(); - deletedPackagePolicyMock[0].package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; + expect(packagePolicyPostDeleteCallbacks.length).toBeGreaterThan(0); - const packagePolicyPostDeleteCallbacks: PostPackagePolicyDeleteCallback[] = []; - fleetMock.registerExternalCallback.mockImplementation((...args) => { - if (args[0] === 'postPackagePolicyDelete') { - packagePolicyPostDeleteCallbacks.push(args[1]); + for (const cb of packagePolicyPostDeleteCallbacks) { + await cb(deletedPackagePolicyMock); } - }); - - const coreStart = coreMock.createStart(); - const context = coreMock.createPluginInitializerContext(); - plugin = new CspPlugin(context); - const spy = jest.spyOn(plugin, 'uninstallResources').mockImplementation(); - - // Act - await plugin.start(coreStart, mockPlugins); - await mockPlugins.fleet.fleetSetupCompleted(); - - // Assert - expect(fleetMock.packageService.asInternalUser.getInstallation).toHaveBeenCalledTimes(1); - - expect(packagePolicyPostDeleteCallbacks.length).toBeGreaterThan(0); - - for (const cb of packagePolicyPostDeleteCallbacks) { - await cb(deletedPackagePolicyMock); + expect(fleetMock.packagePolicyService.list).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(expectedNumberOfCallsToUninstallResources); } - expect(fleetMock.packagePolicyService.list).toHaveBeenCalledTimes(1); - expect(spy).toHaveBeenCalledTimes(0); - }); + ); }); }); From cc53b2d24a2504276c905b0735ae80aee8a21038 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 20 Dec 2022 14:33:43 +0200 Subject: [PATCH 12/23] Fixing type checks --- .../public/pages/rules/rules_container.test.tsx | 6 ------ .../public/test/fixtures/csp_benchmark_integration.ts | 4 +--- .../server/fleet_integration/fleet_integration.ts | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx index 6d2e2a44e799d..f4d31591e0b27 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx @@ -52,14 +52,10 @@ const getWrapper = }; const getRuleMock = ({ - packagePolicyId = chance.guid(), - policyId = chance.guid(), savedObjectId = chance.guid(), id = chance.guid(), enabled, }: { - packagePolicyId?: string; - policyId?: string; savedObjectId?: string; id?: string; enabled: boolean; @@ -88,8 +84,6 @@ const getRuleMock = ({ tags: [chance.word(), chance.word()], version: chance.sentence(), }, - package_policy_id: packagePolicyId, - policy_id: policyId, enabled, muted: false, }, diff --git a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts index 8d7105377627f..d4b639eab4b89 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts @@ -55,11 +55,9 @@ export const createCspBenchmarkIntegrationFixture = ({ name: chance.sentence(), agents: chance.integer({ min: 0 }), }, - number_of_rules, - benchmark_id, + number_of_rules = chance.integer({ min: 0, max: 10 }), }: CreateCspBenchmarkIntegrationFixtureInput = {}): Benchmark => ({ package_policy, agent_policy, number_of_rules, - benchmark_id, }); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index a360c8c305e70..4b7c7a2ae26b7 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -22,7 +22,7 @@ export const isCspPackageInstalled = async ( logger: Logger ): Promise => { try { - const { total, _ } = await packagePolicyClient.list(soClient, { + const { total } = await packagePolicyClient.list(soClient, { kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${CLOUD_SECURITY_POSTURE_PACKAGE_NAME}`, page: 1, }); From a39499258d195f6a9308cc00fa509720d47814ac Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 20 Dec 2022 15:44:41 +0200 Subject: [PATCH 13/23] Adding tests + refactoring --- .../cloud_security_posture/common/types.ts | 2 +- .../common/utils/helpers.test.ts | 66 +++++++++++++++ .../common/utils/helpers.ts | 29 ++++++- .../public/pages/rules/use_csp_rules.ts | 10 ++- .../fleet_integration.test.ts | 82 ++++++++----------- .../fleet_integration/fleet_integration.ts | 31 +------ .../cloud_security_posture/server/plugin.ts | 4 +- .../server/routes/benchmarks/benchmarks.ts | 11 ++- 8 files changed, 146 insertions(+), 89 deletions(-) create mode 100644 x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index b1b30ffc5297a..6e23483c0679a 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -6,7 +6,7 @@ */ import type { PackagePolicy, AgentPolicy } from '@kbn/fleet-plugin/common'; -import type { CspRuleMetadata } from './schemas/csp_rule_metadata'; +import { CspRuleMetadata } from './schemas'; export type Evaluation = 'passed' | 'failed' | 'NA'; /** number between 1-100 */ diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts new file mode 100644 index 0000000000000..66e26a927a2ee --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; +import { + extractBenchmarkFromPackagePolicy, + getBenchmarkTypeFilterFromBenchmarkId, +} from './helpers'; + +describe('create CSP rules with post package create callback', () => { + it('get default integration type from inputs with multiple enabled types', () => { + const mockPackagePolicy = createPackagePolicyMock(); + + // Both enabled falls back to default + mockPackagePolicy.inputs = [ + { type: 'cloudbeat/cis_k8s', enabled: true, streams: [] }, + { type: 'cloudbeat/cis_eks', enabled: true, streams: [] }, + ]; + const type = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + expect(type).toMatch('cis_k8s'); + }); + + it('get default integration type from inputs without any enabled types', () => { + const mockPackagePolicy = createPackagePolicyMock(); + + // None enabled falls back to default + mockPackagePolicy.inputs = [ + { type: 'cloudbeat/cis_k8s', enabled: false, streams: [] }, + { type: 'cloudbeat/cis_eks', enabled: false, streams: [] }, + ]; + const type = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + expect(type).toMatch('cis_k8s'); + }); + + it('get EKS integration type', () => { + const mockPackagePolicy = createPackagePolicyMock(); + + // Single EKS selected + mockPackagePolicy.inputs = [ + { type: 'cloudbeat/cis_eks', enabled: true, streams: [] }, + { type: 'cloudbeat/cis_k8s', enabled: false, streams: [] }, + ]; + const typeEks = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + expect(typeEks).toMatch('cis_eks'); + }); + + it('get Vanilla K8S integration type', () => { + const mockPackagePolicy = createPackagePolicyMock(); + + // Single k8s selected + mockPackagePolicy.inputs = [ + { type: 'cloudbeat/cis_eks', enabled: false, streams: [] }, + { type: 'cloudbeat/cis_k8s', enabled: true, streams: [] }, + ]; + const typeK8s = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + expect(typeK8s).toMatch('cis_k8s'); + }); + it('get benchmark type filter based on a benchmark id', () => { + const typeFilter = getBenchmarkTypeFilterFromBenchmarkId('cis_eks'); + expect(typeFilter).toMatch('csp-rule-template.attributes.metadata.benchmark.id: "cis_eks"'); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 9adb80764b2e1..2625925d853c0 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -6,9 +6,15 @@ */ import { Truthy } from 'lodash'; -import { NewPackagePolicyInput, PackagePolicyInput } from '@kbn/fleet-plugin/common'; +import { + NewPackagePolicy, + NewPackagePolicyInput, + PackagePolicy, + PackagePolicyInput, +} from '@kbn/fleet-plugin/common'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, + CLOUDBEAT_VANILLA, CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, } from '../constants'; import { BenchmarkId } from '../types'; @@ -30,7 +36,7 @@ export const extractErrorMessage = (e: unknown, defaultMessage = 'Unknown Error' return defaultMessage; // TODO: i18n }; -export const getBenchmarkTypeFilter = (type: BenchmarkId): string => +export const getBenchmarkTypeFilterFromBenchmarkId = (type: BenchmarkId): string => `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`; export const isEnabledBenchmarkInputType = (input: PackagePolicyInput | NewPackagePolicyInput) => @@ -38,3 +44,22 @@ export const isEnabledBenchmarkInputType = (input: PackagePolicyInput | NewPacka export const isCspPackage = (packageName?: string) => packageName === CLOUD_SECURITY_POSTURE_PACKAGE_NAME; + +export const extractBenchmarkFromPackagePolicy = ( + inputs: PackagePolicy['inputs'] | NewPackagePolicy['inputs'] +): BenchmarkId => { + const enabledInputs = inputs.filter(isEnabledBenchmarkInputType); + + // Use the only enabled input + if (enabledInputs.length === 1) { + return getInputType(enabledInputs[0].type); + } + + // Use the default benchmark id for multiple/none selected + return getInputType(CLOUDBEAT_VANILLA); +}; + +const getInputType = (inputType: string): string => { + // Get the last part of the input type, input type structure: cloudbeat/ + return inputType.split('/')[1]; +}; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts index 3f7e6a3ae8e2c..01e9b2525a000 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts @@ -8,8 +8,10 @@ import { useQuery } from '@tanstack/react-query'; import { FunctionKeys } from 'utility-types'; import type { SavedObjectsFindOptions, SimpleSavedObject } from '@kbn/core/public'; import { NewPackagePolicy, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; -import { getBenchmarkTypeFilter } from '../../../common/utils/helpers'; -import { getBenchmarkInputType } from '../../../server/fleet_integration/fleet_integration'; +import { + extractBenchmarkFromPackagePolicy, + getBenchmarkTypeFilterFromBenchmarkId, +} from '../../../common/utils/helpers'; import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { CspRuleTemplate } from '../../../common/schemas'; import { useKibana } from '../../common/hooks/use_kibana'; @@ -34,7 +36,7 @@ export const useFindCspRules = ( savedObjects.client .get(PACKAGE_POLICY_SAVED_OBJECT_TYPE, packagePolicyId) .then((res) => { - const benchmarkId = getBenchmarkInputType(res.attributes.inputs); + const benchmarkId = extractBenchmarkFromPackagePolicy(res.attributes.inputs); return savedObjects.client.find({ type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, @@ -43,7 +45,7 @@ export const useFindCspRules = ( page: 1, sortField: 'metadata.name', perPage, - filter: getBenchmarkTypeFilter(benchmarkId), + filter: getBenchmarkTypeFilterFromBenchmarkId(benchmarkId), }); }) ); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts index d779b8083af6d..c9a02e6a49e45 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts @@ -5,55 +5,39 @@ * 2.0. */ +import { createPackagePolicyServiceMock } from '@kbn/fleet-plugin/server/mocks'; +import { ListResult, PackagePolicy } from '@kbn/fleet-plugin/common'; +import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; +import { isCspPackagePolicyInstalled } from './fleet_integration'; +import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; -import { getBenchmarkInputType } from './fleet_integration'; -describe('create CSP rules with post package create callback', () => { - it('get default integration type from inputs with multiple enabled types', () => { - const mockPackagePolicy = createPackagePolicyMock(); - - // Both enabled falls back to default - mockPackagePolicy.inputs = [ - { type: 'cloudbeat/cis_k8s', enabled: true, streams: [] }, - { type: 'cloudbeat/cis_eks', enabled: true, streams: [] }, - ]; - const type = getBenchmarkInputType(mockPackagePolicy.inputs); - expect(type).toMatch('cis_k8s'); - }); - - it('get default integration type from inputs without any enabled types', () => { - const mockPackagePolicy = createPackagePolicyMock(); - - // None enabled falls back to default - mockPackagePolicy.inputs = [ - { type: 'cloudbeat/cis_k8s', enabled: false, streams: [] }, - { type: 'cloudbeat/cis_eks', enabled: false, streams: [] }, - ]; - const type = getBenchmarkInputType(mockPackagePolicy.inputs); - expect(type).toMatch('cis_k8s'); - }); - - it('get EKS integration type', () => { - const mockPackagePolicy = createPackagePolicyMock(); - - // Single EKS selected - mockPackagePolicy.inputs = [ - { type: 'cloudbeat/cis_eks', enabled: true, streams: [] }, - { type: 'cloudbeat/cis_k8s', enabled: false, streams: [] }, - ]; - const typeEks = getBenchmarkInputType(mockPackagePolicy.inputs); - expect(typeEks).toMatch('cis_eks'); - }); - - it('get Vanilla K8S integration type', () => { - const mockPackagePolicy = createPackagePolicyMock(); - - // Single k8s selected - mockPackagePolicy.inputs = [ - { type: 'cloudbeat/cis_eks', enabled: false, streams: [] }, - { type: 'cloudbeat/cis_k8s', enabled: true, streams: [] }, - ]; - const typeK8s = getBenchmarkInputType(mockPackagePolicy.inputs); - expect(typeK8s).toMatch('cis_k8s'); - }); +describe('is Csp package installed tests', () => { + const logger = loggingSystemMock.createLogger(); + const soClient = savedObjectsClientMock.create(); + const packagePolicyService = createPackagePolicyServiceMock(); + + beforeEach(() => jest.clearAllMocks()); + it.each` + total | items | expectedCspPolicyResponse + ${1} | ${[createPackagePolicyMock()]} | ${true} + ${0} | ${[]} | ${false} + `( + 'isCspPackagePolicyInstalled should return true when other packages exist', + async ({ total, items, expectedCspPolicyResponse }) => { + packagePolicyService.list.mockImplementationOnce( + async (): Promise> => { + return { + items, + total, + page: 1, + perPage: 1, + }; + } + ); + + const isInstalled = await isCspPackagePolicyInstalled(packagePolicyService, soClient, logger); + expect(isInstalled).toEqual(expectedCspPolicyResponse); + } + ); }); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index 4b7c7a2ae26b7..de8db31f25909 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -5,18 +5,12 @@ * 2.0. */ import type { Logger } from '@kbn/core/server'; -import { - NewPackagePolicy, - PACKAGE_POLICY_SAVED_OBJECT_TYPE, - PackagePolicy, -} from '@kbn/fleet-plugin/common'; -import { PackagePolicyClient } from '@kbn/fleet-plugin/server'; import { SavedObjectsClientContract } from '@kbn/core/server'; -import { BenchmarkId } from '../../common/types'; -import { isEnabledBenchmarkInputType } from '../../common/utils/helpers'; -import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, CLOUDBEAT_VANILLA } from '../../common/constants'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; +import { PackagePolicyClient } from '@kbn/fleet-plugin/server'; +import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../common/constants'; -export const isCspPackageInstalled = async ( +export const isCspPackagePolicyInstalled = async ( packagePolicyClient: PackagePolicyClient, soClient: SavedObjectsClientContract, logger: Logger @@ -33,20 +27,3 @@ export const isCspPackageInstalled = async ( return false; } }; -export const getBenchmarkInputType = ( - inputs: PackagePolicy['inputs'] | NewPackagePolicy['inputs'] -): BenchmarkId => { - const enabledInputs = inputs.filter(isEnabledBenchmarkInputType); - - // Use the only enabled input - if (enabledInputs.length === 1) { - return getInputType(enabledInputs[0].type); - } - - // Use the default benchmark id for multiple/none selected - return getInputType(CLOUDBEAT_VANILLA); -}; -const getInputType = (inputType: string): string => { - // Get the last part of the input type, input type structure: cloudbeat/ - return inputType.split('/')[1]; -}; diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 547d46110427d..697ccdb483fda 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -37,7 +37,7 @@ import { setupRoutes } from './routes/setup_routes'; import { setupSavedObjects } from './saved_objects'; import { initializeCspIndices } from './create_indices/create_indices'; import { initializeCspTransforms } from './create_transforms/create_transforms'; -import { isCspPackageInstalled } from './fleet_integration/fleet_integration'; +import { isCspPackagePolicyInstalled } from './fleet_integration/fleet_integration'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../common/constants'; import { removeFindingsStatsTask, @@ -143,7 +143,7 @@ export class CspPlugin for (const deletedPackagePolicy of deletedPackagePolicies) { if (isCspPackage(deletedPackagePolicy.package?.name)) { const soClient = core.savedObjects.createInternalRepository(); - const isPackageExists = await isCspPackageInstalled( + const isPackageExists = await isCspPackagePolicyInstalled( plugins.fleet.packagePolicyService, soClient, this.logger diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index 26190b56d35f5..1b2c3cb97c79b 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -7,7 +7,6 @@ import type { SavedObjectsClientContract } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { AgentPolicy, PackagePolicy } from '@kbn/fleet-plugin/common'; -import { getBenchmarkInputType } from '../../fleet_integration/fleet_integration'; import { CspRuleTemplate } from '../../../common/schemas'; import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { @@ -16,7 +15,11 @@ import { } from '../../../common/constants'; import { benchmarksQueryParamsSchema } from '../../../common/schemas/benchmark'; import type { Benchmark } from '../../../common/types'; -import { getBenchmarkTypeFilter, isNonNullable } from '../../../common/utils/helpers'; +import { + extractBenchmarkFromPackagePolicy, + getBenchmarkTypeFilterFromBenchmarkId, + isNonNullable, +} from '../../../common/utils/helpers'; import { CspRouter } from '../../types'; import { getAgentStatusesByAgentPolicies, @@ -34,7 +37,7 @@ export const getRulesCountForPolicy = async ( ): Promise => { const rules = await soClient.find({ type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - filter: getBenchmarkTypeFilter(benchmarkName), + filter: getBenchmarkTypeFilterFromBenchmarkId(benchmarkName), perPage: 0, }); @@ -61,7 +64,7 @@ const createBenchmarks = ( .filter(isNonNullable) ?? []; const benchmarks = cspPackagesOnAgent.map(async (cspPackage) => { - const benchmarkId = getBenchmarkInputType(cspPackage.inputs); + const benchmarkId = extractBenchmarkFromPackagePolicy(cspPackage.inputs); const rulesCount = await getRulesCountForPolicy(soClient, benchmarkId); const agentPolicyStatus = { id: agentPolicy.id, From a558f940d8104a7816d5508f8c2f4ea4fdb6394f Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 20 Dec 2022 18:07:59 +0200 Subject: [PATCH 14/23] adding tests + refactoring --- .../cloud_security_posture/common/utils/helpers.test.ts | 2 +- .../public/pages/rules/rules_container.test.tsx | 5 ++--- x-pack/plugins/cloud_security_posture/server/plugin.ts | 3 ++- .../server/routes/benchmarks/benchmarks.test.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts index 66e26a927a2ee..9541757aaf397 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts @@ -11,7 +11,7 @@ import { getBenchmarkTypeFilterFromBenchmarkId, } from './helpers'; -describe('create CSP rules with post package create callback', () => { +describe('test helper methods', () => { it('get default integration type from inputs with multiple enabled types', () => { const mockPackagePolicy = createPackagePolicyMock(); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx index f4d31591e0b27..17f8b631a9213 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx @@ -54,7 +54,6 @@ const getWrapper = const getRuleMock = ({ savedObjectId = chance.guid(), id = chance.guid(), - enabled, }: { savedObjectId?: string; id?: string; @@ -69,6 +68,7 @@ const getRuleMock = ({ benchmark: { name: chance.word(), version: chance.sentence(), + id: chance.word(), }, default_value: chance.sentence(), description: chance.sentence(), @@ -84,13 +84,11 @@ const getRuleMock = ({ tags: [chance.word(), chance.word()], version: chance.sentence(), }, - enabled, muted: false, }, } as RuleSavedObject); const params = { - policyId: chance.guid(), packagePolicyId: chance.guid(), }; @@ -112,6 +110,7 @@ describe('', () => { total: 1, savedObjects: [rule1], }, + policyId: params.packagePolicyId, }); render( diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 697ccdb483fda..202bee7527f6e 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -143,8 +143,9 @@ export class CspPlugin for (const deletedPackagePolicy of deletedPackagePolicies) { if (isCspPackage(deletedPackagePolicy.package?.name)) { const soClient = core.savedObjects.createInternalRepository(); + const packagePolicyService = plugins.fleet.packagePolicyService; const isPackageExists = await isCspPackagePolicyInstalled( - plugins.fleet.packagePolicyService, + packagePolicyService, soClient, this.logger ); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index b1506b16f9eb5..4a7f8fe733837 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -259,7 +259,7 @@ describe('benchmarks API', () => { }); describe('test addPackagePolicyCspRules', () => { - it('should return the total number and filtered by the relevant benchmark', async () => { + it('should return filtered by the relevant benchmark and return the total number of csp rule template of this exact benchmark', async () => { const benchmark = 'cis_k8s'; mockSoClient.find.mockResolvedValueOnce({ aggregations: { enabled_status: { doc_count: 2 } }, From 8890b161aeb0bd96a6e31097f2137e47b02938bd Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Tue, 20 Dec 2022 18:28:32 +0200 Subject: [PATCH 15/23] chaning the schema --- .../saved_objects/migrations/check_registered_types.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts index 983adcac14c91..f4963135d6f01 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts @@ -78,7 +78,7 @@ describe('checking migration metadata changes on all registered SO types', () => "config": "e3f0408976dbdd453641f5699927b28b188f6b8c", "connector_token": "fa5301aa5a2914795d3b1b82d0a49939444009da", "core-usage-stats": "f40a213da2c597b0de94e364a4326a5a1baa4ca9", - "csp-rule-template": "3679c5f2431da8153878db79c78a4e695357fb61", + "csp-rule-template": "d7e403244d466ee0daaf75e1616b9c5d5fd8c1cb", "csp_rule": "d2bb53ea5d2bdfba1a835ad8956dfcd2b2c32e19", "dashboard": "742f2d9f110709fd8599b14f7766f38efc30de61", "endpoint:user-artifact": "f94c250a52b30d0a2d32635f8b4c5bdabd1e25c0", From 9064bec4ed01e2af1b9cd18fcba5c9bc3f649d0c Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Wed, 21 Dec 2022 14:45:10 +0200 Subject: [PATCH 16/23] Updating csp_finding.ts to use csp_rule_template --- .../cloud_security_posture/common/schemas/csp_finding.ts | 4 ++-- .../server/routes/benchmarks/benchmarks.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts index af99c609832d6..4b78872f5d2a0 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts @@ -7,7 +7,7 @@ // TODO: this needs to be defined in a versioned schema import type { EcsEvent } from '@kbn/ecs'; -import type { CspRuleMetadata } from './csp_rule_metadata'; +import { CspRuleTemplate } from './csp_rule_template'; export interface CspFinding { '@timestamp': string; @@ -19,7 +19,7 @@ export interface CspFinding { }; result: CspFindingResult; resource: CspFindingResource; - rule: CspRuleMetadata; + rule: CspRuleTemplate; host: CspFindingHost; event: EcsEvent; agent: CspFindingAgent; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index 4a7f8fe733837..e4da81a088729 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -274,11 +274,11 @@ describe('benchmarks API', () => { ], } as unknown as SavedObjectsFindResponse); - const cspRulesStatus = await getRulesCountForPolicy(mockSoClient, benchmark); + const rulesCount = await getRulesCountForPolicy(mockSoClient, benchmark); const expectedFilter = `csp-rule-template.attributes.metadata.benchmark.id: "${benchmark}"`; expect(mockSoClient.find.mock.calls[0][0].filter).toEqual(expectedFilter); - expect(cspRulesStatus).toEqual(3); + expect(rulesCount).toEqual(3); }); }); }); From 7f589d3e3cd60df1bb42a7280f335abb7c47e11d Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Thu, 22 Dec 2022 13:10:58 +0200 Subject: [PATCH 17/23] Revert csp_finding.ts was pushed accidentally --- .../cloud_security_posture/common/schemas/csp_finding.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts index 4b78872f5d2a0..af99c609832d6 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts @@ -7,7 +7,7 @@ // TODO: this needs to be defined in a versioned schema import type { EcsEvent } from '@kbn/ecs'; -import { CspRuleTemplate } from './csp_rule_template'; +import type { CspRuleMetadata } from './csp_rule_metadata'; export interface CspFinding { '@timestamp': string; @@ -19,7 +19,7 @@ export interface CspFinding { }; result: CspFindingResult; resource: CspFindingResource; - rule: CspRuleTemplate; + rule: CspRuleMetadata; host: CspFindingHost; event: EcsEvent; agent: CspFindingAgent; From 005ba5b8fd338c2f53a3737f5bed6d0038037d24 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Mon, 26 Dec 2022 11:46:16 +0200 Subject: [PATCH 18/23] Code review comments fixes --- .../cloud_security_posture/common/types.ts | 2 +- .../common/utils/helpers.test.ts | 15 ++++++--------- .../common/utils/helpers.ts | 8 +++++--- .../public/pages/benchmarks/benchmarks_table.tsx | 2 +- .../public/pages/rules/use_csp_rules.ts | 8 ++++---- .../test/fixtures/csp_benchmark_integration.ts | 4 ++-- .../server/fleet_integration/fleet_integration.ts | 5 ++--- .../server/routes/benchmarks/benchmarks.test.ts | 2 +- .../server/routes/benchmarks/benchmarks.ts | 12 ++++++------ 9 files changed, 28 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index 6e23483c0679a..bc5a86434e402 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -95,7 +95,7 @@ export type AgentPolicyStatus = Pick & { agents: num export interface Benchmark { package_policy: PackagePolicy; agent_policy: AgentPolicyStatus; - number_of_rules: number; + rules_count: number; } export type BenchmarkId = CspRuleMetadata['benchmark']['id']; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts index 9541757aaf397..24298518aef05 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts @@ -6,10 +6,7 @@ */ import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; -import { - extractBenchmarkFromPackagePolicy, - getBenchmarkTypeFilterFromBenchmarkId, -} from './helpers'; +import { getBenchmarkFromPackagePolicy, getBenchmarkTypeFilter } from './helpers'; describe('test helper methods', () => { it('get default integration type from inputs with multiple enabled types', () => { @@ -20,7 +17,7 @@ describe('test helper methods', () => { { type: 'cloudbeat/cis_k8s', enabled: true, streams: [] }, { type: 'cloudbeat/cis_eks', enabled: true, streams: [] }, ]; - const type = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + const type = getBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); expect(type).toMatch('cis_k8s'); }); @@ -32,7 +29,7 @@ describe('test helper methods', () => { { type: 'cloudbeat/cis_k8s', enabled: false, streams: [] }, { type: 'cloudbeat/cis_eks', enabled: false, streams: [] }, ]; - const type = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + const type = getBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); expect(type).toMatch('cis_k8s'); }); @@ -44,7 +41,7 @@ describe('test helper methods', () => { { type: 'cloudbeat/cis_eks', enabled: true, streams: [] }, { type: 'cloudbeat/cis_k8s', enabled: false, streams: [] }, ]; - const typeEks = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + const typeEks = getBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); expect(typeEks).toMatch('cis_eks'); }); @@ -56,11 +53,11 @@ describe('test helper methods', () => { { type: 'cloudbeat/cis_eks', enabled: false, streams: [] }, { type: 'cloudbeat/cis_k8s', enabled: true, streams: [] }, ]; - const typeK8s = extractBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); + const typeK8s = getBenchmarkFromPackagePolicy(mockPackagePolicy.inputs); expect(typeK8s).toMatch('cis_k8s'); }); it('get benchmark type filter based on a benchmark id', () => { - const typeFilter = getBenchmarkTypeFilterFromBenchmarkId('cis_eks'); + const typeFilter = getBenchmarkTypeFilter('cis_eks'); expect(typeFilter).toMatch('csp-rule-template.attributes.metadata.benchmark.id: "cis_eks"'); }); }); diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 2625925d853c0..6b0acccca1add 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -9,6 +9,7 @@ import { Truthy } from 'lodash'; import { NewPackagePolicy, NewPackagePolicyInput, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, PackagePolicy, PackagePolicyInput, } from '@kbn/fleet-plugin/common'; @@ -36,16 +37,16 @@ export const extractErrorMessage = (e: unknown, defaultMessage = 'Unknown Error' return defaultMessage; // TODO: i18n }; -export const getBenchmarkTypeFilterFromBenchmarkId = (type: BenchmarkId): string => +export const getBenchmarkTypeFilter = (type: BenchmarkId): string => `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"`; export const isEnabledBenchmarkInputType = (input: PackagePolicyInput | NewPackagePolicyInput) => - !!input.type && input.enabled; + input.enabled; export const isCspPackage = (packageName?: string) => packageName === CLOUD_SECURITY_POSTURE_PACKAGE_NAME; -export const extractBenchmarkFromPackagePolicy = ( +export const getBenchmarkFromPackagePolicy = ( inputs: PackagePolicy['inputs'] | NewPackagePolicy['inputs'] ): BenchmarkId => { const enabledInputs = inputs.filter(isEnabledBenchmarkInputType); @@ -63,3 +64,4 @@ const getInputType = (inputType: string): string => { // Get the last part of the input type, input type structure: cloudbeat/ return inputType.split('/')[1]; }; +export const getCSPKuery = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${CLOUD_SECURITY_POSTURE_PACKAGE_NAME}`; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx index 8cbec56384084..ee4fed93d5789 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx @@ -82,7 +82,7 @@ const BENCHMARKS_TABLE_COLUMNS: Array> = [ 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.INTEGRATION_NAME, }, { - field: 'number_of_rules', + field: 'rules_count', name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.rulesColumnTitle', { defaultMessage: 'Rules', }), diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts index 01e9b2525a000..3e9f6594a7f4d 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts @@ -9,8 +9,8 @@ import { FunctionKeys } from 'utility-types'; import type { SavedObjectsFindOptions, SimpleSavedObject } from '@kbn/core/public'; import { NewPackagePolicy, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; import { - extractBenchmarkFromPackagePolicy, - getBenchmarkTypeFilterFromBenchmarkId, + getBenchmarkFromPackagePolicy, + getBenchmarkTypeFilter, } from '../../../common/utils/helpers'; import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { CspRuleTemplate } from '../../../common/schemas'; @@ -36,7 +36,7 @@ export const useFindCspRules = ( savedObjects.client .get(PACKAGE_POLICY_SAVED_OBJECT_TYPE, packagePolicyId) .then((res) => { - const benchmarkId = extractBenchmarkFromPackagePolicy(res.attributes.inputs); + const benchmarkId = getBenchmarkFromPackagePolicy(res.attributes.inputs); return savedObjects.client.find({ type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, @@ -45,7 +45,7 @@ export const useFindCspRules = ( page: 1, sortField: 'metadata.name', perPage, - filter: getBenchmarkTypeFilterFromBenchmarkId(benchmarkId), + filter: getBenchmarkTypeFilter(benchmarkId), }); }) ); diff --git a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts index d4b639eab4b89..bc9243fad2792 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts @@ -55,9 +55,9 @@ export const createCspBenchmarkIntegrationFixture = ({ name: chance.sentence(), agents: chance.integer({ min: 0 }), }, - number_of_rules = chance.integer({ min: 0, max: 10 }), + rules_count = chance.integer({ min: 0, max: 10 }), }: CreateCspBenchmarkIntegrationFixtureInput = {}): Benchmark => ({ package_policy, agent_policy, - number_of_rules, + rules_count, }); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index de8db31f25909..937d62afa231a 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -6,9 +6,8 @@ */ import type { Logger } from '@kbn/core/server'; import { SavedObjectsClientContract } from '@kbn/core/server'; -import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; import { PackagePolicyClient } from '@kbn/fleet-plugin/server'; -import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../common/constants'; +import { getCSPKuery } from '../../common/utils/helpers'; export const isCspPackagePolicyInstalled = async ( packagePolicyClient: PackagePolicyClient, @@ -17,7 +16,7 @@ export const isCspPackagePolicyInstalled = async ( ): Promise => { try { const { total } = await packagePolicyClient.list(soClient, { - kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${CLOUD_SECURITY_POSTURE_PACKAGE_NAME}`, + kuery: getCSPKuery, page: 1, }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index e4da81a088729..656d34462464b 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -259,7 +259,7 @@ describe('benchmarks API', () => { }); describe('test addPackagePolicyCspRules', () => { - it('should return filtered by the relevant benchmark and return the total number of csp rule template of this exact benchmark', async () => { + it('should retrieve the rules count by the filtered benchmark type', async () => { const benchmark = 'cis_k8s'; mockSoClient.find.mockResolvedValueOnce({ aggregations: { enabled_status: { doc_count: 2 } }, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index 1b2c3cb97c79b..00c32f1b46f4a 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -16,8 +16,8 @@ import { import { benchmarksQueryParamsSchema } from '../../../common/schemas/benchmark'; import type { Benchmark } from '../../../common/types'; import { - extractBenchmarkFromPackagePolicy, - getBenchmarkTypeFilterFromBenchmarkId, + getBenchmarkFromPackagePolicy, + getBenchmarkTypeFilter, isNonNullable, } from '../../../common/utils/helpers'; import { CspRouter } from '../../types'; @@ -33,11 +33,11 @@ export const PACKAGE_POLICY_SAVED_OBJECT_TYPE = 'ingest-package-policies'; export const getRulesCountForPolicy = async ( soClient: SavedObjectsClientContract, - benchmarkName: BenchmarkId + benchmarkId: BenchmarkId ): Promise => { const rules = await soClient.find({ type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - filter: getBenchmarkTypeFilterFromBenchmarkId(benchmarkName), + filter: getBenchmarkTypeFilter(benchmarkId), perPage: 0, }); @@ -64,7 +64,7 @@ const createBenchmarks = ( .filter(isNonNullable) ?? []; const benchmarks = cspPackagesOnAgent.map(async (cspPackage) => { - const benchmarkId = extractBenchmarkFromPackagePolicy(cspPackage.inputs); + const benchmarkId = getBenchmarkFromPackagePolicy(cspPackage.inputs); const rulesCount = await getRulesCountForPolicy(soClient, benchmarkId); const agentPolicyStatus = { id: agentPolicy.id, @@ -74,7 +74,7 @@ const createBenchmarks = ( return { package_policy: cspPackage, agent_policy: agentPolicyStatus, - number_of_rules: rulesCount, + rules_count: rulesCount, }; }); From 8d84746cfa015fdb99208704f40f0979c99e283c Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Mon, 26 Dec 2022 13:07:59 +0200 Subject: [PATCH 19/23] Correct it to import type --- x-pack/plugins/cloud_security_posture/common/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index bc5a86434e402..29525fa95e19b 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -6,7 +6,7 @@ */ import type { PackagePolicy, AgentPolicy } from '@kbn/fleet-plugin/common'; -import { CspRuleMetadata } from './schemas'; +import type { CspRuleMetadata } from './schemas/csp_rule_metadata'; export type Evaluation = 'passed' | 'failed' | 'NA'; /** number between 1-100 */ From baf4098c68dc44acf590316c3e0f391de4d9c640 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 26 Dec 2022 11:38:55 +0000 Subject: [PATCH 20/23] [CI] Auto-commit changed files from 'node scripts/ts_project_linter --fix' --- x-pack/plugins/cloud_security_posture/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/cloud_security_posture/tsconfig.json b/x-pack/plugins/cloud_security_posture/tsconfig.json index 347f6e9c51057..d6946e0b71b55 100755 --- a/x-pack/plugins/cloud_security_posture/tsconfig.json +++ b/x-pack/plugins/cloud_security_posture/tsconfig.json @@ -45,6 +45,7 @@ "@kbn/es-types", "@kbn/core-elasticsearch-server", "@kbn/ecs", + "@kbn/core-saved-objects-api-server-mocks", ], "exclude": [ "target/**/*", From ca37e644eb4b4556cd5617138fff924575a134c3 Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Mon, 26 Dec 2022 14:17:29 +0200 Subject: [PATCH 21/23] Fixing test to use test cases rather than using string tagged templates --- .../cloud_security_posture/common/utils/helpers.ts | 11 ----------- .../fleet_integration/fleet_integration.test.ts | 11 +++++------ .../cloud_security_posture/server/plugin.test.ts | 11 +++++------ 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 104c8df62a630..37575e4adda42 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -71,14 +71,3 @@ export function assert(condition: any, msg?: string): asserts condition { throw new Error(msg); } } - -export const createCspRuleSearchFilterByPackagePolicy = ({ - packagePolicyId, - policyId, -}: { - packagePolicyId: string; - policyId?: string; -}): string => - `${CSP_RULE_SAVED_OBJECT_TYPE}.attributes.package_policy_id: "${packagePolicyId}"${ - policyId ? ` AND ${CSP_RULE_SAVED_OBJECT_TYPE}.attributes.policy_id: "${policyId}"` : '' - }`; diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts index c9a02e6a49e45..a27f60c9f3fd6 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts @@ -18,13 +18,12 @@ describe('is Csp package installed tests', () => { const packagePolicyService = createPackagePolicyServiceMock(); beforeEach(() => jest.clearAllMocks()); - it.each` - total | items | expectedCspPolicyResponse - ${1} | ${[createPackagePolicyMock()]} | ${true} - ${0} | ${[]} | ${false} - `( + it.each([ + [1, [createPackagePolicyMock()], true], + [0, [], false], + ])( 'isCspPackagePolicyInstalled should return true when other packages exist', - async ({ total, items, expectedCspPolicyResponse }) => { + async (total, items, expectedCspPolicyResponse) => { packagePolicyService.list.mockImplementationOnce( async (): Promise> => { return { diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts index 2b72d1e1cef10..0d5b88d0ccdb2 100644 --- a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts @@ -259,13 +259,12 @@ describe('Cloud Security Posture Plugin', () => { expect(fleetMock.packagePolicyService.update).toHaveBeenCalledTimes(0); }); - it.each` - total | items | expectedNumberOfCallsToUninstallResources - ${1} | ${[createPackagePolicyMock()]} | ${0} - ${0} | ${[]} | ${1} - `( + it.each([ + [1, [createPackagePolicyMock()], 0], + [0, [], 1], + ])( 'should uninstall resources when package is removed', - async ({ total, items, expectedNumberOfCallsToUninstallResources }) => { + async (total, items, expectedNumberOfCallsToUninstallResources) => { fleetMock.packagePolicyService.list.mockImplementationOnce( async (): Promise> => { return { From e696bb98ca7e05ace9848af38ba68a7b82b2fe3c Mon Sep 17 00:00:00 2001 From: ofiriro3 Date: Mon, 26 Dec 2022 16:44:59 +0200 Subject: [PATCH 22/23] Merge main to mine --- .../fleet_integration.test.ts | 55 +++++++++++++++++-- .../fleet_integration/fleet_integration.ts | 25 +++++++++ .../server/plugin.test.ts | 20 +++++++ .../cloud_security_posture/server/plugin.ts | 9 ++- 4 files changed, 103 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts index a27f60c9f3fd6..7853df051f0fa 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts @@ -7,17 +7,58 @@ import { createPackagePolicyServiceMock } from '@kbn/fleet-plugin/server/mocks'; import { ListResult, PackagePolicy } from '@kbn/fleet-plugin/common'; -import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; -import { isCspPackagePolicyInstalled } from './fleet_integration'; +import { + isCspPackagePolicyInstalled, + onPackagePolicyPostCreateCallback, +} from './fleet_integration'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; +import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../common/constants'; +import { SavedObjectsFindResponse } from '@kbn/core-saved-objects-api-server'; +import { savedObjectsClientMock } from '@kbn/core/server/mocks'; describe('is Csp package installed tests', () => { const logger = loggingSystemMock.createLogger(); - const soClient = savedObjectsClientMock.create(); + const mockSoClient = savedObjectsClientMock.create(); const packagePolicyService = createPackagePolicyServiceMock(); - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => { + return jest.clearAllMocks(); + }); + it.each([ + ['cloud_security_posture-41308bcdaaf665761478bb6f0d55555', ['default']], + ['cloud_security_posture-41308bcdaaf665761478bb6f0d88888', ['foo']], + ])( + 'validate that all index pattern are available cross spaces', + async (id: string, namespaces: string[]) => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; + mockSoClient.find.mockResolvedValueOnce({ + saved_objects: [ + { + type: 'index-pattern', + id, + namespaces, + }, + ], + pit_id: undefined, + } as unknown as SavedObjectsFindResponse); + + await onPackagePolicyPostCreateCallback(logger, mockPackagePolicy, mockSoClient); + + expect(mockSoClient.updateObjectsSpaces).toHaveBeenCalled(); + expect(mockSoClient.updateObjectsSpaces).lastCalledWith( + [ + { + id, + type: 'index-pattern', + }, + ], + ['*'], + [] + ); + } + ); it.each([ [1, [createPackagePolicyMock()], true], [0, [], false], @@ -35,7 +76,11 @@ describe('is Csp package installed tests', () => { } ); - const isInstalled = await isCspPackagePolicyInstalled(packagePolicyService, soClient, logger); + const isInstalled = await isCspPackagePolicyInstalled( + packagePolicyService, + mockSoClient, + logger + ); expect(isInstalled).toEqual(expectedCspPolicyResponse); } ); diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index 937d62afa231a..22097dbfc69fd 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -7,7 +7,32 @@ import type { Logger } from '@kbn/core/server'; import { SavedObjectsClientContract } from '@kbn/core/server'; import { PackagePolicyClient } from '@kbn/fleet-plugin/server'; +import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { DataViewSavedObjectAttrs } from '@kbn/data-views-plugin/common'; import { getCSPKuery } from '../../common/utils/helpers'; +import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../common/constants'; + +export const onPackagePolicyPostCreateCallback = async ( + logger: Logger, + packagePolicy: PackagePolicy, + savedObjectsClient: SavedObjectsClientContract +): Promise => { + return addDataViewToAllSpaces(savedObjectsClient); +}; + +async function addDataViewToAllSpaces(savedObjectsClient: SavedObjectsClientContract) { + const cspmDataViews = await savedObjectsClient.find({ + type: 'index-pattern', + fields: ['title'], + search: CLOUD_SECURITY_POSTURE_PACKAGE_NAME + '*', + searchFields: ['title'], + perPage: 100, + }); + + cspmDataViews.saved_objects.forEach((dataView) => { + savedObjectsClient.updateObjectsSpaces([{ id: dataView.id, type: 'index-pattern' }], ['*'], []); + }); +} export const isCspPackagePolicyInstalled = async ( packagePolicyClient: PackagePolicyClient, diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts index 0d5b88d0ccdb2..0689854210e0f 100644 --- a/x-pack/plugins/cloud_security_posture/server/plugin.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.test.ts @@ -82,6 +82,26 @@ describe('Cloud Security Posture Plugin', () => { }; const contextMock = coreMock.createCustomRequestHandlerContext(mockRouteContext); + const findMock = mockRouteContext.core.savedObjects.client.find as jest.Mock; + findMock.mockReturnValue( + Promise.resolve({ + saved_objects: [ + { + type: 'csp_rule', + attributes: { + enabled: false, + metadata: { + rego_rule_id: 'cis_1_1_1', + benchmark: { id: 'cis_k8s' }, + }, + }, + }, + ], + total: 1, + per_page: 10, + page: 1, + }) + ); let plugin: CspPlugin; diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 202bee7527f6e..915d9b6138ad0 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -37,7 +37,10 @@ import { setupRoutes } from './routes/setup_routes'; import { setupSavedObjects } from './saved_objects'; import { initializeCspIndices } from './create_indices/create_indices'; import { initializeCspTransforms } from './create_transforms/create_transforms'; -import { isCspPackagePolicyInstalled } from './fleet_integration/fleet_integration'; +import { + isCspPackagePolicyInstalled, + onPackagePolicyPostCreateCallback, +} from './fleet_integration/fleet_integration'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../common/constants'; import { removeFindingsStatsTask, @@ -131,6 +134,10 @@ export class CspPlugin ): Promise => { if (isCspPackage(packagePolicy.package?.name)) { await this.initialize(core, plugins.taskManager); + const soClient = (await context.core).savedObjects.client; + await onPackagePolicyPostCreateCallback(this.logger, packagePolicy, soClient); + + return packagePolicy; } return packagePolicy; From 0b3cd273d98377eb2254836ef6ff9943477da464 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 26 Dec 2022 14:49:24 +0000 Subject: [PATCH 23/23] [CI] Auto-commit changed files from 'node scripts/ts_project_linter --fix' --- x-pack/plugins/cloud_security_posture/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/cloud_security_posture/tsconfig.json b/x-pack/plugins/cloud_security_posture/tsconfig.json index d6946e0b71b55..71d207ec19a65 100755 --- a/x-pack/plugins/cloud_security_posture/tsconfig.json +++ b/x-pack/plugins/cloud_security_posture/tsconfig.json @@ -45,7 +45,7 @@ "@kbn/es-types", "@kbn/core-elasticsearch-server", "@kbn/ecs", - "@kbn/core-saved-objects-api-server-mocks", + "@kbn/core-saved-objects-api-server", ], "exclude": [ "target/**/*",