Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cloud Security] Add telemetry for muting rules #174842

Merged
merged 4 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ const getCspmAccountsStats = (
nodes_count: account.nodes_count.value,
pods_count: account.resources.pods_count.value,
}));
logger.info('CSPM telemetry: accounts stats was sent');

return cspmAccountsStats;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,6 @@ export const getCloudAccountsStats = (
};
});

logger.info('Cloud Account Stats telemetry: accounts stats was sent');

return cloudAccountsStats;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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 {
ISavedObjectsRepository,
SavedObjectsClientContract,
} from '@kbn/core-saved-objects-api-server';
import type { Logger } from '@kbn/core/server';
import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants';
import { CspBenchmarkRule } from '../../../../common/types/latest';
import { getCspBenchmarkRulesStatesHandler } from '../../../routes/benchmark_rules/get_states/v1';
import { MutedRulesStats } from './types';

export const getMutedRulesStats = async (
soClient: SavedObjectsClientContract,
encryptedSoClient: ISavedObjectsRepository,
logger: Logger
): Promise<MutedRulesStats[]> => {
try {
const benchmarkRulesStates = await getCspBenchmarkRulesStatesHandler(encryptedSoClient);
const mutedBenchmarkRules = Object.fromEntries(
Object.entries(benchmarkRulesStates).filter(([_, value]) => value.muted === true)
);

const mutedRulesStats = await Promise.all(
Object.values(mutedBenchmarkRules).map(async (mutedBenchmarkRule) => {
const cspBenchmarkRulesSo = await soClient.get<CspBenchmarkRule>(
CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE,
mutedBenchmarkRule.rule_id
);
const ruleMetadata = cspBenchmarkRulesSo.attributes.metadata;
if (ruleMetadata) {
return {
id: ruleMetadata.id,
name: ruleMetadata.name,
benchmark_id: ruleMetadata.benchmark.id,
benchmark_name: ruleMetadata.benchmark.name,
benchmark_version: mutedBenchmarkRule.benchmark_version, // The state object may include different benchmark version then the latest one.
rule_number: ruleMetadata.benchmark.rule_number,
posture_type: ruleMetadata.benchmark.posture_type,
section: ruleMetadata.section,
version: ruleMetadata.version,
};
}
return null;
})
);

return mutedRulesStats.filter(
(filteredMetadata) => filteredMetadata !== null
) as MutedRulesStats[];
} catch (e) {
logger.error(`Failed to get rules states stats ${e}`);
return [];
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { getRulesStats } from './rules_stats_collector';
import { getInstallationStats } from './installation_stats_collector';
import { getAlertsStats } from './alert_stats_collector';
import { getAllCloudAccountsStats } from './cloud_accounts_stats_collector';
import { getMutedRulesStats } from './muted_rules_stats_collector';
import { INTERNAL_CSP_SETTINGS_SAVED_OBJECT_TYPE } from '../../../../common/constants';

export function registerCspmUsageCollector(
logger: Logger,
Expand All @@ -42,6 +44,7 @@ export function registerCspmUsageCollector(
) => {
try {
const val = await promise;
logger.info(`Cloud Security telemetry: ${taskName} payload was sent successfully`);
return val;
} catch (error) {
logger.error(`${taskName} task failed: ${error.message}`);
Expand All @@ -52,6 +55,10 @@ export function registerCspmUsageCollector(

const esClient = collectorFetchContext.esClient;
const soClient = collectorFetchContext.soClient;
const encryptedSoClient = (await coreServices)[0].savedObjects.createInternalRepository([
INTERNAL_CSP_SETTINGS_SAVED_OBJECT_TYPE,
]);

const [
indicesStats,
accountsStats,
Expand All @@ -60,6 +67,7 @@ export function registerCspmUsageCollector(
installationStats,
alertsStats,
cloudAccountStats,
mutedRulesStats,
] = await Promise.all([
awaitPromiseSafe('Indices', getIndicesStats(esClient, soClient, coreServices, logger)),
awaitPromiseSafe('Accounts', getAccountsStats(esClient, logger)),
Expand All @@ -71,6 +79,7 @@ export function registerCspmUsageCollector(
),
awaitPromiseSafe('Alerts', getAlertsStats(esClient, logger)),
awaitPromiseSafe('Cloud Accounts', getAllCloudAccountsStats(esClient, logger)),
awaitPromiseSafe('Muted Rules', getMutedRulesStats(soClient, encryptedSoClient, logger)),
]);
return {
indices: indicesStats,
Expand All @@ -80,6 +89,7 @@ export function registerCspmUsageCollector(
installation_stats: installationStats,
alerts_stats: alertsStats,
cloud_account_stats: cloudAccountStats,
muted_rules_stats: mutedRulesStats,
};
},
schema: cspmUsageSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ const getCspmResourcesStats = (
});
});
});
logger.info('CSPM telemetry: resources stats was sent');

return resourcesStats.flat(2);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,18 @@ export const cspmUsageSchema: MakeSchemaFrom<CspmUsage> = {
},
},
},
muted_rules_stats: {
type: 'array',
items: {
id: { type: 'keyword' },
name: { type: 'keyword' },
section: { type: 'keyword' },
benchmark_id: { type: 'keyword' },
benchmark_name: { type: 'keyword' },
benchmark_version: { type: 'keyword' },
rule_number: { type: 'keyword' },
posture_type: { type: 'keyword' },
version: { type: 'keyword' },
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export type CloudSecurityUsageCollectorType =
| 'Rules'
| 'Installation'
| 'Alerts'
| 'Cloud Accounts';
| 'Cloud Accounts'
| 'Muted Rules';

export type CloudProviderKey = 'cis_eks' | 'cis_gke' | 'cis_k8s' | 'cis_ake';
export type CloudbeatConfigKeyType =
Expand All @@ -32,6 +33,7 @@ export interface CspmUsage {
installation_stats: CloudSecurityInstallationStats[];
alerts_stats: CloudSecurityAlertsStats[];
cloud_account_stats: CloudSecurityAccountsStats[];
muted_rules_stats: MutedRulesStats[];
}

export interface PackageSetupStatus {
Expand Down Expand Up @@ -214,3 +216,15 @@ export interface AccountEntity {
pods_count: Value;
};
}

export interface MutedRulesStats {
id: string;
name: string;
section: string;
version: string;
benchmark_id: string;
benchmark_name: string;
benchmark_version: string;
posture_type: string;
rule_number: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7716,6 +7716,40 @@
}
}
}
},
"muted_rules_stats": {
"type": "array",
"items": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"section": {
"type": "keyword"
},
"benchmark_id": {
"type": "keyword"
},
"benchmark_name": {
"type": "keyword"
},
"benchmark_version": {
"type": "keyword"
},
"rule_number": {
"type": "keyword"
},
"posture_type": {
"type": "keyword"
},
"version": {
"type": "keyword"
}
}
}
}
}
},
Expand Down