diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ApplicationPrivilege.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ApplicationPrivilege.java index 52f283b6b4377..2378f6037adf4 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ApplicationPrivilege.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ApplicationPrivilege.java @@ -192,8 +192,6 @@ private static ApplicationPrivilege resolve(String application, Set name ApplicationPrivilegeDescriptor descriptor = lookup.get(name); if (descriptor != null) { patterns.addAll(descriptor.getActions()); - } else { - throw new IllegalArgumentException("unknown application privilege [" + name + "]"); } } else { actions.add(name); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java index c4cb149992715..0c59343636553 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java @@ -48,7 +48,11 @@ private static Map initializeReservedRoles() { MetadataUtils.DEFAULT_RESERVED_METADATA)) .put("kibana_user", new RoleDescriptor("kibana_user", null, new RoleDescriptor.IndicesPrivileges[] { RoleDescriptor.IndicesPrivileges.builder().indices(".kibana*").privileges("manage", "read", "index", "delete") - .build() }, null, MetadataUtils.DEFAULT_RESERVED_METADATA)) + .build() }, new RoleDescriptor.ApplicationResourcePrivileges[] { + RoleDescriptor.ApplicationResourcePrivileges.builder() + .application("kibana-.kibana").resources("*").privileges("all").build() }, + null, null, + MetadataUtils.DEFAULT_RESERVED_METADATA, null)) .put("monitoring_user", new RoleDescriptor("monitoring_user", new String[] { "cluster:monitor/main" }, new RoleDescriptor.IndicesPrivileges[] { @@ -75,11 +79,15 @@ private static Map initializeReservedRoles() { "kibana_dashboard_only_user", null, new RoleDescriptor.IndicesPrivileges[] { - RoleDescriptor.IndicesPrivileges.builder() - .indices(".kibana*").privileges("read", "view_index_metadata").build() + RoleDescriptor.IndicesPrivileges.builder() + .indices(".kibana*").privileges("read", "view_index_metadata").build() }, - null, - MetadataUtils.DEFAULT_RESERVED_METADATA)) + new RoleDescriptor.ApplicationResourcePrivileges[] { + RoleDescriptor.ApplicationResourcePrivileges.builder() + .application("kibana-.kibana").resources("*").privileges("read").build() }, + null, null, + MetadataUtils.DEFAULT_RESERVED_METADATA, + null)) .put(KibanaUser.ROLE_NAME, new RoleDescriptor(KibanaUser.ROLE_NAME, new String[] { "monitor", "manage_index_templates", MonitoringBulkAction.NAME, "manage_saml", diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java index 5fa47dd59dd78..9cb5e25c5b8d1 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java @@ -92,6 +92,7 @@ import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl.IndexAccessControl; import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache; import org.elasticsearch.xpack.core.security.authz.permission.Role; +import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; @@ -309,6 +310,17 @@ public void testKibanaUserRole() { assertThat(kibanaUserRole.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(index), is(true)); assertThat(kibanaUserRole.indices().allowedIndicesMatcher(UpdateSettingsAction.NAME).test(index), is(true)); }); + + final String randomApplication = "kibana-" + randomAlphaOfLengthBetween(8, 24); + assertThat(kibanaUserRole.application().grants(new ApplicationPrivilege(randomApplication, "app-random", "all"), "*"), is(false)); + + final String application = "kibana-.kibana"; + assertThat(kibanaUserRole.application().grants(new ApplicationPrivilege(application, "app-foo", "foo"), "*"), is(false)); + assertThat(kibanaUserRole.application().grants(new ApplicationPrivilege(application, "app-all", "all"), "*"), is(true)); + + final String applicationWithRandomIndex = "kibana-.kibana_" + randomAlphaOfLengthBetween(8, 24); + assertThat(kibanaUserRole.application().grants(new ApplicationPrivilege(applicationWithRandomIndex, "app-random-index", "all"), + "*"), is(false)); } public void testMonitoringUserRole() { @@ -466,6 +478,19 @@ public void testKibanaDashboardOnlyUserRole() { assertThat(dashboardsOnlyUserRole.indices().allowedIndicesMatcher(GetIndexAction.NAME).test(index), is(true)); assertThat(dashboardsOnlyUserRole.indices().allowedIndicesMatcher(SearchAction.NAME).test(index), is(true)); assertThat(dashboardsOnlyUserRole.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(index), is(true)); + + final String randomApplication = "kibana-" + randomAlphaOfLengthBetween(8, 24); + assertThat(dashboardsOnlyUserRole.application().grants(new ApplicationPrivilege(randomApplication, "app-random", "all"), "*"), + is(false)); + + final String application = "kibana-.kibana"; + assertThat(dashboardsOnlyUserRole.application().grants(new ApplicationPrivilege(application, "app-foo", "foo"), "*"), is(false)); + assertThat(dashboardsOnlyUserRole.application().grants(new ApplicationPrivilege(application, "app-all", "all"), "*"), is(false)); + assertThat(dashboardsOnlyUserRole.application().grants(new ApplicationPrivilege(application, "app-read", "read"), "*"), is(true)); + + final String applicationWithRandomIndex = "kibana-.kibana_" + randomAlphaOfLengthBetween(8, 24); + assertThat(dashboardsOnlyUserRole.application().grants( + new ApplicationPrivilege(applicationWithRandomIndex, "app-random-index", "all"), "*"), is(false)); } public void testSuperuserRole() { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java new file mode 100644 index 0000000000000..65fa6027c627b --- /dev/null +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.integration; + +import org.elasticsearch.action.DocWriteResponse; +import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; +import org.elasticsearch.action.delete.DeleteResponse; +import org.elasticsearch.action.index.IndexResponse; +import org.elasticsearch.common.settings.SecureString; +import org.elasticsearch.test.SecurityIntegTestCase; +import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; + +import java.util.Locale; + +import static java.util.Collections.singletonMap; +import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; +import static org.hamcrest.Matchers.is; + +public class KibanaSystemRoleIntegTests extends SecurityIntegTestCase { + + protected static final SecureString USERS_PASSWD = new SecureString("change_me".toCharArray()); + + @Override + public String configUsers() { + final String usersPasswdHashed = new String(getFastStoredHashAlgoForTests().hash(USERS_PASSWD)); + return super.configUsers() + + "kibana_system:" + usersPasswdHashed; + } + + @Override + public String configUsersRoles() { + return super.configUsersRoles() + + "kibana_system:kibana_system"; + } + + + public void testCreateIndexDeleteInKibanaIndex() throws Exception { + final String index = randomBoolean()? ".kibana" : ".kibana-" + randomAlphaOfLengthBetween(1, 10).toLowerCase(Locale.ENGLISH); + + if (randomBoolean()) { + CreateIndexResponse createIndexResponse = client().filterWithHeader(singletonMap("Authorization", + UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) + .admin().indices().prepareCreate(index).get(); + assertThat(createIndexResponse.isAcknowledged(), is(true)); + } + + IndexResponse response = client() + .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) + .prepareIndex() + .setIndex(index) + .setType("dashboard") + .setSource("foo", "bar") + .setRefreshPolicy(IMMEDIATE) + .get(); + assertEquals(DocWriteResponse.Result.CREATED, response.getResult()); + + DeleteResponse deleteResponse = client() + .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) + .prepareDelete(index, "dashboard", response.getId()) + .get(); + assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult()); + } +} diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaUserRoleIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaUserRoleIntegTests.java index cc080a846fae3..b5b939e174410 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaUserRoleIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaUserRoleIntegTests.java @@ -20,7 +20,7 @@ import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.test.SecurityIntegTestCase; +import org.elasticsearch.test.NativeRealmIntegTestCase; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import java.util.Locale; @@ -36,7 +36,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -public class KibanaUserRoleIntegTests extends SecurityIntegTestCase { +public class KibanaUserRoleIntegTests extends NativeRealmIntegTestCase { protected static final SecureString USERS_PASSWD = new SecureString("change_me".toCharArray()); @@ -154,25 +154,25 @@ public void testCreateIndexDeleteInKibanaIndex() throws Exception { if (randomBoolean()) { CreateIndexResponse createIndexResponse = client().filterWithHeader(singletonMap("Authorization", - UsernamePasswordToken.basicAuthHeaderValue("kibana_user", USERS_PASSWD))) - .admin().indices().prepareCreate(index).get(); + UsernamePasswordToken.basicAuthHeaderValue("kibana_user", USERS_PASSWD))) + .admin().indices().prepareCreate(index).get(); assertThat(createIndexResponse.isAcknowledged(), is(true)); } IndexResponse response = client() - .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_user", USERS_PASSWD))) - .prepareIndex() - .setIndex(index) - .setType("dashboard") - .setSource("foo", "bar") - .setRefreshPolicy(IMMEDIATE) - .get(); + .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_user", USERS_PASSWD))) + .prepareIndex() + .setIndex(index) + .setType("dashboard") + .setSource("foo", "bar") + .setRefreshPolicy(IMMEDIATE) + .get(); assertEquals(DocWriteResponse.Result.CREATED, response.getResult()); DeleteResponse deleteResponse = client() - .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_user", USERS_PASSWD))) - .prepareDelete(index, "dashboard", response.getId()) - .get(); + .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_user", USERS_PASSWD))) + .prepareDelete(index, "dashboard", response.getId()) + .get(); assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult()); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java index 7d4469133687e..453820ea519fc 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java @@ -79,7 +79,7 @@ public String configUsers() { public String configUsersRoles() { return super.configUsersRoles() + ROLE_CAN_RUN_AS + ":" + AUTHENTICATE_USER + "\n" - + "kibana_user:" + EXECUTE_USER; + + "monitoring_user:" + EXECUTE_USER; } @Override