Skip to content

Commit ddcecd6

Browse files
authored
[8.x] [FTR] support custom native roles in serverless tests (elastic#194677) (elastic#196351)
# Backport This will backport the following commits from `main` to `8.x`: - [[FTR] support custom native roles in serverless tests (elastic#194677)](elastic#194677) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Dzmitry Lemechko","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-11T15:11:23Z","message":"[FTR] support custom native roles in serverless tests (elastic#194677)\n\n## Summary\r\n\r\nThis PR updates FTR services to support authentication with custom\r\nnative role. Few notes:\r\n- for compatibility with MKI we reserve **\"customRole\"** as a custom\r\nrole name used in tests\r\n- test user is **automatically assigned** to this role, but before login\r\nin browser/ generating cookie header or API key in each test suite\r\n**role privileges must me updated according test scenario**\r\n\r\nHow to test:\r\nI added a new test file for Search project:\r\n`x-pack/test_serverless/functional/test_suites/search/custom_role_access.ts`\r\n\r\nIt can be run locally with:\r\n```\r\n node scripts/functional_tests --config=x-pack/test_serverless/functional/test_suites/search/config.ts --grep \"With custom role\"\r\n```\r\n\r\nFTR UI test example:\r\n\r\n```ts\r\n// First set privileges for custom role\r\nawait samlAuth.setCustomRole({\r\n elasticsearch: {\r\n indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],\r\n },\r\n kibana: [\r\n {\r\n feature: {\r\n discover: ['read'],\r\n },\r\n spaces: ['*'],\r\n },\r\n ],\r\n });\r\n });\r\n\r\n// Then you can login in browser as a user with newly defined privileges\r\nawait pageObjects.svlCommonPage.loginWithCustomRole();\r\n```\r\n\r\nFTR api_integration test example:\r\n\r\n```ts\r\n// First set privileges for custom role\r\nawait samlAuth.setCustomRole({\r\n elasticsearch: {\r\n indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],\r\n },\r\n kibana: [\r\n {\r\n feature: {\r\n discover: ['read'],\r\n },\r\n spaces: ['*'],\r\n },\r\n ],\r\n });\r\n });\r\n// Then you can generate an API key with newly defined privileges\r\nconst roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('customRole');\r\n// Don't forget to invalidate the API key in the end\r\nawait samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc);\r\n```","sha":"f00ac7a8a21463e6bb4a2784c3a3884f36c62900","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","FTR","v8.16.0","backport:version"],"number":194677,"url":"https://github.com/elastic/kibana/pull/194677","mergeCommit":{"message":"[FTR] support custom native roles in serverless tests (elastic#194677)\n\n## Summary\r\n\r\nThis PR updates FTR services to support authentication with custom\r\nnative role. Few notes:\r\n- for compatibility with MKI we reserve **\"customRole\"** as a custom\r\nrole name used in tests\r\n- test user is **automatically assigned** to this role, but before login\r\nin browser/ generating cookie header or API key in each test suite\r\n**role privileges must me updated according test scenario**\r\n\r\nHow to test:\r\nI added a new test file for Search project:\r\n`x-pack/test_serverless/functional/test_suites/search/custom_role_access.ts`\r\n\r\nIt can be run locally with:\r\n```\r\n node scripts/functional_tests --config=x-pack/test_serverless/functional/test_suites/search/config.ts --grep \"With custom role\"\r\n```\r\n\r\nFTR UI test example:\r\n\r\n```ts\r\n// First set privileges for custom role\r\nawait samlAuth.setCustomRole({\r\n elasticsearch: {\r\n indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],\r\n },\r\n kibana: [\r\n {\r\n feature: {\r\n discover: ['read'],\r\n },\r\n spaces: ['*'],\r\n },\r\n ],\r\n });\r\n });\r\n\r\n// Then you can login in browser as a user with newly defined privileges\r\nawait pageObjects.svlCommonPage.loginWithCustomRole();\r\n```\r\n\r\nFTR api_integration test example:\r\n\r\n```ts\r\n// First set privileges for custom role\r\nawait samlAuth.setCustomRole({\r\n elasticsearch: {\r\n indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],\r\n },\r\n kibana: [\r\n {\r\n feature: {\r\n discover: ['read'],\r\n },\r\n spaces: ['*'],\r\n },\r\n ],\r\n });\r\n });\r\n// Then you can generate an API key with newly defined privileges\r\nconst roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('customRole');\r\n// Don't forget to invalidate the API key in the end\r\nawait samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc);\r\n```","sha":"f00ac7a8a21463e6bb4a2784c3a3884f36c62900"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/194677","number":194677,"mergeCommit":{"message":"[FTR] support custom native roles in serverless tests (elastic#194677)\n\n## Summary\r\n\r\nThis PR updates FTR services to support authentication with custom\r\nnative role. Few notes:\r\n- for compatibility with MKI we reserve **\"customRole\"** as a custom\r\nrole name used in tests\r\n- test user is **automatically assigned** to this role, but before login\r\nin browser/ generating cookie header or API key in each test suite\r\n**role privileges must me updated according test scenario**\r\n\r\nHow to test:\r\nI added a new test file for Search project:\r\n`x-pack/test_serverless/functional/test_suites/search/custom_role_access.ts`\r\n\r\nIt can be run locally with:\r\n```\r\n node scripts/functional_tests --config=x-pack/test_serverless/functional/test_suites/search/config.ts --grep \"With custom role\"\r\n```\r\n\r\nFTR UI test example:\r\n\r\n```ts\r\n// First set privileges for custom role\r\nawait samlAuth.setCustomRole({\r\n elasticsearch: {\r\n indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],\r\n },\r\n kibana: [\r\n {\r\n feature: {\r\n discover: ['read'],\r\n },\r\n spaces: ['*'],\r\n },\r\n ],\r\n });\r\n });\r\n\r\n// Then you can login in browser as a user with newly defined privileges\r\nawait pageObjects.svlCommonPage.loginWithCustomRole();\r\n```\r\n\r\nFTR api_integration test example:\r\n\r\n```ts\r\n// First set privileges for custom role\r\nawait samlAuth.setCustomRole({\r\n elasticsearch: {\r\n indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],\r\n },\r\n kibana: [\r\n {\r\n feature: {\r\n discover: ['read'],\r\n },\r\n spaces: ['*'],\r\n },\r\n ],\r\n });\r\n });\r\n// Then you can generate an API key with newly defined privileges\r\nconst roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('customRole');\r\n// Don't forget to invalidate the API key in the end\r\nawait samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc);\r\n```","sha":"f00ac7a8a21463e6bb4a2784c3a3884f36c62900"}},{"branch":"8.x","label":"v8.16.0","labelRegex":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
1 parent c08dbf1 commit ddcecd6

File tree

13 files changed

+319
-41
lines changed

13 files changed

+319
-41
lines changed

packages/kbn-ftr-common-functional-services/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export type {
3030
InternalRequestHeader,
3131
RoleCredentials,
3232
CookieCredentials,
33+
KibanaRoleDescriptors,
3334
} from './services/saml_auth';
3435

3536
import { SamlAuthProvider } from './services/saml_auth/saml_auth_provider';

packages/kbn-ftr-common-functional-services/services/saml_auth/get_auth_provider.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import { ServerlessAuthProvider } from './serverless/auth_provider';
1212
import { StatefulAuthProvider } from './stateful/auth_provider';
1313

1414
export interface AuthProvider {
15-
getSupportedRoleDescriptors(): Record<string, unknown>;
15+
getSupportedRoleDescriptors(): Map<string, any>;
1616
getDefaultRole(): string;
17+
isCustomRoleEnabled(): boolean;
18+
getCustomRole(): string;
1719
getRolesDefinitionPath(): string;
1820
getCommonRequestHeader(): { [key: string]: string };
1921
getInternalRequestHeader(): { [key: string]: string };

packages/kbn-ftr-common-functional-services/services/saml_auth/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,9 @@
88
*/
99

1010
export { SamlAuthProvider } from './saml_auth_provider';
11-
export type { RoleCredentials, CookieCredentials } from './saml_auth_provider';
11+
export type {
12+
RoleCredentials,
13+
CookieCredentials,
14+
KibanaRoleDescriptors,
15+
} from './saml_auth_provider';
1216
export type { InternalRequestHeader } from './default_request_headers';

packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ export interface CookieCredentials {
2727
[header: string]: string;
2828
}
2929

30+
export interface KibanaRoleDescriptors {
31+
kibana: any;
32+
elasticsearch?: any;
33+
}
34+
35+
const throwIfRoleNotSet = (role: string, customRole: string, roleDescriptors: Map<string, any>) => {
36+
if (role === customRole && !roleDescriptors.has(customRole)) {
37+
throw new Error(
38+
`Set privileges for '${customRole}' using 'samlAuth.setCustomRole' before authentication.`
39+
);
40+
}
41+
};
42+
3043
export function SamlAuthProvider({ getService }: FtrProviderContext) {
3144
const config = getService('config');
3245
const log = getService('log');
@@ -35,9 +48,8 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) {
3548

3649
const authRoleProvider = getAuthProvider({ config });
3750
const supportedRoleDescriptors = authRoleProvider.getSupportedRoleDescriptors();
38-
const supportedRoles = Object.keys(supportedRoleDescriptors);
39-
40-
const customRolesFileName: string | undefined = process.env.ROLES_FILENAME_OVERRIDE;
51+
const supportedRoles = Array.from(supportedRoleDescriptors.keys());
52+
const customRolesFileName = process.env.ROLES_FILENAME_OVERRIDE;
4153
const cloudUsersFilePath = resolve(REPO_ROOT, '.ftr', customRolesFileName ?? 'role_users.json');
4254

4355
// Sharing the instance within FTR config run means cookies are persistent for each role between tests.
@@ -61,55 +73,78 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) {
6173
const DEFAULT_ROLE = authRoleProvider.getDefaultRole();
6274
const COMMON_REQUEST_HEADERS = authRoleProvider.getCommonRequestHeader();
6375
const INTERNAL_REQUEST_HEADERS = authRoleProvider.getInternalRequestHeader();
76+
const CUSTOM_ROLE = authRoleProvider.getCustomRole();
77+
const isCustomRoleEnabled = authRoleProvider.isCustomRoleEnabled();
78+
79+
const getAdminCredentials = async () => {
80+
return await sessionManager.getApiCredentialsForRole('admin');
81+
};
82+
83+
const createApiKeyPayload = (role: string, roleDescriptors: any) => {
84+
return {
85+
name: `myTestApiKey_${role}`,
86+
metadata: {},
87+
...(role === CUSTOM_ROLE
88+
? { kibana_role_descriptors: roleDescriptors }
89+
: { role_descriptors: roleDescriptors }),
90+
};
91+
};
6492

6593
return {
6694
async getInteractiveUserSessionCookieWithRoleScope(role: string) {
95+
// Custom role has no descriptors by default, check if it was added before authentication
96+
throwIfRoleNotSet(role, CUSTOM_ROLE, supportedRoleDescriptors);
6797
return sessionManager.getInteractiveUserSessionCookieWithRoleScope(role);
6898
},
99+
69100
async getM2MApiCookieCredentialsWithRoleScope(role: string): Promise<CookieCredentials> {
101+
// Custom role has no descriptors by default, check if it was added before authentication
102+
throwIfRoleNotSet(role, CUSTOM_ROLE, supportedRoleDescriptors);
70103
return sessionManager.getApiCredentialsForRole(role);
71104
},
105+
72106
async getEmail(role: string) {
73107
return sessionManager.getEmail(role);
74108
},
75109

76110
async getUserData(role: string) {
77111
return sessionManager.getUserData(role);
78112
},
113+
79114
async createM2mApiKeyWithDefaultRoleScope() {
80-
log.debug(`Creating api key for default role: [${this.DEFAULT_ROLE}]`);
81-
return this.createM2mApiKeyWithRoleScope(this.DEFAULT_ROLE);
115+
log.debug(`Creating API key for default role: [${DEFAULT_ROLE}]`);
116+
return this.createM2mApiKeyWithRoleScope(DEFAULT_ROLE);
82117
},
118+
83119
async createM2mApiKeyWithRoleScope(role: string): Promise<RoleCredentials> {
84120
// Get admin credentials in order to create the API key
85-
const adminCookieHeader = await this.getM2MApiCookieCredentialsWithRoleScope('admin');
86-
87-
// Get the role descrtiptor for the role
121+
const adminCookieHeader = await getAdminCredentials();
88122
let roleDescriptors = {};
123+
89124
if (role !== 'admin') {
90-
const roleDescriptor = supportedRoleDescriptors[role];
125+
if (role === CUSTOM_ROLE && !isCustomRoleEnabled) {
126+
throw new Error(`Custom roles are not supported for the current deployment`);
127+
}
128+
const roleDescriptor = supportedRoleDescriptors.get(role);
91129
if (!roleDescriptor) {
92-
throw new Error(`Cannot create API key for non-existent role "${role}"`);
130+
throw new Error(
131+
role === CUSTOM_ROLE
132+
? `Before creating API key for '${CUSTOM_ROLE}', use 'samlAuth.setCustomRole' to set the role privileges`
133+
: `Cannot create API key for non-existent role "${role}"`
134+
);
93135
}
94136
log.debug(
95-
`Creating api key for ${role} role with the following privileges ${JSON.stringify(
96-
roleDescriptor
97-
)}`
137+
`Creating API key for ${role} with privileges: ${JSON.stringify(roleDescriptor)}`
98138
);
99-
roleDescriptors = {
100-
[role]: roleDescriptor,
101-
};
139+
roleDescriptors = { [role]: roleDescriptor };
102140
}
103141

142+
const payload = createApiKeyPayload(role, roleDescriptors);
104143
const response = await supertestWithoutAuth
105144
.post('/internal/security/api_key')
106145
.set(INTERNAL_REQUEST_HEADERS)
107146
.set(adminCookieHeader)
108-
.send({
109-
name: 'myTestApiKey',
110-
metadata: {},
111-
role_descriptors: roleDescriptors,
112-
});
147+
.send(payload);
113148

114149
if (response.status !== 200) {
115150
throw new Error(
@@ -120,38 +155,59 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) {
120155
const apiKey = response.body;
121156
const apiKeyHeader = { Authorization: 'ApiKey ' + apiKey.encoded };
122157

123-
log.debug(`Created api key for role: [${role}]`);
158+
log.debug(`Created API key for role: [${role}]`);
124159
return { apiKey, apiKeyHeader };
125160
},
161+
126162
async invalidateM2mApiKeyWithRoleScope(roleCredentials: RoleCredentials) {
127163
// Get admin credentials in order to invalidate the API key
128-
const adminCookieHeader = await this.getM2MApiCookieCredentialsWithRoleScope('admin');
129-
130-
const requestBody = {
131-
apiKeys: [
132-
{
133-
id: roleCredentials.apiKey.id,
134-
name: roleCredentials.apiKey.name,
135-
},
136-
],
137-
isAdmin: true,
138-
};
164+
const adminCookieHeader = await getAdminCredentials();
139165

140166
const { status } = await supertestWithoutAuth
141167
.post('/internal/security/api_key/invalidate')
142168
.set(INTERNAL_REQUEST_HEADERS)
143169
.set(adminCookieHeader)
144-
.send(requestBody);
170+
.send({
171+
apiKeys: [{ id: roleCredentials.apiKey.id, name: roleCredentials.apiKey.name }],
172+
isAdmin: true,
173+
});
145174

146175
expect(status).to.be(200);
147176
},
177+
178+
async setCustomRole(descriptors: KibanaRoleDescriptors) {
179+
if (!isCustomRoleEnabled) {
180+
throw new Error(`Custom roles are not supported for the current deployment`);
181+
}
182+
log.debug(`Updating role ${CUSTOM_ROLE}`);
183+
const adminCookieHeader = await getAdminCredentials();
184+
185+
const customRoleDescriptors = {
186+
kibana: descriptors.kibana,
187+
elasticsearch: descriptors.elasticsearch ?? [],
188+
};
189+
190+
const { status } = await supertestWithoutAuth
191+
.put(`/api/security/role/${CUSTOM_ROLE}`)
192+
.set(INTERNAL_REQUEST_HEADERS)
193+
.set(adminCookieHeader)
194+
.send(customRoleDescriptors);
195+
196+
expect(status).to.be(204);
197+
198+
// Update descriptors for custome role, it will be used to create API key
199+
supportedRoleDescriptors.set(CUSTOM_ROLE, customRoleDescriptors);
200+
},
201+
148202
getCommonRequestHeader() {
149203
return COMMON_REQUEST_HEADERS;
150204
},
151205

152206
getInternalRequestHeader(): InternalRequestHeader {
153207
return INTERNAL_REQUEST_HEADERS;
154208
},
209+
155210
DEFAULT_ROLE,
211+
CUSTOM_ROLE,
156212
};
157213
}

packages/kbn-ftr-common-functional-services/services/saml_auth/serverless/auth_provider.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const projectDefaultRoles = new Map<string, Role>([
2424
['oblt', 'editor'],
2525
]);
2626

27+
const projectTypesWithCustomRolesEnabled = ['es', 'security'];
28+
2729
const getDefaultServerlessRole = (projectType: string) => {
2830
if (projectDefaultRoles.has(projectType)) {
2931
return projectDefaultRoles.get(projectType)!;
@@ -50,18 +52,39 @@ export class ServerlessAuthProvider implements AuthProvider {
5052
this.rolesDefinitionPath = resolve(SERVERLESS_ROLES_ROOT_PATH, this.projectType, 'roles.yml');
5153
}
5254

53-
getSupportedRoleDescriptors(): Record<string, unknown> {
54-
return readRolesDescriptorsFromResource(this.rolesDefinitionPath);
55+
getSupportedRoleDescriptors() {
56+
const roleDescriptors = new Map<string, any>(
57+
Object.entries(
58+
readRolesDescriptorsFromResource(this.rolesDefinitionPath) as Record<string, unknown>
59+
)
60+
);
61+
// Adding custom role to the map without privileges, so it can be later updated and used in the tests
62+
if (this.isCustomRoleEnabled()) {
63+
roleDescriptors.set(this.getCustomRole(), null);
64+
}
65+
return roleDescriptors;
5566
}
67+
5668
getDefaultRole(): string {
5769
return getDefaultServerlessRole(this.projectType);
5870
}
71+
72+
isCustomRoleEnabled() {
73+
return projectTypesWithCustomRolesEnabled.includes(this.projectType);
74+
}
75+
76+
getCustomRole() {
77+
return 'customRole';
78+
}
79+
5980
getRolesDefinitionPath(): string {
6081
return this.rolesDefinitionPath;
6182
}
83+
6284
getCommonRequestHeader() {
6385
return COMMON_REQUEST_HEADERS;
6486
}
87+
6588
getInternalRequestHeader() {
6689
return getServerlessInternalRequestHeaders();
6790
}

packages/kbn-ftr-common-functional-services/services/saml_auth/stateful/auth_provider.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,31 @@ import {
1818

1919
export class StatefulAuthProvider implements AuthProvider {
2020
private readonly rolesDefinitionPath = resolve(REPO_ROOT, STATEFUL_ROLES_ROOT_PATH, 'roles.yml');
21-
getSupportedRoleDescriptors(): Record<string, unknown> {
22-
return readRolesDescriptorsFromResource(this.rolesDefinitionPath);
21+
22+
getSupportedRoleDescriptors() {
23+
const roleDescriptors = new Map<string, any>(
24+
Object.entries(
25+
readRolesDescriptorsFromResource(this.rolesDefinitionPath) as Record<string, unknown>
26+
)
27+
);
28+
// no privileges set by default
29+
roleDescriptors.set(this.getCustomRole(), null);
30+
31+
return roleDescriptors;
2332
}
33+
2434
getDefaultRole() {
2535
return 'editor';
2636
}
37+
38+
isCustomRoleEnabled() {
39+
return true;
40+
}
41+
42+
getCustomRole() {
43+
return 'customRole';
44+
}
45+
2746
getRolesDefinitionPath() {
2847
return this.rolesDefinitionPath;
2948
}

x-pack/test/api_integration/deployment_agnostic/default_configs/serverless.config.base.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ export function createServerlessTestConfig<T extends DeploymentAgnosticCommonSer
100100
...svlSharedConfig.get('esTestCluster'),
101101
serverArgs: [
102102
...svlSharedConfig.get('esTestCluster.serverArgs'),
103+
// custom native roles are enabled only for search and security projects
104+
...(options.serverlessProject !== 'oblt'
105+
? ['xpack.security.authc.native_roles.enabled=true']
106+
: []),
103107
...esServerArgsFromController[options.serverlessProject],
104108
],
105109
},
@@ -109,6 +113,10 @@ export function createServerlessTestConfig<T extends DeploymentAgnosticCommonSer
109113
...svlSharedConfig.get('kbnTestServer.serverArgs'),
110114
...kbnServerArgsFromController[options.serverlessProject],
111115
`--serverless=${options.serverlessProject}`,
116+
// custom native roles are enabled only for search and security projects
117+
...(options.serverlessProject !== 'oblt'
118+
? ['--xpack.security.roleManagementEnabled=true']
119+
: []),
112120
],
113121
},
114122
testFiles: options.testFiles,

x-pack/test_serverless/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,59 @@ describe("my internal APIs test suite", async function() {
202202
});
203203
```
204204

205+
#### Testing with custom roles
206+
207+
With custom native roles now enabled for the Security and Search projects on MKI, the FTR supports
208+
defining and authenticating with custom roles in both UI functional tests and API integration tests.
209+
210+
For compatibility with MKI, the role name `customRole` is reserved for use in tests. The test user is automatically assigned to this role, but before logging in via the browser, generating a cookie header, or creating an API key in each test suite, the role’s privileges must be updated.
211+
212+
Note: We are still working on a solution to run these tests against MKI. In the meantime, please tag the suite with `skipMKI`.
213+
214+
FTR UI test example:
215+
```
216+
// First, set privileges for the custom role
217+
await samlAuth.setCustomRole({
218+
elasticsearch: {
219+
indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],
220+
},
221+
kibana: [
222+
{
223+
feature: {
224+
discover: ['read'],
225+
},
226+
spaces: ['*'],
227+
},
228+
],
229+
});
230+
// Then, log in via the browser as a user with the newly defined privileges
231+
await pageObjects.svlCommonPage.loginWithCustomRole();
232+
```
233+
234+
FTR api_integration test example:
235+
```
236+
// First, set privileges for the custom role
237+
await samlAuth.setCustomRole({
238+
elasticsearch: {
239+
indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],
240+
},
241+
kibana: [
242+
{
243+
feature: {
244+
discover: ['read'],
245+
},
246+
spaces: ['*'],
247+
},
248+
],
249+
});
250+
251+
// Then, generate an API key with the newly defined privileges
252+
const roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('customRole');
253+
254+
// Remember to invalidate the API key after use
255+
await samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc);
256+
```
257+
205258
### Testing with feature flags
206259

207260
**tl;dr:** Tests specific to functionality behind a feature flag need special

0 commit comments

Comments
 (0)