1717import  org .elasticsearch .common .Strings ;
1818import  org .elasticsearch .common .settings .SecureString ;
1919import  org .elasticsearch .common .settings .Settings ;
20+ import  org .elasticsearch .common .util .Maps ;
2021import  org .elasticsearch .common .util .concurrent .ThreadContext ;
2122import  org .elasticsearch .common .xcontent .XContentHelper ;
2223import  org .elasticsearch .common .xcontent .support .XContentMapValues ;
@@ -1388,8 +1389,7 @@ public void testDlsFls() throws Exception {
13881389            Map .of (dataIndexName , Set .of ("@timestamp" , "age" ))
13891390        );
13901391
1391-         // FLS sort of applies to failure store 
1392-         // TODO this will change with FLS handling 
1392+         // FLS applies to failure store 
13931393        assertSearchResponseContainsExpectedIndicesAndFields (
13941394            performRequest (user , new  Search ("test1::failures" ).toSearchRequest ()),
13951395            Map .of (failureIndexName , Set .of ("@timestamp" ))
@@ -1409,24 +1409,56 @@ public void testDlsFls() throws Exception {
14091409                     { 
14101410                        "names": ["test*"], 
14111411                        "privileges": ["read_failure_store"], 
1412+                         "field_security": { 
1413+                             "grant": ["error.type", "error.message"] 
1414+                         } 
1415+                      } 
1416+                  ] 
1417+              }""" , "test1" ), role );
1418+ 
1419+         // FLS applies to regular data stream 
1420+         assertSearchResponseContainsExpectedIndicesAndFields (
1421+             performRequest (user , new  Search (randomFrom ("test1" , "test1::data" )).toSearchRequest ()),
1422+             Map .of (dataIndexName , Set .of ("@timestamp" , "age" ))
1423+         );
1424+ 
1425+         // FLS applies to failure store 
1426+         assertSearchResponseContainsExpectedIndicesAndFields (
1427+             performRequest (user , new  Search ("test1::failures" ).toSearchRequest ()),
1428+             Map .of (failureIndexName , Set .of ("error.type" , "error.message" ))
1429+         );
1430+ 
1431+         upsertRole (Strings .format (""" 
1432+             { 
1433+                  "cluster": ["all"], 
1434+                  "indices": [ 
1435+                      { 
1436+                         "names": ["%s"], 
1437+                         "privileges": ["read"], 
14121438                        "field_security": { 
14131439                            "grant": ["@timestamp", "age"] 
14141440                        } 
1441+                      }, 
1442+                      { 
1443+                         "names": ["test*"], 
1444+                         "privileges": ["read_failure_store"], 
1445+                         "field_security": { 
1446+                             "grant": ["error.type", "error.message"] 
1447+                         } 
14151448                     } 
14161449                 ] 
1417-              }""" , randomFrom ( "test*" ,  "test1" ) ), role );
1450+              }""" , "test*" ), role );
14181451
14191452        // FLS applies to regular data stream 
14201453        assertSearchResponseContainsExpectedIndicesAndFields (
14211454            performRequest (user , new  Search (randomFrom ("test1" , "test1::data" )).toSearchRequest ()),
14221455            Map .of (dataIndexName , Set .of ("@timestamp" , "age" ))
14231456        );
14241457
1425-         // FLS sort of applies to failure store 
1426-         // TODO this will change with FLS handling 
1458+         // FLS applies to failure store 
14271459        assertSearchResponseContainsExpectedIndicesAndFields (
14281460            performRequest (user , new  Search ("test1::failures" ).toSearchRequest ()),
1429-             Map .of (failureIndexName , Set .of ("@timestamp" ))
1461+             Map .of (failureIndexName , Set .of ("@timestamp" ,  "error.type" ,  "error.message" ))
14301462        );
14311463
14321464        upsertRole (""" 
@@ -1452,10 +1484,56 @@ public void testDlsFls() throws Exception {
14521484            performRequest (user , new  Search (randomFrom ("test1" , "test1::data" )).toSearchRequest ()),
14531485            Map .of (dataIndexName , Set .of ("@timestamp" , "age" , "name" , "email" ))
14541486        );
1455- 
14561487        assertSearchResponseContainsExpectedIndicesAndFields (
14571488            performRequest (user , new  Search ("test1::failures" ).toSearchRequest ()),
1458-             Map .of (failureIndexName , Set .of ("@timestamp" , "document" , "error" ))
1489+             Map .of (
1490+                 failureIndexName ,
1491+                 Set .of (
1492+                     "@timestamp" ,
1493+                     "document.id" ,
1494+                     "document.index" ,
1495+                     "document.source.@timestamp" ,
1496+                     "document.source.age" ,
1497+                     "document.source.email" ,
1498+                     "document.source.name" ,
1499+                     "error.message" ,
1500+                     "error.stack_trace" ,
1501+                     "error.type" 
1502+                 )
1503+             )
1504+         );
1505+ 
1506+         // check that direct read access to backing indices is working 
1507+         upsertRole (Strings .format (""" 
1508+             { 
1509+                  "cluster": ["all"], 
1510+                  "indices": [ 
1511+                      { 
1512+                         "names": ["%s"], 
1513+                         "privileges": ["read"], 
1514+                         "field_security": { 
1515+                             "grant": ["@timestamp", "age"] 
1516+                         } 
1517+                      }, 
1518+                      { 
1519+                         "names": ["%s"], 
1520+                         "privileges": ["read"], 
1521+                         "field_security": { 
1522+                             "grant": ["@timestamp", "document.source.name"] 
1523+                         } 
1524+                      } 
1525+                  ] 
1526+              }""" , dataIndexName , failureIndexName ), role );
1527+ 
1528+         // FLS applies to backing data index 
1529+         assertSearchResponseContainsExpectedIndicesAndFields (
1530+             performRequest (user , new  Search (randomFrom (dataIndexName , ".ds-*" )).toSearchRequest ()),
1531+             Map .of (dataIndexName , Set .of ("@timestamp" , "age" ))
1532+         );
1533+         // and backing failure index 
1534+         assertSearchResponseContainsExpectedIndicesAndFields (
1535+             performRequest (user , new  Search (randomFrom (failureIndexName , ".fs-*" )).toSearchRequest ()),
1536+             Map .of (failureIndexName , Set .of ("@timestamp" , "document.source.name" ))
14591537        );
14601538
14611539        // DLS 
@@ -1507,6 +1585,21 @@ public void testDlsFls() throws Exception {
15071585             }""" , role );
15081586        // DLS does not apply because there is a section without DLS 
15091587        expectSearch (user , new  Search (randomFrom ("test1" , "test1::data" )), dataIndexDocId );
1588+ 
1589+         // DLS is applicable to backing failure store when granted read directly 
1590+         upsertRole (Strings .format (""" 
1591+             { 
1592+                  "cluster": ["all"], 
1593+                  "indices": [ 
1594+                      { 
1595+                         "names": ["%s"], 
1596+                         "privileges": ["read"], 
1597+                         "query":{"term":{"document.source.name":{"value":"jack"}}} 
1598+                      } 
1599+                  ] 
1600+              }""" , failureIndexName ), role );
1601+         expectSearch (user , new  Search (randomFrom (".fs-*" , failureIndexName )));
1602+ 
15101603    }
15111604
15121605    private  static  void  expectThrows (ThrowingRunnable  runnable , int  statusCode ) {
@@ -1797,7 +1890,7 @@ protected void assertSearchResponseContainsExpectedIndicesAndFields(
17971890                assertThat (searchResult .keySet (), equalTo (expectedIndicesAndFields .keySet ()));
17981891                for  (String  index  : expectedIndicesAndFields .keySet ()) {
17991892                    Set <String > expectedFields  = expectedIndicesAndFields .get (index );
1800-                     assertThat (searchResult .get (index ).keySet (), equalTo (expectedFields ));
1893+                     assertThat (Maps . flatten ( searchResult .get (index ),  false ,  true ).keySet (), equalTo (expectedFields ));
18011894                }
18021895            } finally  {
18031896                response .decRef ();
0 commit comments