Skip to content

Commit 324996e

Browse files
authored
Allow fleet-server service account to setup Fleet (#78192)
This PR adds necessary application privilege for Kibana to allow fleet-server service account to initiate the Fleet setup process. Resolves: #78078
1 parent abe0c06 commit 324996e

File tree

6 files changed

+62
-5
lines changed

6 files changed

+62
-5
lines changed

x-pack/docs/en/rest-api/security/get-service-accounts.asciidoc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,17 @@ GET /_security/service/elastic/fleet-server
9797
"allow_restricted_indices": true
9898
}
9999
],
100-
"applications": [],
100+
"applications": [
101+
{
102+
"application" : "kibana-*",
103+
"privileges" : [
104+
"reserved_fleet-setup"
105+
],
106+
"resources" : [
107+
"*"
108+
]
109+
}
110+
],
101111
"run_as": [],
102112
"metadata": {},
103113
"transient_metadata": {

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ public static RoleDescriptor kibanaSystemRoleDescriptor(String name) {
367367
"manage_pipeline", "manage_ilm",
368368
// For the endpoint package that ships a transform
369369
"manage_transform",
370-
InvalidateApiKeyAction.NAME, "grant_api_key",
370+
InvalidateApiKeyAction.NAME, "grant_api_key", "manage_own_api_key",
371371
GetBuiltinPrivilegesAction.NAME, "delegate_pki",
372372
// To facilitate ML UI functionality being controlled using Kibana security privileges
373373
"manage_ml",

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@
9292
import org.elasticsearch.xpack.core.ml.action.ExplainDataFrameAnalyticsAction;
9393
import org.elasticsearch.xpack.core.ml.action.FinalizeJobExecutionAction;
9494
import org.elasticsearch.xpack.core.rollup.action.GetRollupIndexCapsAction;
95+
import org.elasticsearch.xpack.core.security.action.CreateApiKeyAction;
96+
import org.elasticsearch.xpack.core.security.action.CreateApiKeyRequest;
97+
import org.elasticsearch.xpack.core.security.action.GetApiKeyRequest;
98+
import org.elasticsearch.xpack.core.security.action.apikey.QueryApiKeyRequest;
9599
import org.elasticsearch.xpack.core.textstructure.action.FindStructureAction;
96100
import org.elasticsearch.xpack.core.ml.action.FlushJobAction;
97101
import org.elasticsearch.xpack.core.ml.action.ForecastJobAction;
@@ -375,6 +379,17 @@ public void testKibanaSystemRole() {
375379
// API keys
376380
assertThat(kibanaRole.cluster().check(InvalidateApiKeyAction.NAME, request, authentication), is(true));
377381
assertThat(kibanaRole.cluster().check(GrantApiKeyAction.NAME, request, authentication), is(true));
382+
final CreateApiKeyRequest createApiKeyRequest = new CreateApiKeyRequest(randomAlphaOfLength(8), null, null);
383+
assertThat(kibanaRole.cluster().check(CreateApiKeyAction.NAME, createApiKeyRequest, authentication), is(true));
384+
// Can only get and query its own API keys
385+
assertThat(kibanaRole.cluster().check(CreateApiKeyAction.NAME, new GetApiKeyRequest(), authentication), is(false));
386+
assertThat(kibanaRole.cluster().check(CreateApiKeyAction.NAME,
387+
new GetApiKeyRequest(null, null, null, null, true), authentication),
388+
is(true));
389+
final QueryApiKeyRequest queryApiKeyRequest = new QueryApiKeyRequest();
390+
assertThat(kibanaRole.cluster().check(CreateApiKeyAction.NAME, queryApiKeyRequest, authentication), is(false));
391+
queryApiKeyRequest.setFilterForCurrentUser();
392+
assertThat(kibanaRole.cluster().check(CreateApiKeyAction.NAME, queryApiKeyRequest, authentication), is(true));
378393

379394
// ML
380395
assertRoleHasManageMl(kibanaRole);

x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,17 @@ public class ServiceAccountIT extends ESRestTestCase {
113113
+ " \"allow_restricted_indices\": true\n"
114114
+ " }\n"
115115
+ " ],\n"
116-
+ " \"applications\": [],\n"
116+
+ " \"applications\": ["
117+
+ " {\n"
118+
+ " \"application\" : \"kibana-*\",\n"
119+
+ " \"privileges\" : [\n"
120+
+ " \"reserved_fleet-setup\"\n"
121+
+ " ],\n"
122+
+ " \"resources\" : [\n"
123+
+ " \"*\"\n"
124+
+ " ]\n"
125+
+ " }"
126+
+ " ],\n"
117127
+ " \"run_as\": [],\n"
118128
+ " \"metadata\": {},\n"
119129
+ " \"transient_metadata\": {\n"

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccounts.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ final class ElasticServiceAccounts {
3939
.allowRestrictedIndices(true)
4040
.build()
4141
},
42-
null,
42+
new RoleDescriptor.ApplicationResourcePrivileges[]{
43+
RoleDescriptor.ApplicationResourcePrivileges.builder()
44+
.application("kibana-*").resources("*").privileges("reserved_fleet-setup").build()
45+
},
4346
null,
4447
null,
4548
null,

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccountsTests.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
import org.elasticsearch.xpack.core.security.authc.Authentication;
9797
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
9898
import org.elasticsearch.xpack.core.security.authz.permission.Role;
99+
import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege;
99100
import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore;
100101
import org.elasticsearch.xpack.core.security.user.KibanaSystemUser;
101102
import org.elasticsearch.xpack.core.security.user.User;
@@ -127,7 +128,7 @@ public void testKibanaSystemPrivileges() {
127128
assertThat(serviceAccountRoleDescriptor.getMetadata(), equalTo(reservedRolesStoreRoleDescriptor.getMetadata()));
128129
}
129130

130-
public void testElasticFleetPrivileges() {
131+
public void testElasticFleetServerPrivileges() {
131132
final Role role = Role.builder(
132133
ElasticServiceAccounts.ACCOUNTS.get("elastic/fleet-server").roleDescriptor(), null, RESTRICTED_INDICES_AUTOMATON).build();
133134
final Authentication authentication = mock(Authentication.class);
@@ -187,6 +188,24 @@ public void testElasticFleetPrivileges() {
187188
assertThat(role.indices().allowedIndicesMatcher(UpdateSettingsAction.NAME).test(dotFleetIndex), is(false));
188189
assertThat(role.indices().allowedIndicesMatcher("indices:foo").test(dotFleetIndex), is(false));
189190
});
191+
192+
final String kibanaApplication = "kibana-" + randomFrom(randomAlphaOfLengthBetween(8, 24), ".kibana");
193+
final String privilegeName = randomAlphaOfLengthBetween(3, 16);
194+
assertThat(role.application().grants(
195+
new ApplicationPrivilege(
196+
kibanaApplication, privilegeName, "reserved_fleet-setup"), "*"),
197+
is(true));
198+
199+
final String otherApplication = randomValueOtherThanMany(s -> s.startsWith("kibana"),
200+
() -> randomAlphaOfLengthBetween(3, 8)) + "-" + randomAlphaOfLengthBetween(8, 24);
201+
assertThat(role.application().grants(
202+
new ApplicationPrivilege(otherApplication, privilegeName, "reserved_fleet-setup"), "*"),
203+
is(false));
204+
205+
assertThat(role.application().grants(
206+
new ApplicationPrivilege(kibanaApplication, privilegeName,
207+
randomArray(1, 5, String[]::new, () -> randomAlphaOfLengthBetween(3, 16))), "*"),
208+
is(false));
190209
}
191210

192211
public void testElasticServiceAccount() {

0 commit comments

Comments
 (0)