Skip to content

Commit

Permalink
Add agentPolicyPostUpdate extension callback to create indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
paul-tavares committed Oct 23, 2024
1 parent 0544c3e commit a2f207f
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type { ResponseActionsClient } from './services';
import { getResponseActionsClient, NormalizedExternalConnectorClient } from './services';
import {
getAgentPolicyCreateCallback,
getAgentPolicyPostUpdateCallback,
getAgentPolicyUpdateCallback,
getPackagePolicyCreateCallback,
getPackagePolicyDeleteCallback,
Expand Down Expand Up @@ -161,8 +162,6 @@ export class EndpointAppContextService {
const endpointMetadataService = this.getEndpointMetadataService();
const soClient = this.savedObjects.createInternalScopedSoClient({ readonly: false });
const logger = this.createLogger('endpointFleetExtension');
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const fleetServicesFactory = this.fleetServicesFactory!;

registerFleetCallback(
'agentPolicyCreate',
Expand All @@ -173,6 +172,8 @@ export class EndpointAppContextService {
getAgentPolicyUpdateCallback(logger, productFeaturesService)
);

registerFleetCallback('agentPolicyPostUpdate', getAgentPolicyPostUpdateCallback(this));

registerFleetCallback(
'packagePolicyCreate',
getPackagePolicyCreateCallback(
Expand Down Expand Up @@ -234,6 +235,14 @@ export class EndpointAppContextService {
return Boolean(this.setupDependencies.cloud.isServerlessEnabled);
}

public getInternalEsClient(): ElasticsearchClient {
if (!this.startDependencies.esClient) {
throw new EndpointAppContentServicesNotStartedError();
}

return this.startDependencies.esClient;
}

private getFleetAuthzService(): FleetStartContract['authz'] {
if (!this.startDependencies?.fleetStartServices) {
throw new EndpointAppContentServicesNotStartedError();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export const createMockEndpointAppContextService = (
}),
savedObjects: createSavedObjectsClientFactoryMock({ savedObjectsServiceStart }).service,
isServerless: jest.fn().mockReturnValue(false),
getInternalEsClient: jest.fn().mockReturnValue(esClient),
} as unknown as jest.Mocked<EndpointAppContextService>;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ import type { InfoResponse } from '@elastic/elasticsearch/lib/api/types';
import { ProductFeatureSecurityKey } from '@kbn/security-solution-features/keys';
import type {
PostAgentPolicyCreateCallback,
PostAgentPolicyPostUpdateCallback,
PostAgentPolicyUpdateCallback,
PutPackagePolicyPostUpdateCallback,
} from '@kbn/fleet-plugin/server/types';
import type { EndpointInternalFleetServicesInterface } from '../endpoint/services/fleet';
import type { EndpointAppContextService } from '../endpoint/endpoint_app_context_services';
import { createPolicyDataStreamsIfNeeded } from './handlers/create_policy_datastreams';
import { updateAntivirusRegistrationEnabled } from '../../common/endpoint/utils/update_antivirus_registration_enabled';
Expand Down Expand Up @@ -65,6 +67,32 @@ const isEndpointPackagePolicy = <T extends { package?: { name: string } }>(
return packagePolicy.package?.name === 'endpoint';
};

const getEndpointPolicyForAgentPolicy = async (
fleetServices: EndpointInternalFleetServicesInterface,
agentPolicy: AgentPolicy
): Promise<PackagePolicy | undefined> => {
let agentPolicyIntegrations: PackagePolicy[] | undefined = agentPolicy.package_policies;

if (!agentPolicyIntegrations) {
const fullAgentPolicy = await fleetServices.agentPolicy.get(
fleetServices.savedObjects.createInternalScopedSoClient(),
agentPolicy.id,
true
);
agentPolicyIntegrations = fullAgentPolicy?.package_policies ?? [];
}

if (Array.isArray(agentPolicyIntegrations)) {
for (const integrationPolicy of agentPolicyIntegrations) {
if (isEndpointPackagePolicy(integrationPolicy)) {
return integrationPolicy;
}
}
}

return undefined;
};

const shouldUpdateMetaValues = (
endpointPackagePolicy: PolicyConfig,
currentLicenseType: string,
Expand Down Expand Up @@ -287,7 +315,7 @@ export const getPackagePolicyPostUpdateCallback = (
): PutPackagePolicyPostUpdateCallback => {
const logger = endpointServices.createLogger('endpointPackagePolicyPostUpdate');

return async (packagePolicy, _, esClient) => {
return async (packagePolicy) => {
if (!isEndpointPackagePolicy(packagePolicy)) {
return packagePolicy;
}
Expand All @@ -297,7 +325,6 @@ export const getPackagePolicyPostUpdateCallback = (
// The check below will run in the background - we don't need to wait for it
createPolicyDataStreamsIfNeeded({
endpointServices,
esClient,
endpointPolicyIds: [packagePolicy.id],
});

Expand All @@ -311,7 +338,7 @@ export const getPackagePolicyPostCreateCallback = (
const logger = endpointServices.createLogger('endpointPolicyPostCreate');
const exceptionsClient = endpointServices.getExceptionListsClient();

return async (packagePolicy: PackagePolicy, _, esClient): Promise<PackagePolicy> => {
return async (packagePolicy: PackagePolicy): Promise<PackagePolicy> => {
// We only care about Endpoint package policies
if (!exceptionsClient || !isEndpointPackagePolicy(packagePolicy)) {
return packagePolicy;
Expand All @@ -321,7 +348,6 @@ export const getPackagePolicyPostCreateCallback = (
// NOTE: we don't need for it to complete here, thus no `await`.
createPolicyDataStreamsIfNeeded({
endpointServices,
esClient,
endpointPolicyIds: [packagePolicy.id],
});

Expand Down Expand Up @@ -389,6 +415,31 @@ export const getAgentPolicyUpdateCallback = (
};
};

export const getAgentPolicyPostUpdateCallback = (
endpointServices: EndpointAppContextService
): PostAgentPolicyPostUpdateCallback => {
const logger = endpointServices.createLogger('endpointPolicyPostUpdate');

return async (agentPolicy) => {
const fleetServices = endpointServices.getInternalFleetServices();
const endpointPolicy = await getEndpointPolicyForAgentPolicy(fleetServices, agentPolicy);

if (!endpointPolicy) {
return agentPolicy;
}

logger.debug(`Processing post-update to Fleet agent policy: [${agentPolicy.id}]`);

// We don't need to `await` for this function to execute. It can be done in the background
createPolicyDataStreamsIfNeeded({
endpointServices,
endpointPolicyIds: [endpointPolicy.id],
});

return agentPolicy;
};
};

export const getPackagePolicyDeleteCallback = (
exceptionsClient: ExceptionListClient | undefined,
savedObjectsClient: SavedObjectsClientContract | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import pMap from 'p-map';
import type { EndpointAppContextService } from '../../endpoint/endpoint_app_context_services';
import { catchAndWrapError } from '../../endpoint/utils';
Expand Down Expand Up @@ -50,7 +49,6 @@ interface PolicyDataStreamsCreator {

export interface CreatePolicyDataStreamsOptions {
endpointServices: EndpointAppContextService;
esClient: ElasticsearchClient;
endpointPolicyIds: string[];
}

Expand All @@ -60,10 +58,10 @@ export interface CreatePolicyDataStreamsOptions {
*/
export const createPolicyDataStreamsIfNeeded: PolicyDataStreamsCreator = async ({
endpointServices,
esClient,
endpointPolicyIds,
}: CreatePolicyDataStreamsOptions): Promise<void> => {
const logger = endpointServices.createLogger('endpointPolicyDatastreamCreator');
const esClient = endpointServices.getInternalEsClient();

logger.debug(
() =>
Expand Down Expand Up @@ -144,6 +142,8 @@ export const createPolicyDataStreamsIfNeeded: PolicyDataStreamsCreator = async (
', '
)}]:\n ${indexesCreated.join('\n ')}`
);
} else if (createErrors.length === 0) {
logger.debug(() => `Nothing to do. Datastreams already exist`);
}

if (createErrors.length > 0) {
Expand Down

0 comments on commit a2f207f

Please sign in to comment.