6666import org .elasticsearch .xpack .core .ml .action .DeleteForecastAction ;
6767import org .elasticsearch .xpack .core .ml .action .DeleteJobAction ;
6868import org .elasticsearch .xpack .core .ml .action .DeleteModelSnapshotAction ;
69+ import org .elasticsearch .xpack .core .ml .action .DeleteTrainedModelAction ;
70+ import org .elasticsearch .xpack .core .ml .action .EstimateModelMemoryAction ;
71+ import org .elasticsearch .xpack .core .ml .action .EvaluateDataFrameAction ;
72+ import org .elasticsearch .xpack .core .ml .action .ExplainDataFrameAnalyticsAction ;
6973import org .elasticsearch .xpack .core .ml .action .FinalizeJobExecutionAction ;
7074import org .elasticsearch .xpack .core .ml .action .FindFileStructureAction ;
7175import org .elasticsearch .xpack .core .ml .action .FlushJobAction ;
7478import org .elasticsearch .xpack .core .ml .action .GetCalendarEventsAction ;
7579import org .elasticsearch .xpack .core .ml .action .GetCalendarsAction ;
7680import org .elasticsearch .xpack .core .ml .action .GetCategoriesAction ;
81+ import org .elasticsearch .xpack .core .ml .action .GetDataFrameAnalyticsAction ;
82+ import org .elasticsearch .xpack .core .ml .action .GetDataFrameAnalyticsStatsAction ;
7783import org .elasticsearch .xpack .core .ml .action .GetDatafeedsAction ;
7884import org .elasticsearch .xpack .core .ml .action .GetDatafeedsStatsAction ;
7985import org .elasticsearch .xpack .core .ml .action .GetFiltersAction ;
8389import org .elasticsearch .xpack .core .ml .action .GetModelSnapshotsAction ;
8490import org .elasticsearch .xpack .core .ml .action .GetOverallBucketsAction ;
8591import org .elasticsearch .xpack .core .ml .action .GetRecordsAction ;
92+ import org .elasticsearch .xpack .core .ml .action .GetTrainedModelsAction ;
93+ import org .elasticsearch .xpack .core .ml .action .GetTrainedModelsStatsAction ;
94+ import org .elasticsearch .xpack .core .ml .action .InternalInferModelAction ;
8695import org .elasticsearch .xpack .core .ml .action .IsolateDatafeedAction ;
8796import org .elasticsearch .xpack .core .ml .action .KillProcessAction ;
8897import org .elasticsearch .xpack .core .ml .action .MlInfoAction ;
92101import org .elasticsearch .xpack .core .ml .action .PostDataAction ;
93102import org .elasticsearch .xpack .core .ml .action .PreviewDatafeedAction ;
94103import org .elasticsearch .xpack .core .ml .action .PutCalendarAction ;
104+ import org .elasticsearch .xpack .core .ml .action .PutDataFrameAnalyticsAction ;
95105import org .elasticsearch .xpack .core .ml .action .PutDatafeedAction ;
96106import org .elasticsearch .xpack .core .ml .action .PutFilterAction ;
97107import org .elasticsearch .xpack .core .ml .action .PutJobAction ;
108+ import org .elasticsearch .xpack .core .ml .action .PutTrainedModelAction ;
98109import org .elasticsearch .xpack .core .ml .action .RevertModelSnapshotAction ;
99110import org .elasticsearch .xpack .core .ml .action .SetUpgradeModeAction ;
111+ import org .elasticsearch .xpack .core .ml .action .StartDataFrameAnalyticsAction ;
100112import org .elasticsearch .xpack .core .ml .action .StartDatafeedAction ;
113+ import org .elasticsearch .xpack .core .ml .action .StopDataFrameAnalyticsAction ;
101114import org .elasticsearch .xpack .core .ml .action .StopDatafeedAction ;
102115import org .elasticsearch .xpack .core .ml .action .UpdateCalendarJobAction ;
103116import org .elasticsearch .xpack .core .ml .action .UpdateDatafeedAction ;
@@ -333,6 +346,9 @@ public void testKibanaSystemRole() {
333346 assertThat (kibanaRole .cluster ().check (InvalidateApiKeyAction .NAME , request , authentication ), is (true ));
334347 assertThat (kibanaRole .cluster ().check (GrantApiKeyAction .NAME , request , authentication ), is (true ));
335348
349+ // ML
350+ assertRoleHasManageMl (kibanaRole );
351+
336352 // Application Privileges
337353 DeletePrivilegesRequest deleteKibanaPrivileges = new DeletePrivilegesRequest ("kibana-.kibana" , new String []{ "all" , "read" });
338354 DeletePrivilegesRequest deleteLogstashPrivileges = new DeletePrivilegesRequest ("logstash" , new String []{ "all" , "read" });
@@ -387,7 +403,7 @@ public void testKibanaSystemRole() {
387403 assertThat (kibanaRole .indices ().allowedIndicesMatcher (READ_CROSS_CLUSTER_NAME ).test (index ), is (true ));
388404 });
389405
390- // read-only index access
406+ // read-only index access, including cross cluster
391407 Arrays .asList (".monitoring-" + randomAlphaOfLength (randomIntBetween (0 , 13 ))).forEach ((index ) -> {
392408 logger .info ("index name [{}]" , index );
393409 assertThat (kibanaRole .indices ().allowedIndicesMatcher ("indices:foo" ).test (index ), is (false ));
@@ -403,6 +419,26 @@ public void testKibanaSystemRole() {
403419 assertThat (kibanaRole .indices ().allowedIndicesMatcher (READ_CROSS_CLUSTER_NAME ).test (index ), is (true ));
404420 });
405421
422+ // read-only index access, excluding cross cluster
423+ Arrays .asList (
424+ ".ml-anomalies-" + randomAlphaOfLength (randomIntBetween (0 , 13 )),
425+ ".ml-notifications-" + randomAlphaOfLength (randomIntBetween (0 , 13 )),
426+ ".ml-stats-" + randomAlphaOfLength (randomIntBetween (0 , 13 ))
427+ ).forEach ((index ) -> {
428+ logger .trace ("index name [{}]" , index );
429+ assertThat (kibanaRole .indices ().allowedIndicesMatcher ("indices:foo" ).test (index ), is (false ));
430+ assertThat (kibanaRole .indices ().allowedIndicesMatcher ("indices:bar" ).test (index ), is (false ));
431+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (DeleteIndexAction .NAME ).test (index ), is (false ));
432+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (CreateIndexAction .NAME ).test (index ), is (false ));
433+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (IndexAction .NAME ).test (index ), is (false ));
434+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (DeleteAction .NAME ).test (index ), is (false ));
435+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (UpdateSettingsAction .NAME ).test (index ), is (false ));
436+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (SearchAction .NAME ).test (index ), is (true ));
437+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (MultiSearchAction .NAME ).test (index ), is (true ));
438+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (GetAction .NAME ).test (index ), is (true ));
439+ assertThat (kibanaRole .indices ().allowedIndicesMatcher (READ_CROSS_CLUSTER_NAME ).test (index ), is (false ));
440+ });
441+
406442 // read-only indices for APM telemetry
407443 Arrays .asList ("apm-*" ).forEach ((index ) -> {
408444 assertThat (kibanaRole .indices ().allowedIndicesMatcher ("indices:foo" ).test (index ), is (false ));
@@ -1122,6 +1158,39 @@ public void testMachineLearningAdminRole() {
11221158 assertThat (roleDescriptor .getMetadata (), hasEntry ("_reserved" , true ));
11231159
11241160 Role role = Role .builder (roleDescriptor , null ).build ();
1161+ assertRoleHasManageMl (role );
1162+ assertThat (role .cluster ().check (DelegatePkiAuthenticationAction .NAME , request , authentication ), is (false ));
1163+
1164+ assertThat (role .runAs ().check (randomAlphaOfLengthBetween (1 , 30 )), is (false ));
1165+
1166+ assertNoAccessAllowed (role , "foo" );
1167+ assertNoAccessAllowed (role , AnomalyDetectorsIndexFields .CONFIG_INDEX ); // internal use only
1168+ assertOnlyReadAllowed (role , MlMetaIndex .INDEX_NAME );
1169+ assertOnlyReadAllowed (role , AnomalyDetectorsIndexFields .STATE_INDEX_PREFIX );
1170+ assertOnlyReadAllowed (role , AnomalyDetectorsIndexFields .RESULTS_INDEX_PREFIX + AnomalyDetectorsIndexFields .RESULTS_INDEX_DEFAULT );
1171+ assertOnlyReadAllowed (role , NotificationsIndex .NOTIFICATIONS_INDEX );
1172+ assertReadWriteDocsButNotDeleteIndexAllowed (role , AnnotationIndex .INDEX_NAME );
1173+
1174+ assertNoAccessAllowed (role , RestrictedIndicesNames .RESTRICTED_NAMES );
1175+ assertNoAccessAllowed (role , RestrictedIndicesNames .ASYNC_SEARCH_PREFIX + randomAlphaOfLengthBetween (0 , 2 ));
1176+
1177+ final String kibanaApplicationWithRandomIndex = "kibana-" + randomFrom (randomAlphaOfLengthBetween (8 , 24 ), ".kibana" );
1178+ assertThat (role .application ().grants (
1179+ new ApplicationPrivilege (kibanaApplicationWithRandomIndex , "app-foo" , "foo" ), "*" ), is (false ));
1180+ assertThat (role .application ().grants (
1181+ new ApplicationPrivilege (kibanaApplicationWithRandomIndex , "app-reserved_ml" , "reserved_ml_admin" ), "*" ), is (true ));
1182+
1183+ final String otherApplication = "logstash-" + randomAlphaOfLengthBetween (8 , 24 );
1184+ assertThat (role .application ().grants (
1185+ new ApplicationPrivilege (otherApplication , "app-foo" , "foo" ), "*" ), is (false ));
1186+ assertThat (role .application ().grants (
1187+ new ApplicationPrivilege (otherApplication , "app-reserved_ml" , "reserved_ml_admin" ), "*" ), is (false ));
1188+ }
1189+
1190+ private void assertRoleHasManageMl (Role role ) {
1191+ final TransportRequest request = mock (TransportRequest .class );
1192+ final Authentication authentication = mock (Authentication .class );
1193+
11251194 assertThat (role .cluster ().check (CloseJobAction .NAME , request , authentication ), is (true ));
11261195 assertThat (role .cluster ().check (DeleteCalendarAction .NAME , request , authentication ), is (true ));
11271196 assertThat (role .cluster ().check (DeleteCalendarEventAction .NAME , request , authentication ), is (true ));
@@ -1131,6 +1200,10 @@ public void testMachineLearningAdminRole() {
11311200 assertThat (role .cluster ().check (DeleteForecastAction .NAME , request , authentication ), is (true ));
11321201 assertThat (role .cluster ().check (DeleteJobAction .NAME , request , authentication ), is (true ));
11331202 assertThat (role .cluster ().check (DeleteModelSnapshotAction .NAME , request , authentication ), is (true ));
1203+ assertThat (role .cluster ().check (DeleteTrainedModelAction .NAME , request , authentication ), is (true ));
1204+ assertThat (role .cluster ().check (EstimateModelMemoryAction .NAME , request , authentication ), is (true ));
1205+ assertThat (role .cluster ().check (EvaluateDataFrameAction .NAME , request , authentication ), is (true ));
1206+ assertThat (role .cluster ().check (ExplainDataFrameAnalyticsAction .NAME , request , authentication ), is (true ));
11341207 assertThat (role .cluster ().check (FinalizeJobExecutionAction .NAME , request , authentication ), is (false )); // internal use only
11351208 assertThat (role .cluster ().check (FindFileStructureAction .NAME , request , authentication ), is (true ));
11361209 assertThat (role .cluster ().check (FlushJobAction .NAME , request , authentication ), is (true ));
@@ -1141,13 +1214,18 @@ public void testMachineLearningAdminRole() {
11411214 assertThat (role .cluster ().check (GetCategoriesAction .NAME , request , authentication ), is (true ));
11421215 assertThat (role .cluster ().check (GetDatafeedsAction .NAME , request , authentication ), is (true ));
11431216 assertThat (role .cluster ().check (GetDatafeedsStatsAction .NAME , request , authentication ), is (true ));
1217+ assertThat (role .cluster ().check (GetDataFrameAnalyticsAction .NAME , request , authentication ), is (true ));
1218+ assertThat (role .cluster ().check (GetDataFrameAnalyticsStatsAction .NAME , request , authentication ), is (true ));
11441219 assertThat (role .cluster ().check (GetFiltersAction .NAME , request , authentication ), is (true ));
11451220 assertThat (role .cluster ().check (GetInfluencersAction .NAME , request , authentication ), is (true ));
11461221 assertThat (role .cluster ().check (GetJobsAction .NAME , request , authentication ), is (true ));
11471222 assertThat (role .cluster ().check (GetJobsStatsAction .NAME , request , authentication ), is (true ));
11481223 assertThat (role .cluster ().check (GetModelSnapshotsAction .NAME , request , authentication ), is (true ));
11491224 assertThat (role .cluster ().check (GetOverallBucketsAction .NAME , request , authentication ), is (true ));
11501225 assertThat (role .cluster ().check (GetRecordsAction .NAME , request , authentication ), is (true ));
1226+ assertThat (role .cluster ().check (GetTrainedModelsAction .NAME , request , authentication ), is (true ));
1227+ assertThat (role .cluster ().check (GetTrainedModelsStatsAction .NAME , request , authentication ), is (true ));
1228+ assertThat (role .cluster ().check (InternalInferModelAction .NAME , request , authentication ), is (false )); // internal use only
11511229 assertThat (role .cluster ().check (IsolateDatafeedAction .NAME , request , authentication ), is (false )); // internal use only
11521230 assertThat (role .cluster ().check (KillProcessAction .NAME , request , authentication ), is (false )); // internal use only
11531231 assertThat (role .cluster ().check (MlInfoAction .NAME , request , authentication ), is (true ));
@@ -1158,12 +1236,16 @@ public void testMachineLearningAdminRole() {
11581236 assertThat (role .cluster ().check (PreviewDatafeedAction .NAME , request , authentication ), is (true ));
11591237 assertThat (role .cluster ().check (PutCalendarAction .NAME , request , authentication ), is (true ));
11601238 assertThat (role .cluster ().check (PutDatafeedAction .NAME , request , authentication ), is (true ));
1239+ assertThat (role .cluster ().check (PutDataFrameAnalyticsAction .NAME , request , authentication ), is (true ));
11611240 assertThat (role .cluster ().check (PutFilterAction .NAME , request , authentication ), is (true ));
11621241 assertThat (role .cluster ().check (PutJobAction .NAME , request , authentication ), is (true ));
1242+ assertThat (role .cluster ().check (PutTrainedModelAction .NAME , request , authentication ), is (true ));
11631243 assertThat (role .cluster ().check (RevertModelSnapshotAction .NAME , request , authentication ), is (true ));
11641244 assertThat (role .cluster ().check (SetUpgradeModeAction .NAME , request , authentication ), is (true ));
11651245 assertThat (role .cluster ().check (StartDatafeedAction .NAME , request , authentication ), is (true ));
1246+ assertThat (role .cluster ().check (StartDataFrameAnalyticsAction .NAME , request , authentication ), is (true ));
11661247 assertThat (role .cluster ().check (StopDatafeedAction .NAME , request , authentication ), is (true ));
1248+ assertThat (role .cluster ().check (StopDataFrameAnalyticsAction .NAME , request , authentication ), is (true ));
11671249 assertThat (role .cluster ().check (UpdateCalendarJobAction .NAME , request , authentication ), is (true ));
11681250 assertThat (role .cluster ().check (UpdateDatafeedAction .NAME , request , authentication ), is (true ));
11691251 assertThat (role .cluster ().check (UpdateFilterAction .NAME , request , authentication ), is (true ));
@@ -1172,32 +1254,6 @@ public void testMachineLearningAdminRole() {
11721254 assertThat (role .cluster ().check (UpdateProcessAction .NAME , request , authentication ), is (false )); // internal use only
11731255 assertThat (role .cluster ().check (ValidateDetectorAction .NAME , request , authentication ), is (true ));
11741256 assertThat (role .cluster ().check (ValidateJobConfigAction .NAME , request , authentication ), is (true ));
1175- assertThat (role .cluster ().check (DelegatePkiAuthenticationAction .NAME , request , authentication ), is (false ));
1176-
1177- assertThat (role .runAs ().check (randomAlphaOfLengthBetween (1 , 30 )), is (false ));
1178-
1179- assertNoAccessAllowed (role , "foo" );
1180- assertNoAccessAllowed (role , AnomalyDetectorsIndexFields .CONFIG_INDEX ); // internal use only
1181- assertOnlyReadAllowed (role , MlMetaIndex .INDEX_NAME );
1182- assertOnlyReadAllowed (role , AnomalyDetectorsIndexFields .STATE_INDEX_PREFIX );
1183- assertOnlyReadAllowed (role , AnomalyDetectorsIndexFields .RESULTS_INDEX_PREFIX + AnomalyDetectorsIndexFields .RESULTS_INDEX_DEFAULT );
1184- assertOnlyReadAllowed (role , NotificationsIndex .NOTIFICATIONS_INDEX );
1185- assertReadWriteDocsButNotDeleteIndexAllowed (role , AnnotationIndex .INDEX_NAME );
1186-
1187- assertNoAccessAllowed (role , RestrictedIndicesNames .RESTRICTED_NAMES );
1188- assertNoAccessAllowed (role , RestrictedIndicesNames .ASYNC_SEARCH_PREFIX + randomAlphaOfLengthBetween (0 , 2 ));
1189-
1190- final String kibanaApplicationWithRandomIndex = "kibana-" + randomFrom (randomAlphaOfLengthBetween (8 , 24 ), ".kibana" );
1191- assertThat (role .application ().grants (
1192- new ApplicationPrivilege (kibanaApplicationWithRandomIndex , "app-foo" , "foo" ), "*" ), is (false ));
1193- assertThat (role .application ().grants (
1194- new ApplicationPrivilege (kibanaApplicationWithRandomIndex , "app-reserved_ml" , "reserved_ml_admin" ), "*" ), is (true ));
1195-
1196- final String otherApplication = "logstash-" + randomAlphaOfLengthBetween (8 , 24 );
1197- assertThat (role .application ().grants (
1198- new ApplicationPrivilege (otherApplication , "app-foo" , "foo" ), "*" ), is (false ));
1199- assertThat (role .application ().grants (
1200- new ApplicationPrivilege (otherApplication , "app-reserved_ml" , "reserved_ml_admin" ), "*" ), is (false ));
12011257 }
12021258
12031259 public void testMachineLearningUserRole () {
0 commit comments