77
88import org .apache .http .entity .ContentType ;
99import org .apache .http .entity .StringEntity ;
10+ import org .elasticsearch .client .Node ;
1011import org .elasticsearch .client .Request ;
1112import org .elasticsearch .client .Response ;
1213import org .elasticsearch .client .ResponseException ;
14+ import org .elasticsearch .client .RestClient ;
15+ import org .elasticsearch .client .RestClientBuilder ;
1316import org .elasticsearch .common .Strings ;
1417import org .elasticsearch .common .settings .SecureString ;
1518import org .elasticsearch .common .settings .Settings ;
1922import org .elasticsearch .common .xcontent .XContentHelper ;
2023import org .elasticsearch .common .xcontent .XContentType ;
2124import org .elasticsearch .common .xcontent .json .JsonXContent ;
25+ import org .elasticsearch .common .xcontent .support .XContentMapValues ;
2226import org .elasticsearch .rest .RestStatus ;
2327import org .elasticsearch .test .rest .ESRestTestCase ;
2428import org .elasticsearch .xpack .core .indexlifecycle .DeleteAction ;
2529import org .elasticsearch .xpack .core .indexlifecycle .LifecycleAction ;
2630import org .elasticsearch .xpack .core .indexlifecycle .LifecyclePolicy ;
2731import org .elasticsearch .xpack .core .indexlifecycle .LifecycleSettings ;
2832import org .elasticsearch .xpack .core .indexlifecycle .Phase ;
33+ import org .elasticsearch .xpack .core .indexlifecycle .RolloverAction ;
2934import org .junit .Before ;
3035
3136import java .io .IOException ;
3641import static org .elasticsearch .common .xcontent .XContentFactory .jsonBuilder ;
3742import static org .elasticsearch .xpack .core .security .authc .support .UsernamePasswordToken .basicAuthHeaderValue ;
3843import static org .hamcrest .Matchers .equalTo ;
44+ import static org .hamcrest .Matchers .is ;
3945
4046public class PermissionsIT extends ESRestTestCase {
47+ private static final String jsonDoc = "{ \" name\" : \" elasticsearch\" , \" body\" : \" foo bar\" }" ;
4148
4249 private String deletePolicy = "deletePolicy" ;
4350 private Settings indexSettingsWithPolicy ;
@@ -74,7 +81,7 @@ public void init() throws Exception {
7481 .put ("number_of_shards" , 1 )
7582 .put ("number_of_replicas" , 0 )
7683 .build ();
77- createNewSingletonPolicy (deletePolicy ,"delete" , new DeleteAction ());
84+ createNewSingletonPolicy (client (), deletePolicy ,"delete" , new DeleteAction ());
7885 }
7986
8087 /**
@@ -126,7 +133,62 @@ public void testCanViewExplainOnUnmanagedIndex() throws Exception {
126133 assertOK (client ().performRequest (request ));
127134 }
128135
129- private void createNewSingletonPolicy (String policy , String phaseName , LifecycleAction action ) throws IOException {
136+ /**
137+ * Tests when the user is limited by alias of an index is able to write to index
138+ * which was rolled over by an ILM policy.
139+ */
140+ public void testWhenUserLimitedByOnlyAliasOfIndexCanWriteToIndexWhichWasRolledoverByILMPolicy ()
141+ throws IOException , InterruptedException {
142+ /*
143+ * Setup:
144+ * - ILM policy to rollover index when max docs condition is met
145+ * - Index template to which the ILM policy applies and create Index
146+ * - Create role with just write and manage privileges on alias
147+ * - Create user and assign newly created role.
148+ */
149+ createNewSingletonPolicy (adminClient (), "foo-policy" , "hot" , new RolloverAction (null , null , 2L ));
150+ createIndexTemplate ("foo-template" , "foo-logs-*" , "foo_alias" , "foo-policy" );
151+ createIndexAsAdmin ("foo-logs-000001" , "foo_alias" , randomBoolean ());
152+ createRole ("foo_alias_role" , "foo_alias" );
153+ createUser ("test_user" , "x-pack-test-password" , "foo_alias_role" );
154+
155+ // test_user: index docs using alias in the newly created index
156+ indexDocs ("test_user" , "x-pack-test-password" , "foo_alias" , 2 );
157+ refresh ("foo_alias" );
158+
159+ // wait so the ILM policy triggers rollover action, verify that the new index exists
160+ assertThat (awaitBusy (() -> {
161+ Request request = new Request ("HEAD" , "/" + "foo-logs-000002" );
162+ int status ;
163+ try {
164+ status = adminClient ().performRequest (request ).getStatusLine ().getStatusCode ();
165+ } catch (IOException e ) {
166+ throw new RuntimeException (e );
167+ }
168+ return status == 200 ;
169+ }), is (true ));
170+
171+ // test_user: index docs using alias, now should be able write to new index
172+ indexDocs ("test_user" , "x-pack-test-password" , "foo_alias" , 1 );
173+ refresh ("foo_alias" );
174+
175+ // verify that the doc has been indexed into new write index
176+ awaitBusy (() -> {
177+ Request request = new Request ("GET" , "/foo-logs-000002/_search" );
178+ Response response ;
179+ try {
180+ response = adminClient ().performRequest (request );
181+ try (InputStream content = response .getEntity ().getContent ()) {
182+ Map <String , Object > map = XContentHelper .convertToMap (JsonXContent .jsonXContent , content , false );
183+ return ((Integer ) XContentMapValues .extractValue ("hits.total" , map )) == 1 ;
184+ }
185+ } catch (IOException e ) {
186+ throw new RuntimeException (e );
187+ }
188+ });
189+ }
190+
191+ private void createNewSingletonPolicy (RestClient client , String policy , String phaseName , LifecycleAction action ) throws IOException {
130192 Phase phase = new Phase (phaseName , TimeValue .ZERO , singletonMap (action .getWriteableName (), action ));
131193 LifecyclePolicy lifecyclePolicy = new LifecyclePolicy (policy , singletonMap (phase .getName (), phase ));
132194 XContentBuilder builder = jsonBuilder ();
@@ -135,7 +197,7 @@ private void createNewSingletonPolicy(String policy, String phaseName, Lifecycle
135197 "{ \" policy\" :" + Strings .toString (builder ) + "}" , ContentType .APPLICATION_JSON );
136198 Request request = new Request ("PUT" , "_ilm/policy/" + policy );
137199 request .setEntity (entity );
138- client () .performRequest (request );
200+ assertOK ( client .performRequest (request ) );
139201 }
140202
141203 private void createIndexAsAdmin (String name , Settings settings , String mapping ) throws IOException {
@@ -144,4 +206,59 @@ private void createIndexAsAdmin(String name, Settings settings, String mapping)
144206 + ", \" mappings\" : {" + mapping + "} }" );
145207 assertOK (adminClient ().performRequest (request ));
146208 }
209+
210+ private void createIndexAsAdmin (String name , String alias , boolean isWriteIndex ) throws IOException {
211+ Request request = new Request ("PUT" , "/" + name );
212+ request .setJsonEntity ("{ \" aliases\" : { \" " +alias +"\" : {" + ((isWriteIndex ) ? "\" is_write_index\" : true" : "" )
213+ + "} } }" );
214+ assertOK (adminClient ().performRequest (request ));
215+ }
216+
217+ private void createIndexTemplate (String name , String pattern , String alias , String policy ) throws IOException {
218+ Request request = new Request ("PUT" , "/_template/" + name );
219+ request .setJsonEntity ("{\n " +
220+ " \" index_patterns\" : [\" " +pattern +"\" ],\n " +
221+ " \" settings\" : {\n " +
222+ " \" number_of_shards\" : 1,\n " +
223+ " \" number_of_replicas\" : 0,\n " +
224+ " \" index.lifecycle.name\" : \" " +policy +"\" ,\n " +
225+ " \" index.lifecycle.rollover_alias\" : \" " +alias +"\" \n " +
226+ " }\n " +
227+ " }" );
228+ assertOK (adminClient ().performRequest (request ));
229+ }
230+
231+ private void createUser (String name , String password , String role ) throws IOException {
232+ Request request = new Request ("PUT" , "/_security/user/" + name );
233+ request .setJsonEntity ("{ \" password\" : \" " +password +"\" , \" roles\" : [ \" " + role +"\" ] }" );
234+ assertOK (adminClient ().performRequest (request ));
235+ }
236+
237+ private void createRole (String name , String alias ) throws IOException {
238+ Request request = new Request ("PUT" , "/_security/role/" + name );
239+ request .setJsonEntity ("{ \" indices\" : [ { \" names\" : [ \" " + alias +"\" ], \" privileges\" : [ \" write\" , \" manage\" ] } ] }" );
240+ assertOK (adminClient ().performRequest (request ));
241+ }
242+
243+ private void indexDocs (String user , String passwd , String index , int noOfDocs ) throws IOException {
244+ RestClientBuilder builder = RestClient .builder (adminClient ().getNodes ().toArray (new Node [0 ]));
245+ String token = basicAuthHeaderValue (user , new SecureString (passwd .toCharArray ()));
246+ configureClient (builder , Settings .builder ()
247+ .put (ThreadContext .PREFIX + ".Authorization" , token )
248+ .build ());
249+ builder .setStrictDeprecationMode (true );
250+ try (RestClient userClient = builder .build ();) {
251+
252+ for (int cnt = 0 ; cnt < noOfDocs ; cnt ++) {
253+ Request request = new Request ("POST" , "/" + index + "/_doc" );
254+ request .setJsonEntity (jsonDoc );
255+ assertOK (userClient .performRequest (request ));
256+ }
257+ }
258+ }
259+
260+ private void refresh (String index ) throws IOException {
261+ Request request = new Request ("POST" , "/" + index + "/_refresh" );
262+ assertOK (adminClient ().performRequest (request ));
263+ }
147264}
0 commit comments