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

[EDR Workflows][API] Gate Agent Tamper Protection setting on Agent Policy Settings #174400

Merged
merged 24 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
cb3c9b2
upsell on essential
szwarckonrad Jan 5, 2024
db8b0e5
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 15, 2024
dd697bd
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 16, 2024
0c4e21a
upsell on essential
szwarckonrad Jan 16, 2024
65ad15e
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jan 16, 2024
cb5d3c1
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 24, 2024
63ac984
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 25, 2024
77666a8
upsell on essential
szwarckonrad Jan 25, 2024
30f54d0
upsell on essential
szwarckonrad Jan 25, 2024
255b23a
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 25, 2024
03ec056
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 25, 2024
fa11c4b
upsell on essential
szwarckonrad Jan 26, 2024
d01cb0a
Merge remote-tracking branch 'origin/gated-agent-tamper-api' into gat…
szwarckonrad Jan 26, 2024
510c3e0
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 30, 2024
b18a7b4
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jan 30, 2024
14c1f7b
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 31, 2024
63b86df
cr changes
szwarckonrad Jan 31, 2024
b3c6937
cr changes
szwarckonrad Jan 31, 2024
557791f
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Jan 31, 2024
f7c342f
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Feb 1, 2024
06c9bc9
cr changes
szwarckonrad Feb 1, 2024
b63e686
cr changes
szwarckonrad Feb 1, 2024
34c9de8
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Feb 1, 2024
527a332
Merge branch 'main' into gated-agent-tamper-api
szwarckonrad Feb 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ import {
UpdatePackagePolicy,
} from '@kbn/fleet-plugin/common';
import {
ExternalCallback,
FleetStartContract,
PostPackagePolicyPostDeleteCallback,
PostPackagePolicyPostCreateCallback,
ExternalCallback,
} from '@kbn/fleet-plugin/server';
import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../common/constants';
import Chance from 'chance';
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/server/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export const createMockAgentPolicyService = (): jest.Mocked<AgentPolicyServiceIn
list: jest.fn(),
getFullAgentPolicy: jest.fn(),
getByIds: jest.fn(),
bumpRevision: jest.fn(),
};
};

Expand Down
51 changes: 25 additions & 26 deletions x-pack/plugins/fleet/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,32 @@
import { backOff } from 'exponential-backoff';
import type { Observable } from 'rxjs';
import { BehaviorSubject } from 'rxjs';
import { take, filter } from 'rxjs/operators';
import { filter, take } from 'rxjs/operators';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { i18n } from '@kbn/i18n';
import type {
CoreSetup,
CoreStart,
ElasticsearchClient,
ElasticsearchServiceStart,
HttpServiceSetup,
KibanaRequest,
Logger,
Plugin,
PluginInitializerContext,
SavedObjectsClientContract,
SavedObjectsServiceStart,
HttpServiceSetup,
KibanaRequest,
ServiceStatus,
ElasticsearchClient,
SavedObjectsClientContract,
} from '@kbn/core/server';
import { DEFAULT_APP_CATEGORIES, SavedObjectsClient, ServiceStatusLevels } from '@kbn/core/server';
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';

import type { TelemetryPluginSetup, TelemetryPluginStart } from '@kbn/telemetry-plugin/server';

import { DEFAULT_APP_CATEGORIES, SavedObjectsClient, ServiceStatusLevels } from '@kbn/core/server';
import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server';
import type { LicensingPluginStart } from '@kbn/licensing-plugin/server';
import type {
EncryptedSavedObjectsPluginStart,
EncryptedSavedObjectsPluginSetup,
EncryptedSavedObjectsPluginStart,
} from '@kbn/encrypted-saved-objects-plugin/server';
import type {
AuditLogger,
Expand All @@ -57,61 +56,60 @@ import { SECURITY_EXTENSION_ID } from '@kbn/core-saved-objects-server';

import type { FleetConfigType } from '../common/types';
import type { FleetAuthz } from '../common';
import type { ExperimentalFeatures } from '../common/experimental_features';

import {
MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE,
INTEGRATIONS_PLUGIN_ID,
MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE,
UNINSTALL_TOKENS_SAVED_OBJECT_TYPE,
} from '../common';
import type { ExperimentalFeatures } from '../common/experimental_features';
import { parseExperimentalConfigValue } from '../common/experimental_features';

import { getFilesClientFactory } from './services/files/get_files_client_factory';

import type { MessageSigningServiceInterface } from './services/security';
import {
getRouteRequiredAuthz,
makeRouterWithFleetAuthz,
calculateRouteAuthz,
getAuthzFromRequest,
getRouteRequiredAuthz,
makeRouterWithFleetAuthz,
MessageSigningService,
} from './services/security';

import {
PLUGIN_ID,
OUTPUT_SAVED_OBJECT_TYPE,
AGENT_POLICY_SAVED_OBJECT_TYPE,
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
ASSETS_SAVED_OBJECT_TYPE,
PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE,
DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE,
FLEET_SERVER_HOST_SAVED_OBJECT_TYPE,
OUTPUT_SAVED_OBJECT_TYPE,
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
PLUGIN_ID,
PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE,
} from './constants';
import { registerSavedObjects, registerEncryptedSavedObjects } from './saved_objects';
import { registerEncryptedSavedObjects, registerSavedObjects } from './saved_objects';
import { registerRoutes } from './routes';

import type { ExternalCallback, FleetRequestHandlerContext } from './types';
import type {
ESIndexPatternService,
AgentService,
AgentPolicyServiceInterface,
AgentService,
ESIndexPatternService,
PackageService,
} from './services';
import { FleetUsageSender } from './services';
import {
agentPolicyService,
AgentServiceImpl,
appContextService,
licenseService,
ESIndexPatternSavedObjectService,
agentPolicyService,
FleetUsageSender,
licenseService,
packagePolicyService,
AgentServiceImpl,
PackageServiceImpl,
} from './services';
import {
registerFleetUsageCollector,
fetchAgentsUsage,
fetchFleetUsage,
registerFleetUsageCollector,
} from './collectors/register';
import { FleetArtifactsClient } from './services/artifacts';
import type { FleetRouter } from './types/request_context';
Expand Down Expand Up @@ -627,6 +625,7 @@ export class FleetPlugin
list: agentPolicyService.list,
getFullAgentPolicy: agentPolicyService.getFullAgentPolicy,
getByIds: agentPolicyService.getByIDs,
bumpRevision: agentPolicyService.bumpRevision.bind(agentPolicyService),
},
packagePolicyService,
registerExternalCallback: (type: ExternalCallback[0], callback: ExternalCallback[1]) => {
Expand Down
12 changes: 12 additions & 0 deletions x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ export const createAgentPolicyHandler: FleetRequestHandler<
body,
});
} catch (error) {
if (error.statusCode) {
return response.customError({
statusCode: error.statusCode,
body: { message: error.message },
});
}
return defaultFleetErrorHandler({ error, response });
}
};
Expand Down Expand Up @@ -229,6 +235,12 @@ export const updateAgentPolicyHandler: FleetRequestHandler<
body,
});
} catch (error) {
if (error.statusCode) {
return response.customError({
statusCode: error.statusCode,
body: { message: error.message },
});
}
return defaultFleetErrorHandler({ error, response });
}
};
Expand Down
51 changes: 49 additions & 2 deletions x-pack/plugins/fleet/server/services/agent_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ import type {
FullAgentPolicy,
ListWithKuery,
NewPackagePolicy,
PostAgentPolicyCreateCallback,
PostAgentPolicyUpdateCallback,
ExternalCallback,
} from '../types';
import {
getAllowedOutputTypeForPolicy,
Expand Down Expand Up @@ -234,6 +237,43 @@ class AgentPolicyService {
return policyHasSyntheticsIntegration(agentPolicy);
}

public async runExternalCallbacks(
externalCallbackType: ExternalCallback[0],
agentPolicy: NewAgentPolicy | Partial<AgentPolicy>
): Promise<NewAgentPolicy | Partial<AgentPolicy>> {
const logger = appContextService.getLogger();
logger.debug(`Running external callbacks for ${externalCallbackType}`);
try {
const externalCallbacks = appContextService.getExternalCallbacks(externalCallbackType);
let newAgentPolicy = agentPolicy;

if (externalCallbacks && externalCallbacks.size > 0) {
let updatedNewAgentPolicy = newAgentPolicy;
for (const callback of externalCallbacks) {
let result;
if (externalCallbackType === 'agentPolicyCreate') {
result = await (callback as PostAgentPolicyCreateCallback)(
newAgentPolicy as NewAgentPolicy
);
updatedNewAgentPolicy = result;
}
if (externalCallbackType === 'agentPolicyUpdate') {
result = await (callback as PostAgentPolicyUpdateCallback)(
newAgentPolicy as Partial<AgentPolicy>
);
updatedNewAgentPolicy = result;
}
}
newAgentPolicy = updatedNewAgentPolicy;
}
return newAgentPolicy;
} catch (error) {
logger.error(`Error running external callbacks for ${externalCallbackType}`);
logger.error(error);
throw error;
}
}

public async create(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,
Expand All @@ -254,7 +294,7 @@ class AgentPolicyService {
id: options.id,
savedObjectType: AGENT_POLICY_SAVED_OBJECT_TYPE,
});

await this.runExternalCallbacks('agentPolicyCreate', agentPolicy);
this.checkTamperProtectionLicense(agentPolicy);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can be moved to sec sol side to an external callback


const logger = appContextService.getLogger();
Expand Down Expand Up @@ -519,7 +559,14 @@ class AgentPolicyService {
if (!existingAgentPolicy) {
throw new AgentPolicyNotFoundError('Agent policy not found');
}

try {
await this.runExternalCallbacks('agentPolicyUpdate', agentPolicy);
} catch (error) {
logger.error(`Error running external callbacks for agentPolicyUpdate`);
if (error.apiPassThrough) {
throw error;
}
}
this.checkTamperProtectionLicense(agentPolicy);
await this.checkForValidUninstallToken(agentPolicy, id);
Comment on lines 570 to 571
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can be moved to sec sol side to an external callback


Expand Down
14 changes: 12 additions & 2 deletions x-pack/plugins/fleet/server/services/app_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import type {
PostPackagePolicyPostDeleteCallback,
PostPackagePolicyPostCreateCallback,
PutPackagePolicyUpdateCallback,
PostAgentPolicyCreateCallback,
PostAgentPolicyUpdateCallback,
} from '../types';
import type { FleetAppContext } from '../plugin';
import type { TelemetryEventsSender } from '../telemetry/sender';
Expand Down Expand Up @@ -245,7 +247,11 @@ class AppContextService {
type: T
):
| Set<
T extends 'packagePolicyCreate'
T extends 'agentPolicyCreate'
? PostAgentPolicyCreateCallback
: T extends 'agentPolicyUpdate'
? PostAgentPolicyUpdateCallback
: T extends 'packagePolicyCreate'
? PostPackagePolicyCreateCallback
: T extends 'packagePolicyDelete'
? PostPackagePolicyDeleteCallback
Expand All @@ -258,7 +264,11 @@ class AppContextService {
| undefined {
if (this.externalCallbacks) {
return this.externalCallbacks.get(type) as Set<
T extends 'packagePolicyCreate'
T extends 'agentPolicyCreate'
? PostAgentPolicyCreateCallback
: T extends 'agentPolicyUpdate'
? PostAgentPolicyUpdateCallback
: T extends 'packagePolicyCreate'
? PostPackagePolicyCreateCallback
: T extends 'packagePolicyDelete'
? PostPackagePolicyDeleteCallback
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/server/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface AgentPolicyServiceInterface {
list: typeof agentPolicyService['list'];
getFullAgentPolicy: typeof agentPolicyService['getFullAgentPolicy'];
getByIds: typeof agentPolicyService['getByIDs'];
bumpRevision: typeof agentPolicyService['bumpRevision'];
}

// Agent services
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ jest.mock('./app_context', () => ({
getUninstallTokenService: () => ({
generateTokenForPolicyId: jest.fn(),
}),
getExternalCallbacks: jest.fn(),
},
}));

Expand Down
23 changes: 22 additions & 1 deletion x-pack/plugins/fleet/server/types/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import type {
UpdatePackagePolicy,
PackagePolicy,
DeletePackagePoliciesResponse,
NewAgentPolicy,
AgentPolicy,
} from '../../common/types';

export type PostPackagePolicyDeleteCallback = (
Expand Down Expand Up @@ -58,6 +60,14 @@ export type PutPackagePolicyUpdateCallback = (
request?: KibanaRequest
) => Promise<UpdatePackagePolicy>;

export type PostAgentPolicyCreateCallback = (
agentPolicy: NewAgentPolicy
) => Promise<NewAgentPolicy>;

export type PostAgentPolicyUpdateCallback = (
agentPolicy: Partial<AgentPolicy>
) => Promise<Partial<AgentPolicy>>;

export type ExternalCallbackCreate = ['packagePolicyCreate', PostPackagePolicyCreateCallback];
export type ExternalCallbackPostCreate = [
'packagePolicyPostCreate',
Expand All @@ -71,6 +81,15 @@ export type ExternalCallbackPostDelete = [
];
export type ExternalCallbackUpdate = ['packagePolicyUpdate', PutPackagePolicyUpdateCallback];

export type ExternalCallbackAgentPolicyCreate = [
'agentPolicyCreate',
PostAgentPolicyCreateCallback
];
export type ExternalCallbackAgentPolicyUpdate = [
'agentPolicyUpdate',
PostAgentPolicyUpdateCallback
];

/**
* Callbacks supported by the Fleet plugin
*/
Expand All @@ -79,6 +98,8 @@ export type ExternalCallback =
| ExternalCallbackPostCreate
| ExternalCallbackDelete
| ExternalCallbackPostDelete
| ExternalCallbackUpdate;
| ExternalCallbackUpdate
| ExternalCallbackAgentPolicyCreate
| ExternalCallbackAgentPolicyUpdate;

export type ExternalCallbacksStorage = Map<ExternalCallback[0], Set<ExternalCallback[1]>>;
Loading
Loading