-
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.
- Loading branch information
Showing
11 changed files
with
235 additions
and
46 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
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
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
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
125 changes: 125 additions & 0 deletions
125
x-pack/plugins/security/server/routes/api_keys/has.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,125 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
import Boom from '@hapi/boom'; | ||
|
||
import { kibanaResponseFactory } from '@kbn/core/server'; | ||
import type { RequestHandler } from '@kbn/core/server'; | ||
import type { CustomRequestHandlerMock, ScopedClusterClientMock } from '@kbn/core/server/mocks'; | ||
import { coreMock, httpServerMock } from '@kbn/core/server/mocks'; | ||
import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; | ||
import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; | ||
|
||
import { defineHasApiKeysRoutes } from './has'; | ||
import type { InternalAuthenticationServiceStart } from '../../authentication'; | ||
import { authenticationServiceMock } from '../../authentication/authentication_service.mock'; | ||
import { routeDefinitionParamsMock } from '../index.mock'; | ||
|
||
describe('Has API Keys route', () => { | ||
let routeHandler: RequestHandler<any, any, any, any>; | ||
let authc: DeeplyMockedKeys<InternalAuthenticationServiceStart>; | ||
let esClientMock: ScopedClusterClientMock; | ||
let mockContext: CustomRequestHandlerMock<unknown>; | ||
|
||
beforeEach(async () => { | ||
const mockRouteDefinitionParams = routeDefinitionParamsMock.create(); | ||
authc = authenticationServiceMock.createStart(); | ||
mockRouteDefinitionParams.getAuthenticationService.mockReturnValue(authc); | ||
defineHasApiKeysRoutes(mockRouteDefinitionParams); | ||
[[, routeHandler]] = mockRouteDefinitionParams.router.get.mock.calls; | ||
mockContext = coreMock.createCustomRequestHandlerContext({ | ||
core: coreMock.createRequestHandlerContext(), | ||
licensing: licensingMock.createRequestHandlerContext(), | ||
}); | ||
|
||
esClientMock = (await mockContext.core).elasticsearch.client; | ||
|
||
authc.apiKeys.areAPIKeysEnabled.mockResolvedValue(true); | ||
authc.apiKeys.areCrossClusterAPIKeysEnabled.mockResolvedValue(true); | ||
|
||
esClientMock.asCurrentUser.security.getApiKey.mockResponse({ | ||
api_keys: [ | ||
{ id: '123', invalidated: false }, | ||
{ id: '456', invalidated: true }, | ||
], | ||
} as any); | ||
}); | ||
|
||
it('should calculate when user has API keys', async () => { | ||
const response = await routeHandler( | ||
mockContext, | ||
httpServerMock.createKibanaRequest(), | ||
kibanaResponseFactory | ||
); | ||
|
||
expect(response.payload).toEqual( | ||
expect.objectContaining({ | ||
hasApiKeys: true, | ||
}) | ||
); | ||
}); | ||
|
||
it('should calculate when user does not have API keys', async () => { | ||
esClientMock.asCurrentUser.security.getApiKey.mockResponse({ | ||
api_keys: [], | ||
}); | ||
|
||
const response = await routeHandler( | ||
mockContext, | ||
httpServerMock.createKibanaRequest(), | ||
kibanaResponseFactory | ||
); | ||
|
||
expect(response.payload).toEqual( | ||
expect.objectContaining({ | ||
hasApiKeys: false, | ||
}) | ||
); | ||
}); | ||
|
||
it('should filter out invalidated API keys', async () => { | ||
const response = await routeHandler( | ||
mockContext, | ||
httpServerMock.createKibanaRequest(), | ||
kibanaResponseFactory | ||
); | ||
|
||
expect(response.status).toBe(200); | ||
expect(response.payload?.hasApiKeys).toBe(true); | ||
}); | ||
|
||
it('should return `404` if API keys are disabled', async () => { | ||
authc.apiKeys.areAPIKeysEnabled.mockResolvedValue(false); | ||
|
||
const response = await routeHandler( | ||
mockContext, | ||
httpServerMock.createKibanaRequest(), | ||
kibanaResponseFactory | ||
); | ||
|
||
expect(response.status).toBe(404); | ||
expect(response.payload).toEqual({ | ||
message: | ||
"API keys are disabled in Elasticsearch. To use API keys enable 'xpack.security.authc.api_key.enabled' setting.", | ||
}); | ||
}); | ||
|
||
it('should forward error from Elasticsearch GET API keys endpoint', async () => { | ||
const error = Boom.forbidden('test not acceptable message'); | ||
esClientMock.asCurrentUser.security.getApiKey.mockResponseImplementation(() => { | ||
throw error; | ||
}); | ||
|
||
const response = await routeHandler( | ||
mockContext, | ||
httpServerMock.createKibanaRequest(), | ||
kibanaResponseFactory | ||
); | ||
|
||
expect(response.status).toBe(403); | ||
expect(response.payload).toEqual(error); | ||
}); | ||
}); |
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,65 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import type { RouteDefinitionParams } from '..'; | ||
import { wrapIntoCustomErrorResponse } from '../../errors'; | ||
import { createLicensedRouteHandler } from '../licensed_route_handler'; | ||
|
||
/** | ||
* Response of Kibana Has API keys endpoint. | ||
*/ | ||
export interface HasAPIKeysResult { | ||
hasApiKeys: boolean; | ||
} | ||
|
||
export function defineHasApiKeysRoutes({ | ||
router, | ||
getAuthenticationService, | ||
}: RouteDefinitionParams) { | ||
router.get( | ||
{ | ||
path: '/internal/security/has_api_keys', | ||
validate: false, | ||
options: { | ||
access: 'internal', | ||
}, | ||
}, | ||
createLicensedRouteHandler(async (context, _request, response) => { | ||
try { | ||
// copied logic from get.ts | ||
const esClient = (await context.core).elasticsearch.client; | ||
const authenticationService = getAuthenticationService(); | ||
|
||
const areApiKeysEnabled = await authenticationService.apiKeys.areAPIKeysEnabled(); | ||
|
||
if (!areApiKeysEnabled) { | ||
return response.notFound({ | ||
body: { | ||
message: | ||
"API keys are disabled in Elasticsearch. To use API keys enable 'xpack.security.authc.api_key.enabled' setting.", | ||
}, | ||
}); | ||
} | ||
|
||
const apiResponse = await esClient.asCurrentUser.security.getApiKey({ | ||
owner: true, | ||
}); | ||
|
||
const validKeys = apiResponse.api_keys.filter(({ invalidated }) => !invalidated); | ||
|
||
// simply return true if the result array is non-empty | ||
return response.ok<HasAPIKeysResult>({ | ||
body: { | ||
hasApiKeys: validKeys.length > 0, | ||
}, | ||
}); | ||
} catch (error) { | ||
return response.customError(wrapIntoCustomErrorResponse(error)); | ||
} | ||
}) | ||
); | ||
} |
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
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