Adding authc.invalidateAPIKeyAsInternalUser (#60717)

* Initial work

* Fix type check issues

* Fix test failures

* Fix ESLint issues

* Add back comment

* PR feedback

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Mike Côté 2020-03-23 12:39:55 -04:00 committed by GitHub
parent 21e8cea183
commit 91e8e3e883
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 13 deletions

View file

@ -225,4 +225,56 @@ describe('API Keys', () => {
);
});
});
describe('invalidateAsInternalUser()', () => {
it('returns null when security feature is disabled', async () => {
mockLicense.isEnabled.mockReturnValue(false);
const result = await apiKeys.invalidateAsInternalUser({ id: '123' });
expect(result).toBeNull();
expect(mockClusterClient.callAsInternalUser).not.toHaveBeenCalled();
});
it('calls callCluster with proper parameters', async () => {
mockLicense.isEnabled.mockReturnValue(true);
mockClusterClient.callAsInternalUser.mockResolvedValueOnce({
invalidated_api_keys: ['api-key-id-1'],
previously_invalidated_api_keys: [],
error_count: 0,
});
const result = await apiKeys.invalidateAsInternalUser({ id: '123' });
expect(result).toEqual({
invalidated_api_keys: ['api-key-id-1'],
previously_invalidated_api_keys: [],
error_count: 0,
});
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith('shield.invalidateAPIKey', {
body: {
id: '123',
},
});
});
it('Only passes id as a parameter', async () => {
mockLicense.isEnabled.mockReturnValue(true);
mockClusterClient.callAsInternalUser.mockResolvedValueOnce({
invalidated_api_keys: ['api-key-id-1'],
previously_invalidated_api_keys: [],
error_count: 0,
});
const result = await apiKeys.invalidateAsInternalUser({
id: '123',
name: 'abc',
} as any);
expect(result).toEqual({
invalidated_api_keys: ['api-key-id-1'],
previously_invalidated_api_keys: [],
error_count: 0,
});
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith('shield.invalidateAPIKey', {
body: {
id: '123',
},
});
});
});
});

View file

@ -193,26 +193,51 @@ export class APIKeys {
* @param request Request instance.
* @param params The params to invalidate an API key.
*/
async invalidate(
request: KibanaRequest,
params: InvalidateAPIKeyParams
): Promise<InvalidateAPIKeyResult | null> {
async invalidate(request: KibanaRequest, params: InvalidateAPIKeyParams) {
if (!this.license.isEnabled()) {
return null;
}
this.logger.debug('Trying to invalidate an API key as current user');
let result: InvalidateAPIKeyResult;
try {
// User needs `manage_api_key` privilege to use this API
result = await this.clusterClient
.asScoped(request)
.callAsCurrentUser('shield.invalidateAPIKey', {
body: {
id: params.id,
},
});
this.logger.debug('API key was invalidated successfully as current user');
} catch (e) {
this.logger.error(`Failed to invalidate API key as current user: ${e.message}`);
throw e;
}
return result;
}
/**
* Tries to invalidate an API key by using the internal user.
* @param params The params to invalidate an API key.
*/
async invalidateAsInternalUser(params: InvalidateAPIKeyParams) {
if (!this.license.isEnabled()) {
return null;
}
this.logger.debug('Trying to invalidate an API key');
// User needs `manage_api_key` privilege to use this API
let result: InvalidateAPIKeyResult;
try {
result = (await this.clusterClient
.asScoped(request)
.callAsCurrentUser('shield.invalidateAPIKey', {
body: {
id: params.id,
},
})) as InvalidateAPIKeyResult;
// Internal user needs `cluster:admin/xpack/security/api_key/invalidate` privilege to use this API
result = await this.clusterClient.callAsInternalUser('shield.invalidateAPIKey', {
body: {
id: params.id,
},
});
this.logger.debug('API key was invalidated successfully');
} catch (e) {
this.logger.error(`Failed to invalidate API key: ${e.message}`);

View file

@ -15,6 +15,7 @@ export const authenticationMock = {
getCurrentUser: jest.fn(),
grantAPIKeyAsInternalUser: jest.fn(),
invalidateAPIKey: jest.fn(),
invalidateAPIKeyAsInternalUser: jest.fn(),
isAuthenticated: jest.fn(),
getSessionInfo: jest.fn(),
}),

View file

@ -33,7 +33,7 @@ import {
import { AuthenticatedUser } from '../../common/model';
import { ConfigType, createConfig$ } from '../config';
import { AuthenticationResult } from './authentication_result';
import { setupAuthentication } from '.';
import { Authentication, setupAuthentication } from '.';
import {
CreateAPIKeyResult,
CreateAPIKeyParams,
@ -410,4 +410,25 @@ describe('setupAuthentication()', () => {
expect(apiKeysInstance.invalidate).toHaveBeenCalledWith(request, params);
});
});
describe('invalidateAPIKeyAsInternalUser()', () => {
let invalidateAPIKeyAsInternalUser: Authentication['invalidateAPIKeyAsInternalUser'];
beforeEach(async () => {
invalidateAPIKeyAsInternalUser = (await setupAuthentication(mockSetupAuthenticationParams))
.invalidateAPIKeyAsInternalUser;
});
it('calls invalidateAPIKeyAsInternalUser with given arguments', async () => {
const apiKeysInstance = jest.requireMock('./api_keys').APIKeys.mock.instances[0];
const params = {
id: '123',
};
apiKeysInstance.invalidateAsInternalUser.mockResolvedValueOnce({ success: true });
await expect(invalidateAPIKeyAsInternalUser(params)).resolves.toEqual({
success: true,
});
expect(apiKeysInstance.invalidateAsInternalUser).toHaveBeenCalledWith(params);
});
});
});

View file

@ -176,6 +176,8 @@ export async function setupAuthentication({
grantAPIKeyAsInternalUser: (request: KibanaRequest) => apiKeys.grantAsInternalUser(request),
invalidateAPIKey: (request: KibanaRequest, params: InvalidateAPIKeyParams) =>
apiKeys.invalidate(request, params),
invalidateAPIKeyAsInternalUser: (params: InvalidateAPIKeyParams) =>
apiKeys.invalidateAsInternalUser(params),
isAuthenticated: (request: KibanaRequest) => http.auth.isAuthenticated(request),
};
}

View file

@ -76,6 +76,7 @@ describe('Security Plugin', () => {
"getSessionInfo": [Function],
"grantAPIKeyAsInternalUser": [Function],
"invalidateAPIKey": [Function],
"invalidateAPIKeyAsInternalUser": [Function],
"isAuthenticated": [Function],
"isProviderEnabled": [Function],
"login": [Function],