Skip to content

Commit

Permalink
[Beats Management] APIs: take auth tokens via headers (#19210)
Browse files Browse the repository at this point in the history
* WIP checkin

* WIP checkin

* Add API integration test

* Converting to Jest test

* Fixing API for default case + adding test for it

* Fixing copy pasta typos

* Fixing variable name

* Using a single index

* Implementing GET /api/beats/agents API

* Creating POST /api/beats/agents/verify API

* Refactoring: extracting out helper functions

* Expanding TODO note so I won't forget :)

* Fixing file name

* Updating mapping

* Fixing minor typo in TODO comment

* Make "Enroll Beat" API take enrollment token via header instead of request body

* Make "Update Beat" API take access token via header instead of request body
  • Loading branch information
ycombinator authored and mattapperson committed Aug 7, 2018
1 parent e6d0f0f commit 62dea85
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ export function registerEnrollBeatRoute(server) {
config: {
validate: {
payload: Joi.object({
enrollment_token: Joi.string().required(),
type: Joi.string().required(),
version: Joi.string().required(),
host_name: Joi.string().required()
}).required()
}).required(),
headers: Joi.object({
'kbn-beats-enrollment-token': Joi.string().required()
}).options({ allowUnknown: true })
},
auth: false
},
Expand All @@ -76,7 +78,7 @@ export function registerEnrollBeatRoute(server) {
let accessToken;

try {
const enrollmentToken = request.payload.enrollment_token;
const enrollmentToken = request.headers['kbn-beats-enrollment-token'];
const { token, expires_on: expiresOn } = await getEnrollmentToken(callWithInternalUser, enrollmentToken);
if (!token || token !== enrollmentToken) {
return reply({ message: 'Invalid enrollment token' }).code(400);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ export function registerUpdateBeatRoute(server) {
config: {
validate: {
payload: Joi.object({
access_token: Joi.string().required(),
type: Joi.string(),
version: Joi.string(),
host_name: Joi.string(),
ephemeral_id: Joi.string(),
local_configuration_yml: Joi.string(),
metadata: Joi.object()
}).required()
}).required(),
headers: Joi.object({
'kbn-beats-access-token': Joi.string().required()
}).options({ allowUnknown: true })
},
auth: false
},
Expand All @@ -72,7 +74,7 @@ export function registerUpdateBeatRoute(server) {
return reply({ message: 'Beat not found' }).code(404);
}

const isAccessTokenValid = beat.access_token === request.payload.access_token;
const isAccessTokenValid = beat.access_token === request.headers['kbn-beats-access-token'];
if (!isAccessTokenValid) {
return reply({ message: 'Invalid access token' }).code(401);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function verifyBeats(callWithRequest, beatIds) {
return get(response, 'items', []);
}

function findNonExistentBeatIds(beatsFromEs, beatIdsFromRequest) {
function determineNonExistentBeatIds(beatsFromEs, beatIdsFromRequest) {
return beatsFromEs.reduce((nonExistentBeatIds, beatFromEs, idx) => {
if (!beatFromEs.found) {
nonExistentBeatIds.push(beatIdsFromRequest[idx]);
Expand All @@ -58,21 +58,21 @@ function findNonExistentBeatIds(beatsFromEs, beatIdsFromRequest) {
}, []);
}

function findAlreadyVerifiedBeatIds(beatsFromEs) {
function determineAlreadyVerifiedBeatIds(beatsFromEs) {
return beatsFromEs
.filter(beat => beat.found)
.filter(beat => beat._source.beat.hasOwnProperty('verified_on'))
.map(beat => beat._source.beat.id);
}

function findToBeVerifiedBeatIds(beatsFromEs) {
function determineToBeVerifiedBeatIds(beatsFromEs) {
return beatsFromEs
.filter(beat => beat.found)
.filter(beat => !beat._source.beat.hasOwnProperty('verified_on'))
.map(beat => beat._source.beat.id);
}

function findVerifiedBeatIds(verifications, toBeVerifiedBeatIds) {
function determineVerifiedBeatIds(verifications, toBeVerifiedBeatIds) {
return verifications.reduce((verifiedBeatIds, verification, idx) => {
if (verification.update.status === 200) {
verifiedBeatIds.push(toBeVerifiedBeatIds[idx]);
Expand Down Expand Up @@ -109,12 +109,12 @@ export function registerVerifyBeatsRoute(server) {
try {
const beatsFromEs = await getBeats(callWithRequest, beatIds);

nonExistentBeatIds = findNonExistentBeatIds(beatsFromEs, beatIds);
alreadyVerifiedBeatIds = findAlreadyVerifiedBeatIds(beatsFromEs);
const toBeVerifiedBeatIds = findToBeVerifiedBeatIds(beatsFromEs);
nonExistentBeatIds = determineNonExistentBeatIds(beatsFromEs, beatIds);
alreadyVerifiedBeatIds = determineAlreadyVerifiedBeatIds(beatsFromEs);
const toBeVerifiedBeatIds = determineToBeVerifiedBeatIds(beatsFromEs);

const verifications = await verifyBeats(callWithRequest, toBeVerifiedBeatIds);
verifiedBeatIds = findVerifiedBeatIds(verifications, toBeVerifiedBeatIds);
verifiedBeatIds = determineVerifiedBeatIds(verifications, toBeVerifiedBeatIds);

} catch (err) {
return reply(wrapEsError(err));
Expand Down
13 changes: 7 additions & 6 deletions x-pack/test/api_integration/apis/beats/enroll_beat.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export default function ({ getService }) {
+ chance.integer({ min: 1, max: 10 });

beat = {
enrollment_token: validEnrollmentToken,
type: 'filebeat',
host_name: 'foo.bar.com',
version
Expand All @@ -57,6 +56,7 @@ export default function ({ getService }) {
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-enrollment-token', validEnrollmentToken)
.send(beat)
.expect(201);

Expand All @@ -76,6 +76,7 @@ export default function ({ getService }) {
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-enrollment-token', validEnrollmentToken)
.send(beat)
.expect(201);

Expand All @@ -94,14 +95,12 @@ export default function ({ getService }) {
});

it('should reject an invalid enrollment token', async () => {
const invalidEnrollmentToken = chance.word();
beat.enrollment_token = invalidEnrollmentToken;

const { body: apiResponse } = await supertest
.post(
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-enrollment-token', chance.word())
.send(beat)
.expect(400);

Expand All @@ -124,13 +123,12 @@ export default function ({ getService }) {
}
});

beat.enrollment_token = expiredEnrollmentToken;

const { body: apiResponse } = await supertest
.post(
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-enrollment-token', expiredEnrollmentToken)
.send(beat)
.expect(400);

Expand All @@ -143,6 +141,7 @@ export default function ({ getService }) {
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-enrollment-token', validEnrollmentToken)
.send(beat)
.expect(201);

Expand All @@ -162,6 +161,7 @@ export default function ({ getService }) {
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-enrollment-token', validEnrollmentToken)
.send(beat)
.expect(201);

Expand All @@ -183,6 +183,7 @@ export default function ({ getService }) {
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-enrollment-token', validEnrollmentToken)
.send(beat)
.expect(409);
});
Expand Down
7 changes: 4 additions & 3 deletions x-pack/test/api_integration/apis/beats/update_beat.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export default function ({ getService }) {
+ chance.integer({ min: 1, max: 10 });

beat = {
access_token: '93c4a4dd08564c189a7ec4e4f046b975',
type: `${chance.word()}beat`,
host_name: `www.${chance.word()}.net`,
version,
Expand All @@ -46,6 +45,7 @@ export default function ({ getService }) {
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-access-token', '93c4a4dd08564c189a7ec4e4f046b975')
.send(beat)
.expect(204);

Expand All @@ -64,12 +64,12 @@ export default function ({ getService }) {

it('should return an error for an invalid access token', async () => {
const beatId = 'foo';
beat.access_token = chance.word();
const { body } = await supertest
.put(
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-access-token', chance.word())
.send(beat)
.expect(401);

Expand All @@ -90,12 +90,12 @@ export default function ({ getService }) {

it('should return an error for an existing but unverified beat', async () => {
const beatId = 'bar';
beat.access_token = '3c4a4dd08564c189a7ec4e4f046b9759';
const { body } = await supertest
.put(
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-access-token', '3c4a4dd08564c189a7ec4e4f046b9759')
.send(beat)
.expect(400);

Expand All @@ -121,6 +121,7 @@ export default function ({ getService }) {
`/api/beats/agent/${beatId}`
)
.set('kbn-xsrf', 'xxx')
.set('kbn-beats-access-token', chance.word())
.send(beat)
.expect(404);

Expand Down

0 comments on commit 62dea85

Please sign in to comment.