Skip to content

Commit

Permalink
Merge branch 'main' into update_findings_mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
uri-weisman authored May 4, 2022
2 parents ecaf839 + dda625c commit f4631c3
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ describe('AnalyticsClient', () => {

test(
'Spreads the context updates to the shipper (only after opt-in)',
fakeSchedulers(async (advance) => {
fakeSchedulers((advance) => {
const extendContextMock = jest.fn();
analyticsClient.registerShipper(MockedShipper, { extendContextMock });
expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in
Expand Down Expand Up @@ -345,7 +345,7 @@ describe('AnalyticsClient', () => {

test(
'Does not spread the context if opt-in === false',
fakeSchedulers(async (advance) => {
fakeSchedulers((advance) => {
const extendContextMock = jest.fn();
analyticsClient.registerShipper(MockedShipper, { extendContextMock });
expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in
Expand All @@ -357,7 +357,7 @@ describe('AnalyticsClient', () => {

test(
'Handles errors in the shipper',
fakeSchedulers(async (advance) => {
fakeSchedulers((advance) => {
const extendContextMock = jest.fn().mockImplementation(() => {
throw new Error('Something went terribly wrong');
});
Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/cloud_security_posture/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ export interface ComplianceDashboardData {
trend: PostureTrend[];
}

export interface CspRulesStatus {
all: number;
enabled: number;
disabled: number;
}

export interface Benchmark {
package_policy: Pick<
PackagePolicy,
Expand All @@ -61,4 +67,5 @@ export interface Benchmark {
| 'created_by'
>;
agent_policy: Pick<GetAgentPoliciesResponseItem, 'id' | 'name' | 'agents'>;
rules: CspRulesStatus;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ export const createCspBenchmarkIntegrationFixture = ({
name: chance.sentence(),
agents: chance.integer({ min: 0 }),
},
rules = {
all: chance.integer(),
enabled: chance.integer(),
disabled: chance.integer(),
},
}: CreateCspBenchmarkIntegrationFixtureInput = {}): Benchmark => ({
package_policy,
agent_policy,
rules,
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import {
import {
defineGetBenchmarksRoute,
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
getPackagePolicies,
getCspPackagePolicies,
getAgentPolicies,
createBenchmarkEntry,
addPackagePolicyCspRules,
} from './benchmarks';

import { SavedObjectsClientContract } from '@kbn/core/server';
import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server';
import {
createMockAgentPolicyService,
createPackagePolicyServiceMock,
Expand Down Expand Up @@ -221,7 +222,7 @@ describe('benchmarks API', () => {
it('should format request by package name', async () => {
const mockPackagePolicyService = createPackagePolicyServiceMock();

await getPackagePolicies(mockSoClient, mockPackagePolicyService, 'myPackage', {
await getCspPackagePolicies(mockSoClient, mockPackagePolicyService, 'myPackage', {
page: 1,
per_page: 100,
sort_order: 'desc',
Expand All @@ -239,7 +240,7 @@ describe('benchmarks API', () => {
it('should build sort request by `sort_field` and default `sort_order`', async () => {
const mockAgentPolicyService = createPackagePolicyServiceMock();

await getPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
page: 1,
per_page: 100,
sort_field: 'package_policy.name',
Expand All @@ -260,7 +261,7 @@ describe('benchmarks API', () => {
it('should build sort request by `sort_field` and asc `sort_order`', async () => {
const mockAgentPolicyService = createPackagePolicyServiceMock();

await getPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
page: 1,
per_page: 100,
sort_field: 'package_policy.name',
Expand All @@ -282,7 +283,7 @@ describe('benchmarks API', () => {
it('should format request by benchmark_name', async () => {
const mockAgentPolicyService = createPackagePolicyServiceMock();

await getPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
page: 1,
per_page: 100,
sort_order: 'desc',
Expand Down Expand Up @@ -322,16 +323,51 @@ describe('benchmarks API', () => {
});
});

describe('test addPackagePolicyCspRules', () => {
it('should filter enabled rules', async () => {
const packagePolicy = createPackagePolicyMock();
mockSoClient.find.mockResolvedValueOnce({
aggregations: { enabled_status: { doc_count: 2 } },
page: 1,
per_page: 10000,
total: 3,
saved_objects: [
{
type: 'csp_rule',
id: '0af387d0-c933-11ec-b6c8-4f8afc058cc3',
},
],
} as unknown as SavedObjectsFindResponse);

const cspRulesStatus = await addPackagePolicyCspRules(mockSoClient, packagePolicy);

expect(cspRulesStatus).toEqual({
all: 3,
enabled: 2,
disabled: 1,
});
});
});

describe('test createBenchmarkEntry', () => {
it('should build benchmark entry agent policy and package policy', async () => {
const packagePolicy = createPackagePolicyMock();
const agentPolicy = createMockAgentPolicy();
// @ts-expect-error
agentPolicy.agents = 3;

const enrichAgentPolicy = await createBenchmarkEntry(agentPolicy, packagePolicy);
const cspRulesStatus = {
all: 100,
enabled: 52,
disabled: 48,
};
const enrichAgentPolicy = await createBenchmarkEntry(
agentPolicy,
packagePolicy,
cspRulesStatus
);

expect(enrichAgentPolicy).toMatchObject({
expect(enrichAgentPolicy).toEqual({
package_policy: {
id: 'c6d16e42-c32d-4dce-8a88-113cfe276ad1',
name: 'endpoint-1',
Expand All @@ -348,6 +384,11 @@ describe('benchmarks API', () => {
},
},
agent_policy: { id: 'some-uuid1', name: 'Test Policy', agents: 3 },
rules: {
all: 100,
disabled: 48,
enabled: 52,
},
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { uniq, map } from 'lodash';
import type { SavedObjectsClientContract } from '@kbn/core/server';
import type { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server';
import { transformError } from '@kbn/securitysolution-es-utils';
import type {
PackagePolicyServiceInterface,
Expand All @@ -19,6 +19,7 @@ import type {
AgentPolicy,
ListResult,
} from '@kbn/fleet-plugin/common';
import { cspRuleAssetSavedObjectType, CspRuleSchema } from '../../../common/schemas/csp_rule';
import {
BENCHMARKS_ROUTE_PATH,
CLOUD_SECURITY_POSTURE_PACKAGE_NAME,
Expand All @@ -29,7 +30,7 @@ import {
BenchmarksQuerySchema,
} from '../../../common/schemas/benchmark';
import { CspAppContext } from '../../plugin';
import type { Benchmark } from '../../../common/types';
import type { Benchmark, CspRulesStatus } from '../../../common/types';
import { isNonNullable } from '../../../common/utils/helpers';
import { CspRouter } from '../../types';

Expand All @@ -44,7 +45,7 @@ const getPackageNameQuery = (packageName: string, benchmarkFilter?: string): str
return kquery;
};

export const getPackagePolicies = (
export const getCspPackagePolicies = (
soClient: SavedObjectsClientContract,
packagePolicyService: PackagePolicyServiceInterface,
packageName: string,
Expand Down Expand Up @@ -94,10 +95,49 @@ const addRunningAgentToAgentPolicy = async (
)
);
};
export interface RulesStatusAggregation {
enabled_status: {
doc_count: number;
};
}
export const getCspRulesStatus = (
soClient: SavedObjectsClientContract,
packagePolicy: PackagePolicy
): Promise<SavedObjectsFindResponse<CspRuleSchema, RulesStatusAggregation>> => {
const cspRules = soClient.find<CspRuleSchema, RulesStatusAggregation>({
type: cspRuleAssetSavedObjectType,
filter: `${cspRuleAssetSavedObjectType}.attributes.package_policy_id: ${packagePolicy.id} AND ${cspRuleAssetSavedObjectType}.attributes.policy_id: ${packagePolicy.policy_id}`,
aggs: {
enabled_status: {
filter: {
term: {
[`${cspRuleAssetSavedObjectType}.attributes.enabled`]: true,
},
},
},
},
perPage: 0,
});
return cspRules;
};

export const addPackagePolicyCspRules = async (
soClient: SavedObjectsClientContract,
packagePolicy: PackagePolicy
): Promise<CspRulesStatus> => {
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;
};

export const createBenchmarkEntry = (
agentPolicy: GetAgentPoliciesResponseItem,
packagePolicy: PackagePolicy
packagePolicy: PackagePolicy,
cspRulesStatus: CspRulesStatus
): Benchmark => ({
package_policy: {
id: packagePolicy.id,
Expand All @@ -121,26 +161,33 @@ export const createBenchmarkEntry = (
name: agentPolicy.name,
agents: agentPolicy.agents,
},
rules: cspRulesStatus,
});

const createBenchmarks = (
soClient: SavedObjectsClientContract,
agentPolicies: GetAgentPoliciesResponseItem[],
packagePolicies: PackagePolicy[]
): Benchmark[] =>
packagePolicies.flatMap((packagePolicy) => {
return agentPolicies
.map((agentPolicy) => {
const agentPkgPolicies = agentPolicy.package_policies as string[];
const isExistsOnAgent = agentPkgPolicies.find(
(pkgPolicy) => pkgPolicy === packagePolicy.id
);
if (isExistsOnAgent) {
return createBenchmarkEntry(agentPolicy, packagePolicy);
}
return;
})
.filter(isNonNullable);
});
cspPackagePolicies: PackagePolicy[]
): Promise<Benchmark[]> => {
const cspPackagePoliciesMap = new Map(
cspPackagePolicies.map((packagePolicy) => [packagePolicy.id, packagePolicy])
);
return Promise.all(
agentPolicies.flatMap((agentPolicy) => {
const cspPackagesOnAgent = agentPolicy.package_policies
.map((pckPolicyId) => {
if (typeof pckPolicyId === 'string') return cspPackagePoliciesMap.get(pckPolicyId);
})
.filter(isNonNullable);
const benchmarks = cspPackagesOnAgent.map(async (cspPackage) => {
const cspRulesStatus = await addPackagePolicyCspRules(soClient, cspPackage);
const benchmark = createBenchmarkEntry(agentPolicy, cspPackage, cspRulesStatus);
return benchmark;
});
return benchmarks;
})
);
};

export const defineGetBenchmarksRoute = (router: CspRouter, cspContext: CspAppContext): void =>
router.get(
Expand All @@ -165,7 +212,7 @@ export const defineGetBenchmarksRoute = (router: CspRouter, cspContext: CspAppCo
throw new Error(`Failed to get Fleet services`);
}

const packagePolicies = await getPackagePolicies(
const cspPackagePolicies = await getCspPackagePolicies(
soClient,
packagePolicyService,
CLOUD_SECURITY_POSTURE_PACKAGE_NAME,
Expand All @@ -174,15 +221,20 @@ export const defineGetBenchmarksRoute = (router: CspRouter, cspContext: CspAppCo

const agentPolicies = await getAgentPolicies(
soClient,
packagePolicies.items,
cspPackagePolicies.items,
agentPolicyService
);

const enrichAgentPolicies = await addRunningAgentToAgentPolicy(agentService, agentPolicies);
const benchmarks = createBenchmarks(enrichAgentPolicies, packagePolicies.items);
const benchmarks = await createBenchmarks(
soClient,
enrichAgentPolicies,
cspPackagePolicies.items
);

return response.ok({
body: {
...packagePolicies,
...cspPackagePolicies,
items: benchmarks,
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,17 @@ export const getPackagePolicy = async (
return packagePolicies![0];
};

export const getCspRules = async (
export const getCspRules = (
soClient: SavedObjectsClientContract,
packagePolicy: PackagePolicy
) => {
const cspRules = await soClient.find<CspRuleSchema>({
): Promise<SavedObjectsFindResponse<CspRuleSchema, unknown>> => {
return soClient.find<CspRuleSchema>({
type: cspRuleAssetSavedObjectType,
filter: `${cspRuleAssetSavedObjectType}.attributes.package_policy_id: ${packagePolicy.id} AND ${cspRuleAssetSavedObjectType}.attributes.policy_id: ${packagePolicy.policy_id}`,
searchFields: ['name'],
// TODO: research how to get all rules
perPage: 10000,
});
return cspRules;
};

export const createRulesConfig = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ export const ruleAssetSavedObjectMappings: SavedObjectsType<CspRuleSchema>['mapp
description: {
type: 'text',
},
enabled: {
type: 'boolean',
fields: {
keyword: {
type: 'keyword', // sort
},
},
},
},
};

Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/osquery/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class OsqueryPlugin implements Plugin<OsqueryPluginSetup, OsqueryPluginSt
title: PLUGIN_NAME,
order: 9030,
category: DEFAULT_APP_CATEGORIES.management,
euiIconType: 'logoOsquery',
async mount(params: AppMountParameters) {
// Get start services as specified in kibana.json
const [coreStart, depsStart] = await core.getStartServices();
Expand Down

0 comments on commit f4631c3

Please sign in to comment.