Skip to content

Commit

Permalink
[Fleet] Handler api key creation errors when Fleet Admin is invalid (e…
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet committed Dec 1, 2020
1 parent 3ddbc57 commit 6244a70
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ function useCreateApiKeyForm(
policy_id: policyIdInput.value,
}),
});
if (res.error) {
throw res.error;
}
policyIdInput.clear();
apiKeyNameInput.clear();
setIsLoading(false);
Expand Down
7 changes: 6 additions & 1 deletion x-pack/plugins/fleet/server/errors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
*/

/* eslint-disable max-classes-per-file */
export { defaultIngestErrorHandler, ingestErrorToResponseOptions } from './handlers';
export {
defaultIngestErrorHandler,
ingestErrorToResponseOptions,
isLegacyESClientError,
} from './handlers';

export class IngestManagerError extends Error {
constructor(message?: string) {
Expand All @@ -24,3 +28,4 @@ export class PackageUnsupportedMediaTypeError extends IngestManagerError {}
export class PackageInvalidArchiveError extends IngestManagerError {}
export class PackageCacheError extends IngestManagerError {}
export class PackageOperationNotSupportedError extends IngestManagerError {}
export class FleetAdminUserInvalidError extends IngestManagerError {}
58 changes: 46 additions & 12 deletions x-pack/plugins/fleet/server/services/api_keys/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { KibanaRequest, FakeRequest, SavedObjectsClientContract } from 'src/core/server';
import type { Request } from '@hapi/hapi';
import { KibanaRequest, SavedObjectsClientContract } from '../../../../../../src/core/server';
import { FleetAdminUserInvalidError, isLegacyESClientError } from '../../errors';
import { CallESAsCurrentUser } from '../../types';
import { appContextService } from '../app_context';
import { outputService } from '../output';
Expand All @@ -18,22 +20,38 @@ export async function createAPIKey(
if (!adminUser) {
throw new Error('No admin user configured');
}
const request: FakeRequest = {
const request = KibanaRequest.from(({
path: '/',
route: { settings: {} },
url: { href: '/' },
raw: { req: { url: '/' } },
headers: {
authorization: `Basic ${Buffer.from(`${adminUser.username}:${adminUser.password}`).toString(
'base64'
)}`,
},
};
} as unknown) as Request);
const security = appContextService.getSecurity();
if (!security) {
throw new Error('Missing security plugin');
}

return security.authc.createAPIKey(request as KibanaRequest, {
name,
role_descriptors: roleDescriptors,
});
try {
const key = await security.authc.createAPIKey(request, {
name,
role_descriptors: roleDescriptors,
});

return key;
} catch (err) {
if (isLegacyESClientError(err) && err.statusCode === 401) {
// Clear Fleet admin user cache as the user is probably not valid anymore
outputService.invalidateCache();
throw new FleetAdminUserInvalidError(`Fleet Admin user is invalid: ${err.message}`);
}

throw err;
}
}
export async function authenticate(callCluster: CallESAsCurrentUser) {
try {
Expand All @@ -51,20 +69,36 @@ export async function invalidateAPIKey(soClient: SavedObjectsClientContract, id:
if (!adminUser) {
throw new Error('No admin user configured');
}
const request: FakeRequest = {
const request = KibanaRequest.from(({
path: '/',
route: { settings: {} },
url: { href: '/' },
raw: { req: { url: '/' } },
headers: {
authorization: `Basic ${Buffer.from(`${adminUser.username}:${adminUser.password}`).toString(
'base64'
)}`,
},
};
} as unknown) as Request);

const security = appContextService.getSecurity();
if (!security) {
throw new Error('Missing security plugin');
}

return security.authc.invalidateAPIKey(request as KibanaRequest, {
id,
});
try {
const res = await security.authc.invalidateAPIKey(request, {
id,
});

return res;
} catch (err) {
if (isLegacyESClientError(err) && err.statusCode === 401) {
// Clear Fleet admin user cache as the user is probably not valid anymore
outputService.invalidateCache();
throw new FleetAdminUserInvalidError(`Fleet Admin user is invalid: ${err.message}`);
}

throw err;
}
}
31 changes: 29 additions & 2 deletions x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ export default function (providerContext: FtrProviderContext) {
.expect(400);
});

it('should not allow to create an enrollment api key for a non existing agent policy', async () => {
it('should return a 400 if the fleet admin user is modifed outside of Fleet', async () => {
await supertest
.post(`/api/fleet/enrollment-api-keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'idonotexistspolicy',
raoul: 'raoul',
})
.expect(400);
});
Expand Down Expand Up @@ -161,6 +161,33 @@ export default function (providerContext: FtrProviderContext) {
},
});
});

describe('It should handle error when the Fleet user is invalid', () => {
before(async () => {});
after(async () => {
await getService('supertest')
.post(`/api/fleet/agents/setup`)
.set('kbn-xsrf', 'xxx')
.send({ forceRecreate: true });
});

it('should not allow to create an enrollment api key if the Fleet admin user is invalid', async () => {
await es.security.changePassword({
username: 'fleet_enroll',
body: {
password: Buffer.from((Math.random() * 10000000).toString()).toString('base64'),
},
});
const res = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
})
.expect(400);
expect(res.body.message).match(/Fleet Admin user is invalid/);
});
});
});
});
}

0 comments on commit 6244a70

Please sign in to comment.