mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
# Backport This will backport the following commits from `main` to `8.11`: - [[Cloud Security][Telemetry] Create a unified cloud accounts collector (#167203)](https://github.com/elastic/kibana/pull/167203) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Lola","email":"omolola.akinleye@elastic.co"},"sourceCommit":{"committedDate":"2023-10-04T22:26:49Z","message":"[Cloud Security][Telemetry] Create a unified cloud accounts collector (#167203)\n\n## Summary\r\n\r\nSummarize your PR. If it involves visual changes include a screenshot or\r\ngif.\r\n\r\nAdds Cloud Security Telemetry to track all cloud accounts from products\r\n`CSPM`,`KSPM`, and`CNVM`\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"fc434d185dfbdac8061aa2c344fb03013f462c9d","branchLabelMapping":{"^v8.12.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Cloud Security","v8.11.0","v8.12.0"],"number":167203,"url":"https://github.com/elastic/kibana/pull/167203","mergeCommit":{"message":"[Cloud Security][Telemetry] Create a unified cloud accounts collector (#167203)\n\n## Summary\r\n\r\nSummarize your PR. If it involves visual changes include a screenshot or\r\ngif.\r\n\r\nAdds Cloud Security Telemetry to track all cloud accounts from products\r\n`CSPM`,`KSPM`, and`CNVM`\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"fc434d185dfbdac8061aa2c344fb03013f462c9d"}},"sourceBranch":"main","suggestedTargetBranches":["8.11"],"targetPullRequestStates":[{"branch":"8.11","label":"v8.11.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.12.0","labelRegex":"^v8.12.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/167203","number":167203,"mergeCommit":{"message":"[Cloud Security][Telemetry] Create a unified cloud accounts collector (#167203)\n\n## Summary\r\n\r\nSummarize your PR. If it involves visual changes include a screenshot or\r\ngif.\r\n\r\nAdds Cloud Security Telemetry to track all cloud accounts from products\r\n`CSPM`,`KSPM`, and`CNVM`\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"fc434d185dfbdac8061aa2c344fb03013f462c9d"}}]}] BACKPORT--> Co-authored-by: Lola <omolola.akinleye@elastic.co>
This commit is contained in:
parent
379cbdaea1
commit
6a19c59fbd
9 changed files with 699 additions and 5 deletions
|
@ -20,7 +20,6 @@ export const getIdentifierRuntimeMapping = (): MappingRuntimeFields => ({
|
|||
!doc["rule.benchmark.posture_type"].empty;
|
||||
def orchestratorIdAvailable = doc.containsKey("orchestrator.cluster.id") &&
|
||||
!doc["orchestrator.cluster.id"].empty;
|
||||
|
||||
if (!postureTypeAvailable) {
|
||||
def identifier = orchestratorIdAvailable ?
|
||||
doc["orchestrator.cluster.id"].value : doc["cluster_id"].value;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
|
||||
export const getPackagePolicyIdRuntimeMapping = (): MappingRuntimeFields => ({
|
||||
package_policy_identifier: {
|
||||
type: 'keyword',
|
||||
script: {
|
||||
source: `
|
||||
def packagePolicyIdAvailable = doc.containsKey("cloud_security_posture.package_policy.id") &&
|
||||
!doc["cloud_security_posture.package_policy.id"].empty;
|
||||
if (packagePolicyIdAvailable) {
|
||||
emit(doc["cloud_security_posture.package_policy.id"].value);
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
});
|
|
@ -20,7 +20,7 @@ export const getSafeKspmClusterIdRuntimeMapping = (): MappingRuntimeFields => ({
|
|||
!doc["orchestrator.cluster.id"].empty;
|
||||
def clusterIdAvailable = doc.containsKey("cluster_id") &&
|
||||
!doc["cluster_id"].empty;
|
||||
|
||||
|
||||
if (orchestratorIdAvailable) {
|
||||
emit(doc["orchestrator.cluster.id"].value);
|
||||
} else if (clusterIdAvailable) {
|
||||
|
|
|
@ -0,0 +1,411 @@
|
|||
/*
|
||||
* 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 type { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
|
||||
import type { Logger } from '@kbn/core/server';
|
||||
import type { SearchRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { getPackagePolicyIdRuntimeMapping } from '../../../../common/runtime_mappings/get_package_policy_id_mapping';
|
||||
import { getIdentifierRuntimeMapping } from '../../../../common/runtime_mappings/get_identifier_runtime_mapping';
|
||||
import { calculatePostureScore } from '../../../../common/utils/helpers';
|
||||
import type {
|
||||
AccountEntity,
|
||||
AccountsStats,
|
||||
CloudProviderKey,
|
||||
CloudSecurityAccountsStats,
|
||||
} from './types';
|
||||
import {
|
||||
CSPM_POLICY_TEMPLATE,
|
||||
KSPM_POLICY_TEMPLATE,
|
||||
LATEST_FINDINGS_INDEX_DEFAULT_NS,
|
||||
LATEST_VULNERABILITIES_INDEX_DEFAULT_NS,
|
||||
VULN_MGMT_POLICY_TEMPLATE,
|
||||
} from '../../../../common/constants';
|
||||
|
||||
export const getPostureAccountsStatsQuery = (index: string): SearchRequest => ({
|
||||
index,
|
||||
runtime_mappings: { ...getIdentifierRuntimeMapping(), ...getPackagePolicyIdRuntimeMapping() },
|
||||
query: {
|
||||
match_all: {},
|
||||
},
|
||||
aggs: {
|
||||
accounts: {
|
||||
terms: {
|
||||
field: 'asset_identifier',
|
||||
order: {
|
||||
_count: 'desc',
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
aggs: {
|
||||
cloud_provider: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: 'cloud.provider',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
latest_doc_updated_timestamp: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: '@timestamp',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
benchmark_id: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: 'rule.benchmark.id',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
benchmark_version: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: 'rule.benchmark.version',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
benchmark_name: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: 'rule.benchmark.name',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
passed_findings_count: {
|
||||
filter: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
term: {
|
||||
'result.evaluation': 'passed',
|
||||
},
|
||||
},
|
||||
],
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
failed_findings_count: {
|
||||
filter: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
term: {
|
||||
'result.evaluation': 'failed',
|
||||
},
|
||||
},
|
||||
],
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
// KSPM QUERY FIELDS
|
||||
kubernetes_version: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: 'cloudbeat.kubernetes.version',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
resources: {
|
||||
filter: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
term: {
|
||||
'resource.sub_type': 'Pod',
|
||||
},
|
||||
},
|
||||
],
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
pods_count: {
|
||||
cardinality: {
|
||||
field: 'resource.id',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nodes_count: {
|
||||
cardinality: {
|
||||
field: 'host.name',
|
||||
},
|
||||
},
|
||||
agents_count: {
|
||||
cardinality: {
|
||||
field: 'agent.id',
|
||||
},
|
||||
},
|
||||
package_policy_id: {
|
||||
terms: {
|
||||
field: 'package_policy_identifier',
|
||||
order: {
|
||||
_count: 'desc',
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
size: 0,
|
||||
_source: false,
|
||||
});
|
||||
|
||||
export const getVulnMgmtAccountsStatsQuery = (index: string): SearchRequest => ({
|
||||
index,
|
||||
runtime_mappings: getPackagePolicyIdRuntimeMapping(),
|
||||
query: {
|
||||
match_all: {},
|
||||
},
|
||||
aggs: {
|
||||
accounts: {
|
||||
terms: {
|
||||
field: 'cloud.account.id',
|
||||
order: {
|
||||
_count: 'desc',
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
aggs: {
|
||||
latest_doc_updated_timestamp: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: '@timestamp',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
cloud_provider: {
|
||||
top_metrics: {
|
||||
metrics: {
|
||||
field: 'cloud.provider',
|
||||
},
|
||||
size: 1,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
package_policy_id: {
|
||||
terms: {
|
||||
field: 'package_policy_identifier',
|
||||
order: {
|
||||
_count: 'desc',
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
size: 0,
|
||||
_source: false,
|
||||
});
|
||||
|
||||
const cloudBaseStats = (account: AccountEntity) => ({
|
||||
account_id: account.key,
|
||||
latest_doc_count: account.doc_count,
|
||||
latest_doc_updated_timestamp: account.latest_doc_updated_timestamp.top[0].metrics['@timestamp'],
|
||||
cloud_provider: account.cloud_provider.top[0].metrics['cloud.provider'],
|
||||
package_policy_id: account.package_policy_id?.buckets[0]?.key ?? null,
|
||||
});
|
||||
|
||||
const getPostureManagementStats = (account: AccountEntity) => ({
|
||||
posture_management_stats: {
|
||||
posture_score: calculatePostureScore(
|
||||
account.passed_findings_count.doc_count,
|
||||
account.failed_findings_count.doc_count
|
||||
),
|
||||
passed_findings_count: account.passed_findings_count.doc_count,
|
||||
failed_findings_count: account.failed_findings_count.doc_count,
|
||||
benchmark_name: account.benchmark_name.top[0].metrics['rule.benchmark.name'],
|
||||
benchmark_version: account.benchmark_version.top[0].metrics['rule.benchmark.version'],
|
||||
},
|
||||
});
|
||||
|
||||
const getKspmStats = (account: AccountEntity) => ({
|
||||
kspm_stats: {
|
||||
kubernetes_version: account.kubernetes_version.top[0].metrics['cloudbeat.kubernetes.version'],
|
||||
agents_count: account.agents_count.value,
|
||||
nodes_count: account.nodes_count.value,
|
||||
pods_count: account.resources.pods_count.value,
|
||||
},
|
||||
});
|
||||
|
||||
const kspmCloudProviders: Record<CloudProviderKey, string | null> = {
|
||||
cis_eks: 'aws',
|
||||
cis_gke: 'gcp',
|
||||
cis_k8s: null,
|
||||
cis_ake: 'azure',
|
||||
};
|
||||
const cspmBenchmarkIds = ['cis_aws', 'cis_azure', 'cis_gcp'];
|
||||
const kspmBenchmarkIds = ['cis_eks', 'cis_ake', 'cis_gke', 'cis_k8s'];
|
||||
|
||||
const getCloudProvider = (ruleBenchmarkId: CloudProviderKey) => {
|
||||
return kspmCloudProviders[ruleBenchmarkId];
|
||||
};
|
||||
|
||||
const getPostureType = (ruleBenchmarkId: string) => {
|
||||
if (cspmBenchmarkIds.includes(ruleBenchmarkId)) {
|
||||
return CSPM_POLICY_TEMPLATE;
|
||||
} else if (kspmBenchmarkIds.includes(ruleBenchmarkId)) {
|
||||
return KSPM_POLICY_TEMPLATE;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getCloudAccountsStats = (
|
||||
aggregatedResourcesStats: AccountsStats,
|
||||
logger: Logger
|
||||
): CloudSecurityAccountsStats[] => {
|
||||
const accounts = aggregatedResourcesStats.accounts.buckets;
|
||||
|
||||
const cloudAccountsStats = accounts.map((account) => {
|
||||
const cloudAccount = cloudBaseStats(account);
|
||||
const postureType = getPostureType(
|
||||
account.benchmark_id?.top?.[0]?.metrics['rule.benchmark.id']
|
||||
);
|
||||
|
||||
if (!postureType) {
|
||||
return {
|
||||
...cloudAccount,
|
||||
product: VULN_MGMT_POLICY_TEMPLATE,
|
||||
};
|
||||
}
|
||||
|
||||
if (postureType === CSPM_POLICY_TEMPLATE) {
|
||||
return {
|
||||
...cloudAccount,
|
||||
product: CSPM_POLICY_TEMPLATE,
|
||||
...getPostureManagementStats(account),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...cloudAccount,
|
||||
product: KSPM_POLICY_TEMPLATE,
|
||||
...getPostureManagementStats(account),
|
||||
...getKspmStats(account),
|
||||
cloud_provider: getCloudProvider(
|
||||
account.benchmark_id.top[0].metrics['rule.benchmark.id'] as CloudProviderKey
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
logger.info('Cloud Account Stats telemetry: accounts stats was sent');
|
||||
|
||||
return cloudAccountsStats;
|
||||
};
|
||||
|
||||
export const getIndexAccountStats = async (
|
||||
esClient: ElasticsearchClient,
|
||||
logger: Logger,
|
||||
index: string,
|
||||
getAccountQuery: (index: string) => SearchRequest
|
||||
) => {
|
||||
const accountsStatsResponse = await esClient.search<unknown, AccountsStats>(
|
||||
getAccountQuery(index)
|
||||
);
|
||||
|
||||
return accountsStatsResponse.aggregations
|
||||
? getCloudAccountsStats(accountsStatsResponse.aggregations, logger)
|
||||
: [];
|
||||
};
|
||||
|
||||
export const getAllCloudAccountsStats = async (
|
||||
esClient: ElasticsearchClient,
|
||||
logger: Logger
|
||||
): Promise<CloudSecurityAccountsStats[]> => {
|
||||
try {
|
||||
const indices = [LATEST_FINDINGS_INDEX_DEFAULT_NS, LATEST_VULNERABILITIES_INDEX_DEFAULT_NS];
|
||||
const [findingIndex, vulnerabilitiesIndex] = await Promise.all(
|
||||
indices.map(async (index) => ({
|
||||
exists: await esClient.indices.exists({
|
||||
index,
|
||||
}),
|
||||
name: index,
|
||||
}))
|
||||
);
|
||||
|
||||
let postureIndexAccountStats: CloudSecurityAccountsStats[] = [];
|
||||
let vulnerabilityIndexAccountStats: CloudSecurityAccountsStats[] = [];
|
||||
|
||||
if (!findingIndex.exists && !vulnerabilitiesIndex.exists) return [];
|
||||
if (findingIndex.exists) {
|
||||
postureIndexAccountStats = await getIndexAccountStats(
|
||||
esClient,
|
||||
logger,
|
||||
findingIndex.name,
|
||||
getPostureAccountsStatsQuery
|
||||
);
|
||||
}
|
||||
|
||||
if (vulnerabilitiesIndex.exists) {
|
||||
vulnerabilityIndexAccountStats = await getIndexAccountStats(
|
||||
esClient,
|
||||
logger,
|
||||
vulnerabilitiesIndex.name,
|
||||
getVulnMgmtAccountsStatsQuery
|
||||
);
|
||||
}
|
||||
|
||||
return [...postureIndexAccountStats, ...vulnerabilityIndexAccountStats];
|
||||
} catch (e) {
|
||||
logger.error(`Failed to get cloud account stats v2 ${e}`);
|
||||
logger.error(`Failed to get cloud account stats v2 ${e.stack}`);
|
||||
return [];
|
||||
}
|
||||
};
|
|
@ -13,15 +13,69 @@ import {
|
|||
SO_SEARCH_LIMIT,
|
||||
} from '@kbn/fleet-plugin/common';
|
||||
import { agentPolicyService } from '@kbn/fleet-plugin/server/services';
|
||||
import type { CloudSecurityInstallationStats } from './types';
|
||||
import type {
|
||||
CloudbeatConfigKeyType,
|
||||
CloudSecurityInstallationStats,
|
||||
SetupAccessOption,
|
||||
} from './types';
|
||||
import type { CspServerPluginStart, CspServerPluginStartDeps } from '../../../types';
|
||||
import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../../../common/constants';
|
||||
|
||||
interface CredentialMappings {
|
||||
'gcp.credentials.file': 'credentials file';
|
||||
'gcp.credentials.json': 'credentials json';
|
||||
shared_credential_file: 'credentials file';
|
||||
role_arn: 'role';
|
||||
}
|
||||
|
||||
const getEnabledInputStreamVars = (packagePolicy: PackagePolicy) => {
|
||||
const enabledInput = packagePolicy.inputs.find((input) => input.enabled);
|
||||
return enabledInput?.streams[0].vars;
|
||||
};
|
||||
|
||||
const getEnabledIsSetupAutomatic = (packagePolicy: PackagePolicy) => {
|
||||
const cloudbeatConfig: Record<CloudbeatConfigKeyType, string> = {
|
||||
'cloudbeat/cis_aws': 'cloud_formation_template_url',
|
||||
'cloudbeat/vuln_mgmt_aws': 'cloud_formation_template_url',
|
||||
'cloudbeat/cis_gcp': 'cloud_shell_url',
|
||||
'cloudbeat/cis_azure': 'arm_template_url',
|
||||
};
|
||||
|
||||
const enabledInput = packagePolicy.inputs.find((input) => input.enabled);
|
||||
|
||||
if (!enabledInput) return false;
|
||||
|
||||
const configKey = cloudbeatConfig[enabledInput.type as CloudbeatConfigKeyType];
|
||||
|
||||
return !!configKey && !!enabledInput.config?.[configKey]?.value;
|
||||
};
|
||||
|
||||
const getSetupAccessOption = (
|
||||
packagePolicy: PackagePolicy
|
||||
): CloudSecurityInstallationStats['setup_access_option'] => {
|
||||
const inputStreamVars = getEnabledInputStreamVars(packagePolicy);
|
||||
|
||||
if (!inputStreamVars) return null;
|
||||
|
||||
const credentialMappings: Record<string, SetupAccessOption> = {
|
||||
'gcp.credentials.file': 'credentials file',
|
||||
'gcp.credentials.json': 'credentials json',
|
||||
shared_credential_file: 'credentials file',
|
||||
role_arn: 'role',
|
||||
};
|
||||
|
||||
for (const [key, config] of Object.entries(inputStreamVars)) {
|
||||
if (config?.value && credentialMappings[key as keyof CredentialMappings]) {
|
||||
return credentialMappings[key as keyof CredentialMappings];
|
||||
}
|
||||
}
|
||||
|
||||
if (inputStreamVars.session_token) return 'temporary access';
|
||||
if (inputStreamVars.access_key && inputStreamVars.secret_access_key) return 'direct access';
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const getAccountTypeField = (
|
||||
packagePolicy: PackagePolicy
|
||||
): CloudSecurityInstallationStats['account_type'] => {
|
||||
|
@ -47,6 +101,7 @@ const getInstalledPackagePolicies = (
|
|||
const agentCounts =
|
||||
agentPolicies?.find((agentPolicy) => agentPolicy?.id === packagePolicy.policy_id)?.agents ??
|
||||
0;
|
||||
const isSetupAutomatic = getEnabledIsSetupAutomatic(packagePolicy);
|
||||
|
||||
return {
|
||||
package_policy_id: packagePolicy.id,
|
||||
|
@ -57,6 +112,8 @@ const getInstalledPackagePolicies = (
|
|||
agent_policy_id: packagePolicy.policy_id,
|
||||
agent_count: agentCounts,
|
||||
account_type: getAccountTypeField(packagePolicy),
|
||||
is_setup_automatic: isSetupAutomatic,
|
||||
setup_access_option: isSetupAutomatic ? null : getSetupAccessOption(packagePolicy),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
|
@ -16,6 +16,7 @@ import { getAccountsStats } from './accounts_stats_collector';
|
|||
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';
|
||||
|
||||
export function registerCspmUsageCollector(
|
||||
logger: Logger,
|
||||
|
@ -58,6 +59,7 @@ export function registerCspmUsageCollector(
|
|||
rulesStats,
|
||||
installationStats,
|
||||
alertsStats,
|
||||
cloudAccountStats,
|
||||
] = await Promise.all([
|
||||
awaitPromiseSafe('Indices', getIndicesStats(esClient, soClient, coreServices, logger)),
|
||||
awaitPromiseSafe('Accounts', getAccountsStats(esClient, logger)),
|
||||
|
@ -68,6 +70,7 @@ export function registerCspmUsageCollector(
|
|||
getInstallationStats(esClient, soClient, coreServices, logger)
|
||||
),
|
||||
awaitPromiseSafe('Alerts', getAlertsStats(esClient, logger)),
|
||||
awaitPromiseSafe('Cloud Accounts', getAllCloudAccountsStats(esClient, logger)),
|
||||
]);
|
||||
return {
|
||||
indices: indicesStats,
|
||||
|
@ -76,6 +79,7 @@ export function registerCspmUsageCollector(
|
|||
rules_stats: rulesStats,
|
||||
installation_stats: installationStats,
|
||||
alerts_stats: alertsStats,
|
||||
cloud_account_stats: cloudAccountStats,
|
||||
};
|
||||
},
|
||||
schema: cspmUsageSchema,
|
||||
|
|
|
@ -154,6 +154,8 @@ export const cspmUsageSchema: MakeSchemaFrom<CspmUsage> = {
|
|||
created_at: { type: 'date' },
|
||||
agent_count: { type: 'long' },
|
||||
account_type: { type: 'keyword' },
|
||||
is_setup_automatic: { type: 'boolean' },
|
||||
setup_access_option: { type: 'keyword' },
|
||||
},
|
||||
},
|
||||
alerts_stats: {
|
||||
|
@ -167,4 +169,28 @@ export const cspmUsageSchema: MakeSchemaFrom<CspmUsage> = {
|
|||
alerts_acknowledged_count: { type: 'long' },
|
||||
},
|
||||
},
|
||||
cloud_account_stats: {
|
||||
type: 'array',
|
||||
items: {
|
||||
account_id: { type: 'keyword' },
|
||||
cloud_provider: { type: 'keyword' },
|
||||
product: { type: 'keyword' },
|
||||
package_policy_id: { type: 'keyword' },
|
||||
latest_doc_count: { type: 'long' },
|
||||
latest_doc_updated_timestamp: { type: 'date' },
|
||||
posture_management_stats: {
|
||||
posture_score: { type: 'long' },
|
||||
benchmark_name: { type: 'keyword' },
|
||||
benchmark_version: { type: 'keyword' },
|
||||
passed_findings_count: { type: 'long' },
|
||||
failed_findings_count: { type: 'long' },
|
||||
},
|
||||
kspm_stats: {
|
||||
kubernetes_version: { type: 'keyword' },
|
||||
agents_count: { type: 'short' },
|
||||
nodes_count: { type: 'short' },
|
||||
pods_count: { type: 'short' },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AggregationsMultiBucketBase } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { CspStatusCode } from '../../../../common/types';
|
||||
|
||||
export type CloudSecurityUsageCollectorType =
|
||||
|
@ -13,7 +14,15 @@ export type CloudSecurityUsageCollectorType =
|
|||
| 'Resources'
|
||||
| 'Rules'
|
||||
| 'Installation'
|
||||
| 'Alerts';
|
||||
| 'Alerts'
|
||||
| 'Cloud Accounts';
|
||||
|
||||
export type CloudProviderKey = 'cis_eks' | 'cis_gke' | 'cis_k8s' | 'cis_ake';
|
||||
export type CloudbeatConfigKeyType =
|
||||
| 'cloudbeat/cis_aws'
|
||||
| 'cloudbeat/vuln_mgmt_aws'
|
||||
| 'cloudbeat/cis_gcp'
|
||||
| 'cloudbeat/cis_azure';
|
||||
|
||||
export interface CspmUsage {
|
||||
indices: CspmIndicesStats;
|
||||
|
@ -22,6 +31,7 @@ export interface CspmUsage {
|
|||
rules_stats: CspmRulesStats[];
|
||||
installation_stats: CloudSecurityInstallationStats[];
|
||||
alerts_stats: CloudSecurityAlertsStats[];
|
||||
cloud_account_stats: CloudSecurityAccountsStats[];
|
||||
}
|
||||
|
||||
export interface PackageSetupStatus {
|
||||
|
@ -58,6 +68,32 @@ export interface CspmResourcesStats {
|
|||
passed_findings_count: number;
|
||||
failed_findings_count: number;
|
||||
}
|
||||
|
||||
export interface CloudSecurityAccountsStats {
|
||||
account_id: string;
|
||||
product: string;
|
||||
cloud_provider: string | null;
|
||||
package_policy_id: string | null;
|
||||
posture_management_stats?: CloudPostureAccountsStats;
|
||||
kspm_stats?: KSPMAccountsStats;
|
||||
latest_doc_count: number;
|
||||
latest_doc_updated_timestamp: string;
|
||||
}
|
||||
export interface CloudPostureAccountsStats {
|
||||
posture_score: number;
|
||||
benchmark_name: string;
|
||||
benchmark_version: string;
|
||||
passed_findings_count: number;
|
||||
failed_findings_count: number;
|
||||
}
|
||||
|
||||
export interface KSPMAccountsStats {
|
||||
kubernetes_version: string | null;
|
||||
agents_count: number;
|
||||
nodes_count: number;
|
||||
pods_count: number;
|
||||
}
|
||||
|
||||
export interface CspmAccountsStats {
|
||||
account_id: string;
|
||||
posture_score: number;
|
||||
|
@ -65,9 +101,9 @@ export interface CspmAccountsStats {
|
|||
benchmark_id: string;
|
||||
benchmark_name: string;
|
||||
benchmark_version: string;
|
||||
kubernetes_version: string | null;
|
||||
passed_findings_count: number;
|
||||
failed_findings_count: number;
|
||||
kubernetes_version: string | null;
|
||||
agents_count: number;
|
||||
nodes_count: number;
|
||||
pods_count: number;
|
||||
|
@ -87,6 +123,13 @@ export interface CspmRulesStats {
|
|||
failed_findings_count: number;
|
||||
}
|
||||
|
||||
export type SetupAccessOption =
|
||||
| 'temporary access'
|
||||
| 'direct access'
|
||||
| 'role'
|
||||
| 'credentials file'
|
||||
| 'credentials json'
|
||||
| null;
|
||||
export interface CloudSecurityInstallationStats {
|
||||
package_policy_id: string;
|
||||
feature: string;
|
||||
|
@ -95,7 +138,9 @@ export interface CloudSecurityInstallationStats {
|
|||
deployment_mode: string;
|
||||
created_at: string;
|
||||
agent_count: number;
|
||||
is_setup_automatic: boolean;
|
||||
account_type?: 'single-account' | 'organization-account';
|
||||
setup_access_option: SetupAccessOption;
|
||||
}
|
||||
|
||||
export interface CloudSecurityAlertsStats {
|
||||
|
@ -106,3 +151,66 @@ export interface CloudSecurityAlertsStats {
|
|||
alerts_closed_count: number;
|
||||
alerts_acknowledged_count: number;
|
||||
}
|
||||
|
||||
export interface Value {
|
||||
value: number;
|
||||
}
|
||||
export interface BenchmarkName {
|
||||
metrics: { 'rule.benchmark.name': string };
|
||||
}
|
||||
|
||||
export interface BenchmarkVersion {
|
||||
metrics: { 'rule.benchmark.version': string };
|
||||
}
|
||||
|
||||
export interface BenchmarkId {
|
||||
metrics: { 'rule.benchmark.id': string };
|
||||
}
|
||||
|
||||
export interface CloudProvider {
|
||||
metrics: { 'cloud.provider': string };
|
||||
}
|
||||
|
||||
export interface KubernetesVersion {
|
||||
metrics: { 'cloudbeat.kubernetes.version': string };
|
||||
}
|
||||
|
||||
export interface PackagePolicyId {
|
||||
metrics: { 'cloud_security_posture.package_policy.id': string };
|
||||
}
|
||||
|
||||
export interface LatestDocTimestamp {
|
||||
metrics: { '@timestamp': string };
|
||||
}
|
||||
|
||||
export interface AccountsStats {
|
||||
accounts: {
|
||||
buckets: AccountEntity[];
|
||||
};
|
||||
}
|
||||
export interface AccountEntity {
|
||||
key: string; // account_id
|
||||
doc_count: number; // latest findings doc count
|
||||
passed_findings_count: AggregationsMultiBucketBase;
|
||||
failed_findings_count: AggregationsMultiBucketBase;
|
||||
package_policy_id: {
|
||||
doc_count_error_upper_bound: number;
|
||||
sum_other_doc_count: number;
|
||||
buckets: Array<{
|
||||
key: string; // package_policy_id
|
||||
doc_count: number;
|
||||
}>;
|
||||
};
|
||||
cloud_provider: { top: CloudProvider[] };
|
||||
latest_doc_updated_timestamp: { top: LatestDocTimestamp[] };
|
||||
benchmark_id: { top: BenchmarkId[] };
|
||||
benchmark_name: { top: BenchmarkName[] };
|
||||
benchmark_version: { top: BenchmarkVersion[] };
|
||||
kubernetes_version: { top: KubernetesVersion[] };
|
||||
agents_count: Value;
|
||||
nodes_count: Value;
|
||||
pods_count: Value;
|
||||
resources: {
|
||||
pods_count: Value;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7604,6 +7604,12 @@
|
|||
},
|
||||
"account_type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"is_setup_automatic": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"setup_access_option": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7632,6 +7638,66 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cloud_account_stats": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"account_id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"cloud_provider": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"product": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"package_policy_id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"latest_doc_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"latest_doc_updated_timestamp": {
|
||||
"type": "date"
|
||||
},
|
||||
"posture_management_stats": {
|
||||
"properties": {
|
||||
"posture_score": {
|
||||
"type": "long"
|
||||
},
|
||||
"benchmark_name": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"benchmark_version": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"passed_findings_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"failed_findings_count": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kspm_stats": {
|
||||
"properties": {
|
||||
"kubernetes_version": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"agents_count": {
|
||||
"type": "short"
|
||||
},
|
||||
"nodes_count": {
|
||||
"type": "short"
|
||||
},
|
||||
"pods_count": {
|
||||
"type": "short"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue