[D4C] Dataview creation code added. also added a test for plugin (#154688)

## Summary

Adds handling for dataview creation in all spaces when integration is
added.

Related: https://github.com/elastic/integrations/pull/5836/files

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Karl Godard 2023-04-10 16:50:52 -07:00 committed by GitHub
parent 575397b48b
commit 2e75a02032
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 272 additions and 4 deletions

View file

@ -18,7 +18,12 @@ import type {
PackagePolicy,
} from '@kbn/fleet-plugin/common';
import { errors } from '@elastic/elasticsearch';
import { INPUT_CONTROL, CLOUD_DEFEND_FLEET_PACKAGE_KUERY } from '../../common/constants';
import { DataViewSavedObjectAttrs } from '@kbn/data-views-plugin/common';
import {
INPUT_CONTROL,
CLOUD_DEFEND_FLEET_PACKAGE_KUERY,
INTEGRATION_PACKAGE_NAME,
} from '../../common/constants';
import { POLICIES_PACKAGE_POLICY_PREFIX, PoliciesQueryParams } from '../../common/schemas/policy';
export const PACKAGE_POLICY_SAVED_OBJECT_TYPE = 'ingest-package-policies';
@ -66,6 +71,28 @@ export const getAgentStatusesByAgentPolicies = async (
return result;
};
export const onPackagePolicyPostCreateCallback = async (
logger: Logger,
packagePolicy: PackagePolicy,
savedObjectsClient: SavedObjectsClientContract
): Promise<void> => {
return addDataViewToAllSpaces(savedObjectsClient);
};
async function addDataViewToAllSpaces(savedObjectsClient: SavedObjectsClientContract) {
const cloudDefendDataViews = await savedObjectsClient.find<DataViewSavedObjectAttrs>({
type: 'index-pattern',
fields: ['title'],
search: INTEGRATION_PACKAGE_NAME + '*',
searchFields: ['title'],
perPage: 100,
});
cloudDefendDataViews.saved_objects.forEach((dataView) => {
savedObjectsClient.updateObjectsSpaces([{ id: dataView.id, type: 'index-pattern' }], ['*'], []);
});
}
export const getCloudDefendAgentPolicies = async (
soClient: SavedObjectsClientContract,
packagePolicies: PackagePolicy[],

View file

@ -0,0 +1,215 @@
/*
* 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 {
coreMock,
elasticsearchServiceMock,
httpServerMock,
savedObjectsClientMock,
} from '@kbn/core/server/mocks';
import {
createPackagePolicyServiceMock,
createArtifactsClientMock,
createMockPackageService,
createMockAgentService,
createMockAgentPolicyService,
} from '@kbn/fleet-plugin/server/mocks';
import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks';
import { dataPluginMock } from '@kbn/data-plugin/server/mocks';
import { CloudDefendPlugin } from './plugin';
import { CloudDefendPluginStartDeps } from './types';
import { createFleetAuthzMock } from '@kbn/fleet-plugin/common/mocks';
import { PackagePolicy, UpdatePackagePolicy } from '@kbn/fleet-plugin/common';
import {
ExternalCallback,
FleetStartContract,
PostPackagePolicyPostCreateCallback,
} from '@kbn/fleet-plugin/server';
import { INTEGRATION_PACKAGE_NAME } from '../common/constants';
import Chance from 'chance';
import type { AwaitedProperties } from '@kbn/utility-types';
import type { DeeplyMockedKeys } from '@kbn/utility-types-jest';
import {
ElasticsearchClient,
RequestHandlerContext,
SavedObjectsClientContract,
} from '@kbn/core/server';
import { securityMock } from '@kbn/security-plugin/server/mocks';
import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
import * as onPackagePolicyPostCreateCallback from './lib/fleet_util';
const chance = new Chance();
const mockRouteContext = {
core: coreMock.createRequestHandlerContext(),
} as unknown as AwaitedProperties<RequestHandlerContext>;
const createMockFleetStartContract = (): DeeplyMockedKeys<FleetStartContract> => {
return {
authz: {
fromRequest: jest.fn(async (_) => createFleetAuthzMock()),
},
fleetSetupCompleted: jest.fn().mockResolvedValue(undefined),
esIndexPatternService: {
getESIndexPattern: jest.fn().mockResolvedValue(undefined),
},
// @ts-expect-error 2322
agentService: createMockAgentService(),
// @ts-expect-error 2322
packageService: createMockPackageService(),
agentPolicyService: createMockAgentPolicyService(),
registerExternalCallback: jest.fn((..._: ExternalCallback) => {}),
packagePolicyService: createPackagePolicyServiceMock(),
createArtifactsClient: jest.fn().mockReturnValue(createArtifactsClientMock()),
};
};
describe('Cloud Defend Plugin', () => {
describe('start()', () => {
const fleetMock = createMockFleetStartContract();
const mockPlugins: CloudDefendPluginStartDeps = {
fleet: fleetMock,
data: dataPluginMock.createStartContract(),
security: securityMock.createStart(),
licensing: licensingMock.createStart(),
};
const contextMock = coreMock.createCustomRequestHandlerContext(mockRouteContext);
let plugin: CloudDefendPlugin;
beforeEach(() => jest.clearAllMocks());
it('should initialize when new package is created', async () => {
const soClient = savedObjectsClientMock.create();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
const onPackagePolicyPostCreateCallbackSpy = jest
.spyOn(onPackagePolicyPostCreateCallback, 'onPackagePolicyPostCreateCallback')
.mockResolvedValue();
const packageMock = createPackagePolicyMock();
packageMock.package!.name = INTEGRATION_PACKAGE_NAME;
const packagePolicyPostCreateCallbacks: PostPackagePolicyPostCreateCallback[] = [];
fleetMock.registerExternalCallback.mockImplementation((...args) => {
if (args[0] === 'packagePolicyPostCreate') {
packagePolicyPostCreateCallbacks.push(args[1]);
}
});
const context = coreMock.createPluginInitializerContext<unknown>();
plugin = new CloudDefendPlugin(context);
// Act
plugin.start(coreMock.createStart(), mockPlugins);
await mockPlugins.fleet.fleetSetupCompleted();
// Assert
expect(onPackagePolicyPostCreateCallbackSpy).not.toHaveBeenCalled();
expect(packagePolicyPostCreateCallbacks.length).toBeGreaterThan(0);
for (const cb of packagePolicyPostCreateCallbacks) {
await cb(
packageMock,
soClient,
esClient,
contextMock,
httpServerMock.createKibanaRequest()
);
}
expect(onPackagePolicyPostCreateCallbackSpy).toHaveBeenCalled();
});
it('should not initialize when other package is created', async () => {
const soClient = savedObjectsClientMock.create();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
const packageMock = createPackagePolicyMock();
packageMock.package!.name = chance.word();
const packagePolicyPostCreateCallbacks: PostPackagePolicyPostCreateCallback[] = [];
fleetMock.registerExternalCallback.mockImplementation((...args) => {
if (args[0] === 'packagePolicyPostCreate') {
packagePolicyPostCreateCallbacks.push(args[1]);
}
});
const context = coreMock.createPluginInitializerContext<unknown>();
plugin = new CloudDefendPlugin(context);
// Act
plugin.start(coreMock.createStart(), mockPlugins);
await mockPlugins.fleet.fleetSetupCompleted();
// Assert
expect(packagePolicyPostCreateCallbacks.length).toBeGreaterThan(0);
for (const cb of packagePolicyPostCreateCallbacks) {
await cb(
packageMock,
soClient,
esClient,
contextMock,
httpServerMock.createKibanaRequest()
);
}
});
it('packagePolicyPostCreate should return the same received policy', async () => {
fleetMock.packagePolicyService.update.mockImplementation(
(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,
id: string,
packagePolicyUpdate: UpdatePackagePolicy
): Promise<PackagePolicy> => {
// @ts-expect-error 2322
return packagePolicyUpdate;
}
);
const packageMock = createPackagePolicyMock();
packageMock.package!.name = INTEGRATION_PACKAGE_NAME;
packageMock.vars = { runtimeCfg: { type: 'foo' } };
const packagePolicyPostCreateCallbacks: PostPackagePolicyPostCreateCallback[] = [];
fleetMock.registerExternalCallback.mockImplementation((...args) => {
if (args[0] === 'packagePolicyPostCreate') {
packagePolicyPostCreateCallbacks.push(args[1]);
}
});
const context = coreMock.createPluginInitializerContext<unknown>();
plugin = new CloudDefendPlugin(context);
// Act
plugin.start(coreMock.createStart(), mockPlugins);
await mockPlugins.fleet.fleetSetupCompleted();
expect(packagePolicyPostCreateCallbacks.length).toBeGreaterThan(0);
const soClient = savedObjectsClientMock.create();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
for (const cb of packagePolicyPostCreateCallbacks) {
const updatedPackagePolicy = await cb(
packageMock,
soClient,
esClient,
contextMock,
httpServerMock.createKibanaRequest()
);
expect(updatedPackagePolicy).toEqual(packageMock);
}
expect(fleetMock.packagePolicyService.update).toHaveBeenCalledTimes(0);
});
});
});

View file

@ -4,8 +4,15 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server';
import type { NewPackagePolicy } from '@kbn/fleet-plugin/common';
import {
PluginInitializerContext,
CoreSetup,
CoreStart,
Plugin,
Logger,
SavedObjectsClientContract,
} from '@kbn/core/server';
import type { PackagePolicy, NewPackagePolicy } from '@kbn/fleet-plugin/common';
import {
CloudDefendPluginSetup,
CloudDefendPluginStart,
@ -15,6 +22,7 @@ import {
import { setupRoutes } from './routes/setup_routes';
import { isCloudDefendPackage } from '../common/utils/helpers';
import { isSubscriptionAllowed } from '../common/utils/subscription';
import { onPackagePolicyPostCreateCallback } from './lib/fleet_util';
export class CloudDefendPlugin implements Plugin<CloudDefendPluginSetup, CloudDefendPluginStart> {
private readonly logger: Logger;
@ -61,6 +69,21 @@ export class CloudDefendPlugin implements Plugin<CloudDefendPluginSetup, CloudDe
);
});
plugins.fleet.registerExternalCallback(
'packagePolicyPostCreate',
async (
packagePolicy: PackagePolicy,
soClient: SavedObjectsClientContract
): Promise<PackagePolicy> => {
if (isCloudDefendPackage(packagePolicy.package?.name)) {
await onPackagePolicyPostCreateCallback(this.logger, packagePolicy, soClient);
return packagePolicy;
}
return packagePolicy;
}
);
return {};
}

View file

@ -29,7 +29,10 @@
"@kbn/shared-ux-link-redirect-app",
"@kbn/core-logging-server-mocks",
"@kbn/securitysolution-es-utils",
"@kbn/es-types"
"@kbn/es-types",
"@kbn/data-views-plugin",
"@kbn/utility-types",
"@kbn/utility-types-jest"
],
"exclude": ["target/**/*"]
}