Skip to content

Commit

Permalink
[Ingest Manager] Use long polling for agent checkin (#68922)
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet authored Jun 18, 2020
1 parent 550b95f commit 0c47747
Show file tree
Hide file tree
Showing 23 changed files with 534 additions and 353 deletions.
2 changes: 2 additions & 0 deletions x-pack/plugins/ingest_manager/common/constants/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ export const AGENT_TYPE_TEMPORARY = 'TEMPORARY';

export const AGENT_POLLING_THRESHOLD_MS = 30000;
export const AGENT_POLLING_INTERVAL = 1000;
export const AGENT_UPDATE_LAST_CHECKIN_INTERVAL_MS = 30000;
export const AGENT_UPDATE_ACTIONS_INTERVAL_MS = 5000;
1 change: 1 addition & 0 deletions x-pack/plugins/ingest_manager/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface IngestManagerConfigType {
fleet: {
enabled: boolean;
tlsCheckDisabled: boolean;
pollingRequestTimeout: number;
kibana: {
host?: string;
ca_sha256?: string;
Expand Down
5 changes: 4 additions & 1 deletion x-pack/plugins/ingest_manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
"name": "ingest-manager",
"version": "8.0.0",
"private": true,
"license": "Elastic-License"
"license": "Elastic-License",
"dependencies": {
"abort-controller": "^3.0.0"
}
}
2 changes: 2 additions & 0 deletions x-pack/plugins/ingest_manager/server/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export {
AGENT_TYPE_TEMPORARY,
AGENT_POLLING_THRESHOLD_MS,
AGENT_POLLING_INTERVAL,
AGENT_UPDATE_LAST_CHECKIN_INTERVAL_MS,
AGENT_UPDATE_ACTIONS_INTERVAL_MS,
INDEX_PATTERN_PLACEHOLDER_SUFFIX,
// Routes
PLUGIN_ID,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/ingest_manager/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const config = {
fleet: schema.object({
enabled: schema.boolean({ defaultValue: true }),
tlsCheckDisabled: schema.boolean({ defaultValue: false }),
pollingRequestTimeout: schema.number({ defaultValue: 60000 }),
kibana: schema.object({
host: schema.maybe(schema.string()),
ca_sha256: schema.maybe(schema.string()),
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/ingest_manager/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
} from './services';
import { getAgentStatusById } from './services/agents';
import { CloudSetup } from '../../cloud/server';
import { agentCheckinState } from './services/agents/checkin/state';

export interface IngestManagerSetupDeps {
licensing: LicensingPluginSetup;
Expand Down Expand Up @@ -229,6 +230,8 @@ export class IngestManagerPlugin
logger: this.logger,
});
licenseService.start(this.licensing$);
agentCheckinState.start();

return {
esIndexPatternService: new ESIndexPatternSavedObjectService(),
agentService: {
Expand All @@ -240,5 +243,6 @@ export class IngestManagerPlugin
public async stop() {
appContextService.stop();
licenseService.stop();
agentCheckinState.stop();
}
}
40 changes: 24 additions & 16 deletions x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { RequestHandler, KibanaRequest } from 'src/core/server';
import { RequestHandler } from 'src/core/server';
import { TypeOf } from '@kbn/config-schema';
import { AbortController } from 'abort-controller';
import {
GetAgentsResponse,
GetOneAgentResponse,
Expand All @@ -32,13 +33,6 @@ import * as AgentService from '../../services/agents';
import * as APIKeyService from '../../services/api_keys';
import { appContextService } from '../../services/app_context';

export function getInternalUserSOClient(request: KibanaRequest) {
// soClient as kibana internal users, be carefull on how you use it, security is not enabled
return appContextService.getSavedObjects().getScopedClient(request, {
excludedWrappers: ['security'],
});
}

export const getAgentHandler: RequestHandler<TypeOf<
typeof GetOneAgentRequestSchema.params
>> = async (context, request, response) => {
Expand Down Expand Up @@ -176,14 +170,20 @@ export const postAgentCheckinHandler: RequestHandler<
TypeOf<typeof PostAgentCheckinRequestSchema.body>
> = async (context, request, response) => {
try {
const soClient = getInternalUserSOClient(request);
const soClient = appContextService.getInternalUserSOClient(request);
const res = APIKeyService.parseApiKeyFromHeaders(request.headers);
const agent = await AgentService.getAgentByAccessAPIKeyId(soClient, res.apiKeyId);
const abortController = new AbortController();
request.events.aborted$.subscribe(() => {
abortController.abort();
});
const signal = abortController.signal;
const { actions } = await AgentService.agentCheckin(
soClient,
agent,
request.body.events || [],
request.body.local_metadata
request.body.local_metadata,
{ signal }
);
const body: PostAgentCheckinResponse = {
action: 'checkin',
Expand All @@ -198,16 +198,24 @@ export const postAgentCheckinHandler: RequestHandler<
};

return response.ok({ body });
} catch (e) {
if (e.isBoom && e.output.statusCode === 404) {
return response.notFound({
body: { message: `Agent ${request.params.agentId} not found` },
} catch (err) {
const logger = appContextService.getLogger();
if (err.isBoom) {
if (err.output.statusCode >= 500) {
logger.error(err);
}

return response.customError({
statusCode: err.output.statusCode,
body: { message: err.output.payload.message },
});
}

logger.error(err);

return response.customError({
statusCode: 500,
body: { message: e.message },
body: { message: err.message },
});
}
};
Expand All @@ -218,7 +226,7 @@ export const postAgentEnrollHandler: RequestHandler<
TypeOf<typeof PostAgentEnrollRequestSchema.body>
> = async (context, request, response) => {
try {
const soClient = getInternalUserSOClient(request);
const soClient = appContextService.getInternalUserSOClient(request);
const { apiKeyId } = APIKeyService.parseApiKeyFromHeaders(request.headers);
const enrollmentAPIKey = await APIKeyService.getEnrollmentAPIKeyById(soClient, apiKeyId);

Expand Down
6 changes: 4 additions & 2 deletions x-pack/plugins/ingest_manager/server/routes/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ import {
postAgentEnrollHandler,
postAgentsUnenrollHandler,
getAgentStatusForConfigHandler,
getInternalUserSOClient,
putAgentsReassignHandler,
} from './handlers';
import { postAgentAcksHandlerBuilder } from './acks_handlers';
import * as AgentService from '../../services/agents';
import { postNewAgentActionHandlerBuilder } from './actions_handlers';
import { appContextService } from '../../services';

export const registerRoutes = (router: IRouter) => {
// Get one
Expand Down Expand Up @@ -110,7 +110,9 @@ export const registerRoutes = (router: IRouter) => {
postAgentAcksHandlerBuilder({
acknowledgeAgentActions: AgentService.acknowledgeAgentActions,
getAgentByAccessAPIKeyId: AgentService.getAgentByAccessAPIKeyId,
getSavedObjectsClientContract: getInternalUserSOClient,
getSavedObjectsClientContract: appContextService.getInternalUserSOClient.bind(
appContextService
),
saveAgentEvents: AgentService.saveAgentEvents,
})
);
Expand Down
2 changes: 0 additions & 2 deletions x-pack/plugins/ingest_manager/server/services/agent_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ class AgentConfigService {
updated_by: user ? user.username : 'system',
});

await this.triggerAgentConfigUpdatedEvent(soClient, 'updated', id);

return (await this.get(soClient, id)) as AgentConfig;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ export async function getAgentActionByIds(
);
}

export async function getNewActionsSince(soClient: SavedObjectsClientContract, timestamp: string) {
const res = await soClient.find<AgentActionSOAttributes>({
type: AGENT_ACTION_SAVED_OBJECT_TYPE,
filter: `not ${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at: * AND ${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.created_at >= "${timestamp}"`,
});

return res.saved_objects.map(savedObjectToAgentAction);
}

export interface ActionsService {
getAgent: (soClient: SavedObjectsClientContract, agentId: string) => Promise<Agent>;

Expand Down
136 changes: 0 additions & 136 deletions x-pack/plugins/ingest_manager/server/services/agents/checkin.test.ts

This file was deleted.

Loading

0 comments on commit 0c47747

Please sign in to comment.