Skip to content

Commit

Permalink
Adding authc.invalidateAPIKeyAsInternalUser (elastic#60717)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
mikecote and elasticmachine committed Mar 23, 2020
1 parent e7d8010 commit f8499e0
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 9 deletions.
52 changes: 52 additions & 0 deletions x-pack/plugins/security/server/authentication/api_keys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,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',
},
});
});
});
});
41 changes: 33 additions & 8 deletions x-pack/plugins/security/server/authentication/api_keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,26 +136,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');
this.logger.debug('Trying to invalidate an API key as current user');

// User needs `manage_api_key` privilege to use this API
let result: InvalidateAPIKeyResult;
try {
result = (await this.clusterClient
// User needs `manage_api_key` privilege to use this API
result = await this.clusterClient
.asScoped(request)
.callAsCurrentUser('shield.invalidateAPIKey', {
body: {
id: params.id,
},
})) as InvalidateAPIKeyResult;
});
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');

let result: InvalidateAPIKeyResult;
try {
// 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}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const authenticationMock = {
createAPIKey: jest.fn(),
getCurrentUser: jest.fn(),
invalidateAPIKey: jest.fn(),
invalidateAPIKeyAsInternalUser: jest.fn(),
isAuthenticated: jest.fn(),
getSessionInfo: jest.fn(),
}),
Expand Down
23 changes: 22 additions & 1 deletion x-pack/plugins/security/server/authentication/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -438,4 +438,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);
});
});
});
2 changes: 2 additions & 0 deletions x-pack/plugins/security/server/authentication/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ export async function setupAuthentication({
apiKeys.create(request, params),
invalidateAPIKey: (request: KibanaRequest, params: InvalidateAPIKeyParams) =>
apiKeys.invalidate(request, params),
invalidateAPIKeyAsInternalUser: (params: InvalidateAPIKeyParams) =>
apiKeys.invalidateAsInternalUser(params),
isAuthenticated: (request: KibanaRequest) => http.auth.isAuthenticated(request),
};
}
1 change: 1 addition & 0 deletions x-pack/plugins/security/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe('Security Plugin', () => {
"getCurrentUser": [Function],
"getSessionInfo": [Function],
"invalidateAPIKey": [Function],
"invalidateAPIKeyAsInternalUser": [Function],
"isAuthenticated": [Function],
"isProviderEnabled": [Function],
"login": [Function],
Expand Down

0 comments on commit f8499e0

Please sign in to comment.