Skip to content

Commit b710b81

Browse files
authored
[7.x] Migrate privilege/role/user-related operations to a new Elasticsearch client. (#85015)
1 parent 3b50370 commit b710b81

File tree

35 files changed

+228
-411
lines changed

35 files changed

+228
-411
lines changed

x-pack/plugins/security/server/authorization/authorization_service.test.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ afterEach(() => {
5555
});
5656

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

6666
const authorizationService = new AuthorizationService();
67+
const getClusterClient = () => Promise.resolve(mockClusterClient);
6768
const authz = authorizationService.setup({
6869
http: mockCoreSetup.http,
6970
capabilities: mockCoreSetup.capabilities,
70-
clusterClient: mockClusterClient,
71+
getClusterClient,
7172
license: mockLicense,
7273
loggers: loggingSystemMock.create(),
7374
kibanaIndexName,
@@ -84,7 +85,7 @@ it(`#setup returns exposed services`, () => {
8485
expect(authz.checkPrivilegesWithRequest).toBe(mockCheckPrivilegesWithRequest);
8586
expect(checkPrivilegesWithRequestFactory).toHaveBeenCalledWith(
8687
authz.actions,
87-
mockClusterClient,
88+
getClusterClient,
8889
authz.applicationName
8990
);
9091

@@ -119,14 +120,14 @@ describe('#start', () => {
119120
beforeEach(() => {
120121
statusSubject = new Subject<OnlineStatusRetryScheduler>();
121122

122-
const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
123+
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
123124
const mockCoreSetup = coreMock.createSetup();
124125

125126
const authorizationService = new AuthorizationService();
126127
authorizationService.setup({
127128
http: mockCoreSetup.http,
128129
capabilities: mockCoreSetup.capabilities,
129-
clusterClient: mockClusterClient,
130+
getClusterClient: () => Promise.resolve(mockClusterClient),
130131
license: licenseMock.create(),
131132
loggers: loggingSystemMock.create(),
132133
kibanaIndexName,
@@ -190,15 +191,15 @@ describe('#start', () => {
190191
});
191192

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

197198
const authorizationService = new AuthorizationService();
198199
authorizationService.setup({
199200
http: mockCoreSetup.http,
200201
capabilities: mockCoreSetup.capabilities,
201-
clusterClient: mockClusterClient,
202+
getClusterClient: () => Promise.resolve(mockClusterClient),
202203
license: licenseMock.create(),
203204
loggers: loggingSystemMock.create(),
204205
kibanaIndexName,

x-pack/plugins/security/server/authorization/authorization_service.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import type { Capabilities as UICapabilities } from '../../../../../src/core/typ
1616
import {
1717
LoggerFactory,
1818
KibanaRequest,
19-
ILegacyClusterClient,
2019
Logger,
2120
HttpServiceSetup,
2221
CapabilitiesSetup,
22+
IClusterClient,
2323
} from '../../../../../src/core/server';
2424

2525
import {
@@ -63,7 +63,7 @@ interface AuthorizationServiceSetupParams {
6363
buildNumber: number;
6464
http: HttpServiceSetup;
6565
capabilities: CapabilitiesSetup;
66-
clusterClient: ILegacyClusterClient;
66+
getClusterClient: () => Promise<IClusterClient>;
6767
license: SecurityLicense;
6868
loggers: LoggerFactory;
6969
features: FeaturesPluginSetup;
@@ -74,7 +74,7 @@ interface AuthorizationServiceSetupParams {
7474

7575
interface AuthorizationServiceStartParams {
7676
features: FeaturesPluginStart;
77-
clusterClient: ILegacyClusterClient;
77+
clusterClient: IClusterClient;
7878
online$: Observable<OnlineStatusRetryScheduler>;
7979
}
8080

@@ -100,7 +100,7 @@ export class AuthorizationService {
100100
capabilities,
101101
packageVersion,
102102
buildNumber,
103-
clusterClient,
103+
getClusterClient,
104104
license,
105105
loggers,
106106
features,
@@ -117,7 +117,7 @@ export class AuthorizationService {
117117

118118
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
119119
actions,
120-
clusterClient,
120+
getClusterClient,
121121
this.applicationName
122122
);
123123

x-pack/plugins/security/server/authorization/check_privileges.test.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ const mockActions = {
2121
const savedObjectTypes = ['foo-type', 'bar-type'];
2222

2323
const createMockClusterClient = (response: any) => {
24-
const mockScopedClusterClient = elasticsearchServiceMock.createLegacyScopedClusterClient();
25-
mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(response);
24+
const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
25+
mockScopedClusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValue({
26+
body: response,
27+
} as any);
2628

27-
const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
29+
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
2830
mockClusterClient.asScoped.mockReturnValue(mockScopedClusterClient);
2931

3032
return { mockClusterClient, mockScopedClusterClient };
@@ -45,7 +47,7 @@ describe('#atSpace', () => {
4547
);
4648
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
4749
mockActions,
48-
mockClusterClient,
50+
() => Promise.resolve(mockClusterClient),
4951
application
5052
);
5153
const request = httpServerMock.createKibanaRequest();
@@ -70,7 +72,7 @@ describe('#atSpace', () => {
7072
}));
7173

7274
expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request);
73-
expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', {
75+
expect(mockScopedClusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({
7476
body: {
7577
cluster: options.elasticsearchPrivileges?.cluster,
7678
index: expectedIndexPrivilegePayload,
@@ -891,7 +893,7 @@ describe('#atSpaces', () => {
891893
);
892894
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
893895
mockActions,
894-
mockClusterClient,
896+
() => Promise.resolve(mockClusterClient),
895897
application
896898
);
897899
const request = httpServerMock.createKibanaRequest();
@@ -916,7 +918,7 @@ describe('#atSpaces', () => {
916918
}));
917919

918920
expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request);
919-
expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', {
921+
expect(mockScopedClusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({
920922
body: {
921923
cluster: options.elasticsearchPrivileges?.cluster,
922924
index: expectedIndexPrivilegePayload,
@@ -2095,7 +2097,7 @@ describe('#globally', () => {
20952097
);
20962098
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
20972099
mockActions,
2098-
mockClusterClient,
2100+
() => Promise.resolve(mockClusterClient),
20992101
application
21002102
);
21012103
const request = httpServerMock.createKibanaRequest();
@@ -2120,7 +2122,7 @@ describe('#globally', () => {
21202122
}));
21212123

21222124
expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request);
2123-
expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', {
2125+
expect(mockScopedClusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({
21242126
body: {
21252127
cluster: options.elasticsearchPrivileges?.cluster,
21262128
index: expectedIndexPrivilegePayload,

x-pack/plugins/security/server/authorization/check_privileges.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import { pick, transform, uniq } from 'lodash';
8-
import { ILegacyClusterClient, KibanaRequest } from '../../../../../src/core/server';
8+
import { IClusterClient, KibanaRequest } from '../../../../../src/core/server';
99
import { GLOBAL_RESOURCE } from '../../common/constants';
1010
import { ResourceSerializer } from './resource_serializer';
1111
import {
@@ -24,7 +24,7 @@ interface CheckPrivilegesActions {
2424

2525
export function checkPrivilegesWithRequestFactory(
2626
actions: CheckPrivilegesActions,
27-
clusterClient: ILegacyClusterClient,
27+
getClusterClient: () => Promise<IClusterClient>,
2828
applicationName: string
2929
) {
3030
const hasIncompatibleVersion = (
@@ -47,9 +47,10 @@ export function checkPrivilegesWithRequestFactory(
4747
: [];
4848
const allApplicationPrivileges = uniq([actions.version, actions.login, ...kibanaPrivileges]);
4949

50-
const hasPrivilegesResponse = (await clusterClient
50+
const clusterClient = await getClusterClient();
51+
const { body: hasPrivilegesResponse } = await clusterClient
5152
.asScoped(request)
52-
.callAsCurrentUser('shield.hasPrivileges', {
53+
.asCurrentUser.security.hasPrivileges<HasPrivilegesResponse>({
5354
body: {
5455
cluster: privileges.elasticsearch?.cluster,
5556
index: Object.entries(privileges.elasticsearch?.index ?? {}).map(
@@ -62,7 +63,7 @@ export function checkPrivilegesWithRequestFactory(
6263
{ application: applicationName, resources, privileges: allApplicationPrivileges },
6364
],
6465
},
65-
})) as HasPrivilegesResponse;
66+
});
6667

6768
validateEsPrivilegeResponse(
6869
hasPrivilegesResponse,

x-pack/plugins/security/server/authorization/register_privileges_with_cluster.test.ts

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
/* eslint-disable @typescript-eslint/naming-convention */
77

8-
import { ILegacyClusterClient, Logger } from 'kibana/server';
8+
import { Logger } from 'kibana/server';
99
import { RawKibanaPrivileges } from '../../common/model';
1010
import { registerPrivilegesWithCluster } from './register_privileges_with_cluster';
1111

@@ -33,29 +33,33 @@ const registerPrivilegesWithClusterTest = (
3333
}
3434
) => {
3535
const createExpectUpdatedPrivileges = (
36-
mockClusterClient: jest.Mocked<ILegacyClusterClient>,
36+
mockClusterClient: ReturnType<typeof elasticsearchServiceMock.createClusterClient>,
3737
mockLogger: jest.Mocked<Logger>,
3838
error: Error
3939
) => {
4040
return (postPrivilegesBody: any, deletedPrivileges: string[] = []) => {
4141
expect(error).toBeUndefined();
42-
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledTimes(
43-
2 + deletedPrivileges.length
44-
);
45-
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith('shield.getPrivilege', {
46-
privilege: application,
42+
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenCalledTimes(1);
43+
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenCalledWith({
44+
application,
4745
});
48-
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith('shield.postPrivileges', {
46+
47+
expect(mockClusterClient.asInternalUser.security.putPrivileges).toHaveBeenCalledTimes(1);
48+
expect(mockClusterClient.asInternalUser.security.putPrivileges).toHaveBeenCalledWith({
4949
body: postPrivilegesBody,
5050
});
51+
52+
expect(mockClusterClient.asInternalUser.security.deletePrivileges).toHaveBeenCalledTimes(
53+
deletedPrivileges.length
54+
);
5155
for (const deletedPrivilege of deletedPrivileges) {
5256
expect(mockLogger.debug).toHaveBeenCalledWith(
5357
`Deleting Kibana Privilege ${deletedPrivilege} from Elasticsearch for ${application}`
5458
);
55-
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledWith(
56-
'shield.deletePrivilege',
57-
{ application, privilege: deletedPrivilege }
58-
);
59+
expect(mockClusterClient.asInternalUser.security.deletePrivileges).toHaveBeenCalledWith({
60+
application,
61+
name: deletedPrivilege,
62+
});
5963
}
6064

6165
expect(mockLogger.debug).toHaveBeenCalledWith(
@@ -68,15 +72,15 @@ const registerPrivilegesWithClusterTest = (
6872
};
6973

7074
const createExpectDidntUpdatePrivileges = (
71-
mockClusterClient: jest.Mocked<ILegacyClusterClient>,
75+
mockClusterClient: ReturnType<typeof elasticsearchServiceMock.createClusterClient>,
7276
mockLogger: Logger,
7377
error: Error
7478
) => {
7579
return () => {
7680
expect(error).toBeUndefined();
77-
expect(mockClusterClient.callAsInternalUser).toHaveBeenCalledTimes(1);
78-
expect(mockClusterClient.callAsInternalUser).toHaveBeenLastCalledWith('shield.getPrivilege', {
79-
privilege: application,
81+
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenCalledTimes(1);
82+
expect(mockClusterClient.asInternalUser.security.getPrivileges).toHaveBeenLastCalledWith({
83+
application,
8084
});
8185

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

103107
test(description, async () => {
104-
const mockClusterClient = elasticsearchServiceMock.createLegacyClusterClient();
105-
mockClusterClient.callAsInternalUser.mockImplementation(async (api) => {
106-
switch (api) {
107-
case 'shield.getPrivilege': {
108-
if (throwErrorWhenGettingPrivileges) {
109-
throw throwErrorWhenGettingPrivileges;
110-
}
111-
112-
// ES returns an empty object if we don't have any privileges
113-
if (!existingPrivileges) {
114-
return {};
115-
}
108+
const mockClusterClient = elasticsearchServiceMock.createClusterClient();
109+
mockClusterClient.asInternalUser.security.getPrivileges.mockImplementation((async () => {
110+
if (throwErrorWhenGettingPrivileges) {
111+
throw throwErrorWhenGettingPrivileges;
112+
}
116113

117-
return existingPrivileges;
118-
}
119-
case 'shield.deletePrivilege': {
120-
break;
121-
}
122-
case 'shield.postPrivileges': {
123-
if (throwErrorWhenPuttingPrivileges) {
124-
throw throwErrorWhenPuttingPrivileges;
125-
}
114+
// ES returns an empty object if we don't have any privileges
115+
if (!existingPrivileges) {
116+
return { body: {} };
117+
}
126118

127-
return;
128-
}
129-
default: {
130-
expect(true).toBe(false);
131-
}
119+
return { body: existingPrivileges };
120+
}) as any);
121+
mockClusterClient.asInternalUser.security.putPrivileges.mockImplementation((async () => {
122+
if (throwErrorWhenPuttingPrivileges) {
123+
throw throwErrorWhenPuttingPrivileges;
132124
}
133-
});
125+
}) as any);
126+
134127
const mockLogger = loggingSystemMock.create().get() as jest.Mocked<Logger>;
135128

136129
let error;

0 commit comments

Comments
 (0)