-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EMT-248: initial check in to see if we get a clean build
- Loading branch information
1 parent
36d6590
commit 08d6a61
Showing
12 changed files
with
479 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { postAgentAcksHandlerBuilder } from './acks_handlers'; | ||
import { | ||
KibanaResponseFactory, | ||
RequestHandlerContext, | ||
SavedObjectsClientContract, | ||
} from 'kibana/server'; | ||
import { httpServerMock, savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; | ||
import { PostAgentAcksResponse } from '../../../common/types/rest_spec'; | ||
import { AckEventSchema } from '../../types/models'; | ||
import { AcksService } from '../../services/agents'; | ||
|
||
describe('test acks schema', () => { | ||
it('validate that ack event schema expect action id', async () => { | ||
expect(() => | ||
AckEventSchema.validate({ | ||
type: 'ACTION_RESULT', | ||
subtype: 'CONFIG', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
agent_id: 'agent', | ||
message: 'hello', | ||
payload: 'payload', | ||
}) | ||
).toThrow(Error); | ||
|
||
expect( | ||
AckEventSchema.validate({ | ||
type: 'ACTION_RESULT', | ||
subtype: 'CONFIG', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
agent_id: 'agent', | ||
action_id: 'actionId', | ||
message: 'hello', | ||
payload: 'payload', | ||
}) | ||
).toBeTruthy(); | ||
}); | ||
}); | ||
|
||
describe('test acks handlers', () => { | ||
let mockResponse: jest.Mocked<KibanaResponseFactory>; | ||
let mockSavedObjectsClient: jest.Mocked<SavedObjectsClientContract>; | ||
|
||
beforeEach(() => { | ||
mockSavedObjectsClient = savedObjectsClientMock.create(); | ||
mockResponse = httpServerMock.createResponseFactory(); | ||
}); | ||
|
||
it('should succeed on valid agent event', async () => { | ||
const mockRequest = httpServerMock.createKibanaRequest({ | ||
headers: { | ||
authorization: 'ApiKey TmVqTDBIQUJsRkw1em52R1ZIUF86NS1NaTItdHFUTHFHbThmQW1Fb0ljUQ==', | ||
}, | ||
body: { | ||
events: [ | ||
{ | ||
type: 'ACTION_RESULT', | ||
subtype: 'CONFIG', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
action_id: 'action1', | ||
agent_id: 'agent', | ||
message: 'message', | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
const ackService: AcksService = { | ||
acknowledgeAgentActions: jest.fn().mockReturnValueOnce([ | ||
{ | ||
type: 'CONFIG_CHANGE', | ||
id: 'action1', | ||
}, | ||
]), | ||
getAgentByAccessAPIKeyId: jest.fn().mockReturnValueOnce({ | ||
id: 'agent', | ||
}), | ||
getSavedObjectsClientContract: jest.fn().mockReturnValueOnce(mockSavedObjectsClient), | ||
saveAgentEvents: jest.fn(), | ||
} as jest.Mocked<AcksService>; | ||
|
||
const postAgentAcksHandler = postAgentAcksHandlerBuilder(ackService); | ||
await postAgentAcksHandler(({} as unknown) as RequestHandlerContext, mockRequest, mockResponse); | ||
expect(mockResponse.ok.mock.calls[0][0]?.body as PostAgentAcksResponse).toEqual({ | ||
action: 'acks', | ||
success: true, | ||
items: [ | ||
{ | ||
type: 'CONFIG_CHANGE', | ||
id: 'action1', | ||
}, | ||
], | ||
}); | ||
}); | ||
}); |
72 changes: 72 additions & 0 deletions
72
x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
// handlers that handle events from agents in response to actions received | ||
|
||
import { RequestHandler } from 'kibana/server'; | ||
import { TypeOf } from '@kbn/config-schema'; | ||
import { PostAgentAcksRequestSchema } from '../../types/rest_spec'; | ||
import * as APIKeyService from '../../services/api_keys'; | ||
import { AcksService } from '../../services/agents'; | ||
import { AgentEvent } from '../../../common/types/models'; | ||
import { PostAgentAcksResponse } from '../../../common/types/rest_spec'; | ||
|
||
export const postAgentAcksHandlerBuilder = function( | ||
ackService: AcksService | ||
): RequestHandler< | ||
TypeOf<typeof PostAgentAcksRequestSchema.params>, | ||
undefined, | ||
TypeOf<typeof PostAgentAcksRequestSchema.body> | ||
> { | ||
return async (context, request, response) => { | ||
try { | ||
const soClient = ackService.getSavedObjectsClientContract(request); | ||
const res = APIKeyService.parseApiKey(request.headers); | ||
const agent = await ackService.getAgentByAccessAPIKeyId(soClient, res.apiKeyId as string); | ||
const agentEvents = request.body.events as AgentEvent[]; | ||
|
||
// validate that all events are for the authorized agent obtained from the api key | ||
const notAuthorizedAgentEvent = agentEvents.filter( | ||
agentEvent => agentEvent.agent_id !== agent.id | ||
); | ||
|
||
if (notAuthorizedAgentEvent && notAuthorizedAgentEvent.length > 0) { | ||
return response.badRequest({ | ||
body: | ||
'agent events contains events with different agent id from currently authorized agent', | ||
}); | ||
} | ||
|
||
const agentActions = await ackService.acknowledgeAgentActions(soClient, agent, agentEvents); | ||
|
||
if (agentActions.length > 0) { | ||
await ackService.saveAgentEvents(soClient, agentEvents); | ||
} | ||
|
||
const body: PostAgentAcksResponse = { | ||
action: 'acks', | ||
success: true, | ||
items: [...agentActions], | ||
}; | ||
|
||
return response.ok({ body }); | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.log(JSON.stringify(e.message)); | ||
if (e.isBoom) { | ||
return response.customError({ | ||
statusCode: e.output.statusCode, | ||
body: { message: e.message }, | ||
}); | ||
} | ||
|
||
return response.customError({ | ||
statusCode: 500, | ||
body: { message: e.message }, | ||
}); | ||
} | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
x-pack/plugins/ingest_manager/server/services/agents/acks.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
import { savedObjectsClientMock } from '../../../../../../src/core/server/saved_objects/service/saved_objects_client.mock'; | ||
import { Agent, AgentAction, AgentEvent } from '../../../common/types/models'; | ||
import { AGENT_TYPE_PERMANENT } from '../../../common/constants'; | ||
import { acknowledgeAgentActions } from './acks'; | ||
import { isBoom } from 'boom'; | ||
|
||
describe('test agent acks services', () => { | ||
it('should succeed on valid and matched actions', async () => { | ||
const mockSavedObjectsClient = savedObjectsClientMock.create(); | ||
const agentActions = await acknowledgeAgentActions( | ||
mockSavedObjectsClient, | ||
({ | ||
id: 'id', | ||
type: AGENT_TYPE_PERMANENT, | ||
actions: [ | ||
{ | ||
type: 'CONFIG_CHANGE', | ||
id: 'action1', | ||
sent_at: '2020-03-14T19:45:02.620Z', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
created_at: '2020-03-14T19:45:02.620Z', | ||
}, | ||
], | ||
} as unknown) as Agent, | ||
[ | ||
{ | ||
type: 'ACTION_RESULT', | ||
subtype: 'CONFIG', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
action_id: 'action1', | ||
agent_id: 'id', | ||
} as AgentEvent, | ||
] | ||
); | ||
expect(agentActions).toEqual([ | ||
({ | ||
type: 'CONFIG_CHANGE', | ||
id: 'action1', | ||
sent_at: '2020-03-14T19:45:02.620Z', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
created_at: '2020-03-14T19:45:02.620Z', | ||
} as unknown) as AgentAction, | ||
]); | ||
}); | ||
|
||
it('should fail for actions that cannot be found on agent actions list', async () => { | ||
const mockSavedObjectsClient = savedObjectsClientMock.create(); | ||
try { | ||
await acknowledgeAgentActions( | ||
mockSavedObjectsClient, | ||
({ | ||
id: 'id', | ||
type: AGENT_TYPE_PERMANENT, | ||
actions: [ | ||
{ | ||
type: 'CONFIG_CHANGE', | ||
id: 'action1', | ||
sent_at: '2020-03-14T19:45:02.620Z', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
created_at: '2020-03-14T19:45:02.620Z', | ||
}, | ||
], | ||
} as unknown) as Agent, | ||
[ | ||
({ | ||
type: 'ACTION_RESULT', | ||
subtype: 'CONFIG', | ||
timestamp: '2019-01-04T14:32:03.36764-05:00', | ||
action_id: 'action2', | ||
agent_id: 'id', | ||
} as unknown) as AgentEvent, | ||
] | ||
); | ||
expect(true).toBeFalsy(); | ||
} catch (e) { | ||
expect(isBoom(e)).toBeTruthy(); | ||
} | ||
}); | ||
}); |
Oops, something went wrong.