Skip to content

Commit

Permalink
Deprecate Cloud Defend billing logic
Browse files Browse the repository at this point in the history
  • Loading branch information
CohenIdo authored and JoseLuisGJ committed Dec 19, 2024
1 parent 5501349 commit 7cbffc9
Show file tree
Hide file tree
Showing 8 changed files with 10 additions and 428 deletions.
2 changes: 1 addition & 1 deletion config/serverless.security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ xpack.fleet.internal.registry.excludePackages: [
'dga',

# Unsupported in serverless
'cloud-defend',
'cloud_defend',
]
# fleet_server package installed to publish agent metrics
xpack.fleet.packages:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
import type { Logger } from '@kbn/core/server';
import { ProductLine } from '../../common/product';
import { getCloudSecurityUsageRecord } from './cloud_security_metering_task';
import { CLOUD_DEFEND, CNVM, CSPM, KSPM } from './constants';
import { CNVM, CSPM, KSPM } from './constants';
import type { CloudSecuritySolutions } from './types';
import type { MeteringCallBackResponse, MeteringCallbackInput, Tier, UsageRecord } from '../types';
import type { ServerlessSecurityConfig } from '../config';
import { getCloudDefendUsageRecords } from './defend_for_containers_metering';

export const cloudSecurityMetringCallback = async ({
esClient,
Expand All @@ -35,24 +34,11 @@ export const cloudSecurityMetringCallback = async ({
const tier: Tier = getCloudProductTier(config, logger);

try {
const cloudSecuritySolutions: CloudSecuritySolutions[] = [CSPM, KSPM, CNVM, CLOUD_DEFEND];
const cloudSecuritySolutions: CloudSecuritySolutions[] = [CSPM, KSPM, CNVM];

const promiseResults = await Promise.allSettled(
cloudSecuritySolutions.map((cloudSecuritySolution) => {
if (cloudSecuritySolution !== CLOUD_DEFEND) {
return getCloudSecurityUsageRecord({
esClient,
projectId,
logger,
taskId,
lastSuccessfulReport,
cloudSecuritySolution,
tier,
});
}

// since lastSuccessfulReport is not used by getCloudSecurityUsageRecord, we want to verify if it is used by getCloudDefendUsageRecords before getCloudSecurityUsageRecord.
return getCloudDefendUsageRecords({
return getCloudSecurityUsageRecord({
esClient,
projectId,
logger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,7 @@ import {
import type { ServerlessSecurityConfig } from '../config';

import type { ProductTier } from '../../common/product';
import {
CLOUD_SECURITY_TASK_TYPE,
CSPM,
KSPM,
CNVM,
CLOUD_DEFEND,
BILLABLE_ASSETS_CONFIG,
} from './constants';
import { getCloudDefendUsageRecords } from './defend_for_containers_metering';
import { CLOUD_SECURITY_TASK_TYPE, CSPM, KSPM, CNVM, BILLABLE_ASSETS_CONFIG } from './constants';

const mockEsClient = elasticsearchServiceMock.createStart().client.asInternalUser;
const logger: ReturnType<typeof loggingSystemMock.createLogger> = loggingSystemMock.createLogger();
Expand Down Expand Up @@ -336,173 +328,3 @@ describe('should return the relevant product tier', () => {
expect(tier).toBe('none');
});
});

describe('cloud defend metering', () => {
it('should return usageRecords with correct values', async () => {
const cloudSecuritySolution = 'cloud_defend';
const agentId1 = chance.guid();
const eventIngestedStr = '2024-05-28T12:10:51Z';
const eventIngestedTimestamp = new Date(eventIngestedStr);

// @ts-ignore
mockEsClient.search.mockResolvedValueOnce({
hits: {
hits: [
{
_id: 'someRecord',
_index: 'mockIndex',
_source: {
'cloud_defend.block_action_enabled': true,
'agent.id': agentId1,
event: {
ingested: eventIngestedStr,
},
},
},
],
},
});

const projectId = chance.guid();
const taskId = chance.guid();

const tier = 'essentials' as ProductTier;

const result = await getCloudDefendUsageRecords({
esClient: mockEsClient,
projectId,
taskId,
lastSuccessfulReport: new Date(),
cloudSecuritySolution,
logger,
tier,
});

const roundedIngestedTimestamp = eventIngestedTimestamp;
roundedIngestedTimestamp.setMinutes(0);
roundedIngestedTimestamp.setSeconds(0);
roundedIngestedTimestamp.setMilliseconds(0);

expect(result).toEqual([
{
id: expect.stringContaining(
`${projectId}_${agentId1}_${roundedIngestedTimestamp.toISOString()}`
),
usage_timestamp: eventIngestedStr,
creation_timestamp: expect.any(String),
usage: {
type: CLOUD_SECURITY_TASK_TYPE,
sub_type: CLOUD_DEFEND,
quantity: 1,
period_seconds: 3600,
},
source: {
id: taskId,
instance_group_id: projectId,
metadata: {
tier: 'essentials',
},
},
},
]);
});

it('should return an empty array when Elasticsearch returns an empty response', async () => {
// @ts-ignore
mockEsClient.search.mockResolvedValueOnce({
hits: {
hits: [],
},
});
const tier = 'essentials' as ProductTier;
// Call the function with mock parameters
const result = await getCloudDefendUsageRecords({
esClient: mockEsClient,
projectId: chance.guid(),
taskId: chance.guid(),
lastSuccessfulReport: new Date(),
cloudSecuritySolution: 'cloud_defend',
logger,
tier,
});

// Assert that the result is an empty array
expect(result).toEqual([]);
});

it('should handle errors from Elasticsearch', async () => {
// Mock Elasticsearch client's search method to throw an error
mockEsClient.search.mockRejectedValueOnce(new Error('Elasticsearch query failed'));

const tier = 'essentials' as ProductTier;

// Call the function with mock parameters
await getCloudDefendUsageRecords({
esClient: mockEsClient,
projectId: chance.guid(),
taskId: chance.guid(),
lastSuccessfulReport: new Date(),
cloudSecuritySolution: 'cloud_defend',
logger,
tier,
});

// Assert that the logger's error method was called with the correct error message
expect(logger.error).toHaveBeenCalledWith(
'Failed to fetch cloud_defend metering data Error: Elasticsearch query failed'
);
});

it('should return usageRecords when Elasticsearch returns multiple records', async () => {
// Mock Elasticsearch response with multiple records
const agentId1 = chance.guid();
const agentId2 = chance.guid();
const eventIngestedStr1 = '2024-05-28T12:10:51Z';
const eventIngestedStr2 = '2024-05-28T13:10:51Z';

// @ts-ignore
mockEsClient.search.mockResolvedValueOnce({
hits: {
hits: [
{
_id: 'record1',
_index: 'mockIndex',
_source: {
'cloud_defend.block_action_enabled': true,
'agent.id': agentId1,
event: {
ingested: eventIngestedStr1,
},
},
},
{
_id: 'record2',
_index: 'mockIndex',
_source: {
'cloud_defend.block_action_enabled': true,
'agent.id': agentId2,
event: {
ingested: eventIngestedStr2,
},
},
},
],
},
});
const tier = 'essentials' as ProductTier;

// Call the function with mock parameters
const result = await getCloudDefendUsageRecords({
esClient: mockEsClient,
projectId: chance.guid(),
taskId: chance.guid(),
lastSuccessfulReport: new Date(),
cloudSecuritySolution: 'cloud_defend',
logger,
tier,
});

// Assert that the result contains usage records for both records
expect(result).toHaveLength(2);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import {
CDR_LATEST_NATIVE_VULNERABILITIES_INDEX_PATTERN,
} from '@kbn/cloud-security-posture-common';
import { CNVM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-plugin/common/constants';
import { INTEGRATION_PACKAGE_NAME } from '@kbn/cloud-defend-plugin/common/constants';

export const CLOUD_DEFEND_HEARTBEAT_INDEX = 'metrics-cloud_defend.heartbeat-*';
export const CLOUD_SECURITY_TASK_TYPE = 'cloud_security';
export const AGGREGATION_PRECISION_THRESHOLD = 40000;
export const ASSETS_SAMPLE_GRANULARITY = '24h';
Expand All @@ -23,7 +21,6 @@ export const THRESHOLD_MINUTES = 30;
export const CSPM = CSPM_POLICY_TEMPLATE;
export const KSPM = KSPM_POLICY_TEMPLATE;
export const CNVM = CNVM_POLICY_TEMPLATE;
export const CLOUD_DEFEND = INTEGRATION_PACKAGE_NAME;

export const METERING_CONFIGS = {
[CSPM]: {
Expand All @@ -38,10 +35,6 @@ export const METERING_CONFIGS = {
index: CDR_LATEST_NATIVE_VULNERABILITIES_INDEX_PATTERN,
assets_identifier: 'cloud.instance.id',
},
[CLOUD_DEFEND]: {
index: CLOUD_DEFEND_HEARTBEAT_INDEX,
assets_identifier: 'agent.id',
},
};

// see https://github.com/elastic/security-team/issues/8970 for billable asset definition
Expand Down
Loading

0 comments on commit 7cbffc9

Please sign in to comment.