Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ afterEach(() => {
});

it(`#setup returns exposed services`, () => {
const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
const mockGetSpacesService = jest
.fn()
.mockReturnValue({ getSpaceId: jest.fn(), namespaceToSpaceId: jest.fn() });
Expand All @@ -64,10 +64,11 @@ it(`#setup returns exposed services`, () => {
const mockCoreSetup = coreMock.createSetup();

const authorizationService = new AuthorizationService();
const getClusterClient = () => Promise.resolve(mockClusterClient);
const authz = authorizationService.setup({
http: mockCoreSetup.http,
capabilities: mockCoreSetup.capabilities,
clusterClient: mockClusterClient,
getClusterClient,
license: mockLicense,
loggers: loggingSystemMock.create(),
kibanaIndexName,
Expand All @@ -84,7 +85,7 @@ it(`#setup returns exposed services`, () => {
expect(authz.checkPrivilegesWithRequest).toBe(mockCheckPrivilegesWithRequest);
expect(checkPrivilegesWithRequestFactory).toHaveBeenCalledWith(
authz.actions,
mockClusterClient,
getClusterClient,
authz.applicationName
);

Expand Down Expand Up @@ -119,14 +120,14 @@ describe('#start', () => {
beforeEach(() => {
statusSubject = new Subject<OnlineStatusRetryScheduler>();

const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
const mockCoreSetup = coreMock.createSetup();

const authorizationService = new AuthorizationService();
authorizationService.setup({
http: mockCoreSetup.http,
capabilities: mockCoreSetup.capabilities,
clusterClient: mockClusterClient,
getClusterClient: () => Promise.resolve(mockClusterClient),
license: licenseMock.create(),
loggers: loggingSystemMock.create(),
kibanaIndexName,
Expand Down Expand Up @@ -190,15 +191,15 @@ describe('#start', () => {
});

it('#stop unsubscribes from license and ES updates.', async () => {
const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
const statusSubject = new Subject<OnlineStatusRetryScheduler>();
const mockCoreSetup = coreMock.createSetup();

const authorizationService = new AuthorizationService();
authorizationService.setup({
http: mockCoreSetup.http,
capabilities: mockCoreSetup.capabilities,
clusterClient: mockClusterClient,
getClusterClient: () => Promise.resolve(mockClusterClient),
license: licenseMock.create(),
loggers: loggingSystemMock.create(),
kibanaIndexName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import type { Capabilities as UICapabilities } from '../../../../../src/core/typ
import {
LoggerFactory,
KibanaRequest,
ILegacyClusterClient,
Logger,
HttpServiceSetup,
CapabilitiesSetup,
IClusterClient,
} from '../../../../../src/core/server';

import {
Expand Down Expand Up @@ -63,7 +63,7 @@ interface AuthorizationServiceSetupParams {
buildNumber: number;
http: HttpServiceSetup;
capabilities: CapabilitiesSetup;
clusterClient: ILegacyClusterClient;
getClusterClient: () => Promise<IClusterClient>;
license: SecurityLicense;
loggers: LoggerFactory;
features: FeaturesPluginSetup;
Expand All @@ -74,7 +74,7 @@ interface AuthorizationServiceSetupParams {

interface AuthorizationServiceStartParams {
features: FeaturesPluginStart;
clusterClient: ILegacyClusterClient;
clusterClient: IClusterClient;
online$: Observable<OnlineStatusRetryScheduler>;
}

Expand All @@ -100,7 +100,7 @@ export class AuthorizationService {
capabilities,
packageVersion,
buildNumber,
clusterClient,
getClusterClient,
license,
loggers,
features,
Expand All @@ -117,7 +117,7 @@ export class AuthorizationService {

const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
actions,
clusterClient,
getClusterClient,
this.applicationName
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ const mockActions = {
const savedObjectTypes = ['foo-type', 'bar-type'];

const createMockClusterClient = (response: any) => {
const mockScopedClusterClient = elasticsearchServiceMock.createLegacyScopedClusterClient();
mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(response);
const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
mockScopedClusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValue({
body: response,
} as any);

const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
mockClusterClient.asScoped.mockReturnValue(mockScopedClusterClient);

return { mockClusterClient, mockScopedClusterClient };
Expand All @@ -45,7 +47,7 @@ describe('#atSpace', () => {
);
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
mockActions,
mockClusterClient,
() => Promise.resolve(mockClusterClient),
application
);
const request = httpServerMock.createKibanaRequest();
Expand All @@ -70,7 +72,7 @@ describe('#atSpace', () => {
}));

expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request);
expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', {
expect(mockScopedClusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({
body: {
cluster: options.elasticsearchPrivileges?.cluster,
index: expectedIndexPrivilegePayload,
Expand Down Expand Up @@ -891,7 +893,7 @@ describe('#atSpaces', () => {
);
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
mockActions,
mockClusterClient,
() => Promise.resolve(mockClusterClient),
application
);
const request = httpServerMock.createKibanaRequest();
Expand All @@ -916,7 +918,7 @@ describe('#atSpaces', () => {
}));

expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request);
expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', {
expect(mockScopedClusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({
body: {
cluster: options.elasticsearchPrivileges?.cluster,
index: expectedIndexPrivilegePayload,
Expand Down Expand Up @@ -2095,7 +2097,7 @@ describe('#globally', () => {
);
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
mockActions,
mockClusterClient,
() => Promise.resolve(mockClusterClient),
application
);
const request = httpServerMock.createKibanaRequest();
Expand All @@ -2120,7 +2122,7 @@ describe('#globally', () => {
}));

expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request);
expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', {
expect(mockScopedClusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({
body: {
cluster: options.elasticsearchPrivileges?.cluster,
index: expectedIndexPrivilegePayload,
Expand Down
11 changes: 6 additions & 5 deletions x-pack/plugins/security/server/authorization/check_privileges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { pick, transform, uniq } from 'lodash';
import { ILegacyClusterClient, KibanaRequest } from '../../../../../src/core/server';
import { IClusterClient, KibanaRequest } from '../../../../../src/core/server';
import { GLOBAL_RESOURCE } from '../../common/constants';
import { ResourceSerializer } from './resource_serializer';
import {
Expand All @@ -24,7 +24,7 @@ interface CheckPrivilegesActions {

export function checkPrivilegesWithRequestFactory(
actions: CheckPrivilegesActions,
clusterClient: ILegacyClusterClient,
getClusterClient: () => Promise<IClusterClient>,
applicationName: string
) {
const hasIncompatibleVersion = (
Expand All @@ -47,9 +47,10 @@ export function checkPrivilegesWithRequestFactory(
: [];
const allApplicationPrivileges = uniq([actions.version, actions.login, ...kibanaPrivileges]);

const hasPrivilegesResponse = (await clusterClient
const clusterClient = await getClusterClient();
const { body: hasPrivilegesResponse } = await clusterClient
.asScoped(request)
.callAsCurrentUser('shield.hasPrivileges', {
.asCurrentUser.security.hasPrivileges<HasPrivilegesResponse>({
body: {
cluster: privileges.elasticsearch?.cluster,
index: Object.entries(privileges.elasticsearch?.index ?? {}).map(
Expand All @@ -62,7 +63,7 @@ export function checkPrivilegesWithRequestFactory(
{ application: applicationName, resources, privileges: allApplicationPrivileges },
],
},
})) as HasPrivilegesResponse;
});

validateEsPrivilegeResponse(
hasPrivilegesResponse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
/* eslint-disable @typescript-eslint/naming-convention */

import { ILegacyClusterClient, Logger } from 'kibana/server';
import { Logger } from 'kibana/server';
import { RawKibanaPrivileges } from '../../common/model';
import { registerPrivilegesWithCluster } from './register_privileges_with_cluster';

Expand Down Expand Up @@ -33,29 +33,33 @@ const registerPrivilegesWithClusterTest = (
}
) => {
const createExpectUpdatedPrivileges = (
mockClusterClient: jest.Mocked<ILegacyClusterClient>,
mockClusterClient: ReturnType<typeof elasticsearchServiceMock.createClusterClient>,
mockLogger: jest.Mocked<Logger>,
error: Error
) => {
return (postPrivilegesBody: any, deletedPrivileges: string[] = []) => {
expect(error).toBeUndefined();
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledTimes(
2 + deletedPrivileges.length
);
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith('shield.getPrivilege', {
privilege: application,
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenCalledTimes(1);
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenCalledWith({
application,
});
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith('shield.postPrivileges', {

expect(mockClusterClient.asInternalUser.security.putPrivileges).toHaveBeenCalledTimes(1);
expect(mockClusterClient.asInternalUser.security.putPrivileges).toHaveBeenCalledWith({
body: postPrivilegesBody,
});

expect(mockClusterClient.asInternalUser.security.deletePrivileges).toHaveBeenCalledTimes(
deletedPrivileges.length
);
for (const deletedPrivilege of deletedPrivileges) {
expect(mockLogger.debug).toHaveBeenCalledWith(
`Deleting Kibana Privilege ${deletedPrivilege} from Elasticsearch for ${application}`
);
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith(
'shield.deletePrivilege',
{ application, privilege: deletedPrivilege }
);
expect(mockClusterClient.asInternalUser.security.deletePrivileges).toHaveBeenCalledWith({
application,
name: deletedPrivilege,
});
}

expect(mockLogger.debug).toHaveBeenCalledWith(
Expand All @@ -68,15 +72,15 @@ const registerPrivilegesWithClusterTest = (
};

const createExpectDidntUpdatePrivileges = (
mockClusterClient: jest.Mocked<ILegacyClusterClient>,
mockClusterClient: ReturnType<typeof elasticsearchServiceMock.createClusterClient>,
mockLogger: Logger,
error: Error
) => {
return () => {
expect(error).toBeUndefined();
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledTimes(1);
expect(mockClusterClient.callAsInternalUser).toHaveBeenLastCalledWith('shield.getPrivilege', {
privilege: application,
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenCalledTimes(1);
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenLastCalledWith({
application,
});

expect(mockLogger.debug).toHaveBeenCalledWith(
Expand All @@ -101,36 +105,25 @@ const registerPrivilegesWithClusterTest = (
};

test(description, async () => {
const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
mockClusterClient.callAsInternalUser.mockImplementation(async (api) => {
switch (api) {
case 'shield.getPrivilege': {
if (throwErrorWhenGettingPrivileges) {
throw throwErrorWhenGettingPrivileges;
}

// ES returns an empty object if we don't have any privileges
if (!existingPrivileges) {
return {};
}
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
mockClusterClient.asInternalUser.security.getPrivileges.mockImplementation((async () => {
if (throwErrorWhenGettingPrivileges) {
throw throwErrorWhenGettingPrivileges;
}

return existingPrivileges;
}
case 'shield.deletePrivilege': {
break;
}
case 'shield.postPrivileges': {
if (throwErrorWhenPuttingPrivileges) {
throw throwErrorWhenPuttingPrivileges;
}
// ES returns an empty object if we don't have any privileges
if (!existingPrivileges) {
return { body: {} };
}

return;
}
default: {
expect(true).toBe(false);
}
return { body: existingPrivileges };
}) as any);
mockClusterClient.asInternalUser.security.putPrivileges.mockImplementation((async () => {
if (throwErrorWhenPuttingPrivileges) {
throw throwErrorWhenPuttingPrivileges;
}
});
}) as any);

const mockLogger = loggingSystemMock.create().get() as jest.Mocked<Logger>;

let error;
Expand Down
Loading