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] fix index template for serverless #165317

Merged
merged 8 commits into from
Sep 3, 2023
Merged
16 changes: 14 additions & 2 deletions x-pack/plugins/cloud_security_posture/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,25 @@
* 2.0.
*/

import { schema, type TypeOf } from '@kbn/config-schema';
// import { schema, type TypeOf } from '@kbn/config-schema';
// import { type TypeOf } from '@kbn/config-schema';
import type { PluginConfigDescriptor } from '@kbn/core/server';

import { schema, offeringBasedSchema, type TypeOf } from '@kbn/config-schema';

const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),

// Setting only allowed in the Serverless offering
serverless: schema.object({
enabled: offeringBasedSchema({
serverless: schema.literal(true),
options: { defaultValue: schema.contextRef('serverless') },
}),
}),
});
type CloudSecurityPostureConfig = TypeOf<typeof configSchema>;

export type CloudSecurityPostureConfig = TypeOf<typeof configSchema>;

export const config: PluginConfigDescriptor<CloudSecurityPostureConfig> = {
schema: configSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import { errors } from '@elastic/elasticsearch';
import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/types';

import {
BENCHMARK_SCORE_INDEX_DEFAULT_NS,
BENCHMARK_SCORE_INDEX_PATTERN,
Expand All @@ -20,8 +17,23 @@ import { latestFindingsPipelineIngestConfig, scorePipelineIngestConfig } from '.
import { latestIndexConfigs } from './latest_indices';
import { IndexConfig, IndexTemplateParams } from './types';

import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/types';
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import { CloudSecurityPostureConfig } from '../config';

interface IndexTemplateSettings {
index: {
default_pipeline: string;
};
lifecycle?: { name: string };
}

// TODO: Add integration tests
export const initializeCspIndices = async (esClient: ElasticsearchClient, logger: Logger) => {
export const initializeCspIndices = async (
esClient: ElasticsearchClient,
cloudSecurityPostureConfig: CloudSecurityPostureConfig,
logger: Logger
) => {
await Promise.allSettled([
createPipelineIfNotExists(esClient, scorePipelineIngestConfig, logger),
createPipelineIfNotExists(esClient, latestFindingsPipelineIngestConfig, logger),
Expand All @@ -32,9 +44,14 @@ export const initializeCspIndices = async (esClient: ElasticsearchClient, logger
createVulnerabilitiesLatestIndexPromise,
createBenchmarkScoreIndexPromise,
] = await Promise.allSettled([
createLatestIndex(esClient, logger, latestIndexConfigs.findings),
createLatestIndex(esClient, logger, latestIndexConfigs.vulnerabilities),
createBenchmarkScoreIndex(esClient, logger),
createLatestIndex(esClient, latestIndexConfigs.findings, cloudSecurityPostureConfig, logger),
createLatestIndex(
esClient,
latestIndexConfigs.vulnerabilities,
cloudSecurityPostureConfig,
logger
),
createBenchmarkScoreIndex(esClient, cloudSecurityPostureConfig, logger),
]);

if (createFindingsLatestIndexPromise.status === 'rejected') {
Expand All @@ -48,25 +65,31 @@ export const initializeCspIndices = async (esClient: ElasticsearchClient, logger
}
};

const createBenchmarkScoreIndex = async (esClient: ElasticsearchClient, logger: Logger) => {
const createBenchmarkScoreIndex = async (
esClient: ElasticsearchClient,
cloudSecurityPostureConfig: CloudSecurityPostureConfig,
logger: Logger
) => {
try {
// Deletes old assets from previous versions as part of upgrade process
const INDEX_TEMPLATE_V830 = 'cloud_security_posture.scores';
await deleteIndexTemplateSafe(esClient, logger, INDEX_TEMPLATE_V830);

const settings: IndexTemplateSettings = {
index: {
default_pipeline: latestFindingsPipelineIngestConfig.id,
},
lifecycle: { name: '' },
};
if (cloudSecurityPostureConfig.serverless.enabled) delete settings.lifecycle;

// We always want to keep the index template updated
await esClient.indices.putIndexTemplate({
name: BENCHMARK_SCORE_INDEX_TEMPLATE_NAME,
index_patterns: BENCHMARK_SCORE_INDEX_PATTERN,
template: {
mappings: benchmarkScoreMapping,
settings: {
default_pipeline: scorePipelineIngestConfig.id,
// TODO: once we will convert the score index to datastream we will no longer override the ilm to be empty
lifecycle: {
name: '',
},
},
settings,
},
_meta: {
package: {
Expand Down Expand Up @@ -98,8 +121,9 @@ const createBenchmarkScoreIndex = async (esClient: ElasticsearchClient, logger:

const createLatestIndex = async (
esClient: ElasticsearchClient,
logger: Logger,
indexConfig: IndexConfig
indexConfig: IndexConfig,
cloudSecurityPostureConfig: CloudSecurityPostureConfig,
logger: Logger
) => {
const { indexName, indexPattern, indexTemplateName, indexDefaultName } = indexConfig;
try {
Expand All @@ -121,7 +145,7 @@ const createLatestIndex = async (
};

// We always want to keep the index template updated
await updateIndexTemplate(esClient, logger, indexTemplateParams);
await updateIndexTemplate(esClient, indexTemplateParams, cloudSecurityPostureConfig, logger);

const result = await createIndexSafe(esClient, logger, indexDefaultName);

Expand Down Expand Up @@ -173,6 +197,7 @@ const createIndexSafe = async (esClient: ElasticsearchClient, logger: Logger, in
});

if (!isLatestIndexExists) {
// esClient.indices.createDataStream
await esClient.indices.create({
index,
});
Expand All @@ -192,29 +217,35 @@ const createIndexSafe = async (esClient: ElasticsearchClient, logger: Logger, in

const updateIndexTemplate = async (
esClient: ElasticsearchClient,
logger: Logger,
indexTemplateParams: IndexTemplateParams
indexTemplateParams: IndexTemplateParams,
cloudSecurityPostureConfig: CloudSecurityPostureConfig,
logger: Logger
) => {
const { indexTemplateName, indexPattern, template, composedOf, _meta } = indexTemplateParams;

const settings: IndexTemplateSettings = {
...template?.settings, // nothing inside
index: {
default_pipeline: latestFindingsPipelineIngestConfig.id,
},
lifecycle: { name: '' },
};
if (cloudSecurityPostureConfig.serverless.enabled) delete settings.lifecycle;

try {
await esClient.indices.putIndexTemplate({
name: indexTemplateName,
index_patterns: indexPattern,
priority: 500,
template: {
mappings: template?.mappings,
settings: {
...template?.settings,
default_pipeline: latestFindingsPipelineIngestConfig.id,
lifecycle: {
name: '',
},
},
settings,
aliases: template?.aliases,
},
_meta,
composed_of: composedOf,
});

logger.info(`Updated index template successfully [Name: ${indexTemplateName}]`);
} catch (e) {
logger.error(`Failed to update index template [Name: ${indexTemplateName}]`);
Expand Down
7 changes: 5 additions & 2 deletions x-pack/plugins/cloud_security_posture/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
setupFindingsStatsTask,
} from './tasks/findings_stats_task';
import { registerCspmUsageCollector } from './lib/telemetry/collectors/register';
import { CloudSecurityPostureConfig } from './config';

export class CspPlugin
implements
Expand All @@ -60,6 +61,7 @@ export class CspPlugin
>
{
private readonly logger: Logger;
private readonly config: CloudSecurityPostureConfig;
private isCloudEnabled?: boolean;

/**
Expand All @@ -69,8 +71,9 @@ export class CspPlugin
*/
#isInitialized: boolean = false;

constructor(initializerContext: PluginInitializerContext) {
constructor(initializerContext: PluginInitializerContext<CloudSecurityPostureConfig>) {
this.logger = initializerContext.logger.get();
this.config = initializerContext.config.get();
}

public setup(
Expand Down Expand Up @@ -203,7 +206,7 @@ export class CspPlugin
async initialize(core: CoreStart, taskManager: TaskManagerStartContract): Promise<void> {
this.logger.debug('initialize');
const esClient = core.elasticsearch.client.asInternalUser;
await initializeCspIndices(esClient, this.logger);
await initializeCspIndices(esClient, this.config, this.logger);
await initializeCspTransforms(esClient, this.logger);
await scheduleFindingsStatsTask(taskManager, this.logger);
this.#isInitialized = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { cloudSecurityMetringCallback } from './cloud_security_metering';
import type { MetringTaskProperties } from '../types';

const TASK_INTERVAL = 3600; // 1 hour
const TASK_INTERVAL = 120; // 1 hour
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for debugging only - will remove before merge

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CohenIdo Are you going to change the TASK_INTERVAL back to 3600?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep:)


export const cloudSecurityMetringTaskProperties: MetringTaskProperties = {
taskType: 'cloud-security-usage-reporting-task',
Expand Down