7
7
8
8
import org .apache .http .entity .ContentType ;
9
9
import org .apache .http .entity .StringEntity ;
10
+ import org .elasticsearch .client .Node ;
10
11
import org .elasticsearch .client .Request ;
11
12
import org .elasticsearch .client .Response ;
12
13
import org .elasticsearch .client .ResponseException ;
14
+ import org .elasticsearch .client .RestClient ;
15
+ import org .elasticsearch .client .RestClientBuilder ;
13
16
import org .elasticsearch .common .Strings ;
14
17
import org .elasticsearch .common .settings .SecureString ;
15
18
import org .elasticsearch .common .settings .Settings ;
19
22
import org .elasticsearch .common .xcontent .XContentHelper ;
20
23
import org .elasticsearch .common .xcontent .XContentType ;
21
24
import org .elasticsearch .common .xcontent .json .JsonXContent ;
25
+ import org .elasticsearch .common .xcontent .support .XContentMapValues ;
22
26
import org .elasticsearch .rest .RestStatus ;
23
27
import org .elasticsearch .test .rest .ESRestTestCase ;
24
28
import org .elasticsearch .xpack .core .indexlifecycle .DeleteAction ;
25
29
import org .elasticsearch .xpack .core .indexlifecycle .LifecycleAction ;
26
30
import org .elasticsearch .xpack .core .indexlifecycle .LifecyclePolicy ;
27
31
import org .elasticsearch .xpack .core .indexlifecycle .LifecycleSettings ;
28
32
import org .elasticsearch .xpack .core .indexlifecycle .Phase ;
33
+ import org .elasticsearch .xpack .core .indexlifecycle .RolloverAction ;
29
34
import org .junit .Before ;
30
35
31
36
import java .io .IOException ;
36
41
import static org .elasticsearch .common .xcontent .XContentFactory .jsonBuilder ;
37
42
import static org .elasticsearch .xpack .core .security .authc .support .UsernamePasswordToken .basicAuthHeaderValue ;
38
43
import static org .hamcrest .Matchers .equalTo ;
44
+ import static org .hamcrest .Matchers .is ;
39
45
40
46
public class PermissionsIT extends ESRestTestCase {
47
+ private static final String jsonDoc = "{ \" name\" : \" elasticsearch\" , \" body\" : \" foo bar\" }" ;
41
48
42
49
private String deletePolicy = "deletePolicy" ;
43
50
private Settings indexSettingsWithPolicy ;
@@ -74,7 +81,7 @@ public void init() throws Exception {
74
81
.put ("number_of_shards" , 1 )
75
82
.put ("number_of_replicas" , 0 )
76
83
.build ();
77
- createNewSingletonPolicy (deletePolicy ,"delete" , new DeleteAction ());
84
+ createNewSingletonPolicy (client (), deletePolicy ,"delete" , new DeleteAction ());
78
85
}
79
86
80
87
/**
@@ -126,7 +133,62 @@ public void testCanViewExplainOnUnmanagedIndex() throws Exception {
126
133
assertOK (client ().performRequest (request ));
127
134
}
128
135
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.value" , 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 {
130
192
Phase phase = new Phase (phaseName , TimeValue .ZERO , singletonMap (action .getWriteableName (), action ));
131
193
LifecyclePolicy lifecyclePolicy = new LifecyclePolicy (policy , singletonMap (phase .getName (), phase ));
132
194
XContentBuilder builder = jsonBuilder ();
@@ -135,7 +197,7 @@ private void createNewSingletonPolicy(String policy, String phaseName, Lifecycle
135
197
"{ \" policy\" :" + Strings .toString (builder ) + "}" , ContentType .APPLICATION_JSON );
136
198
Request request = new Request ("PUT" , "_ilm/policy/" + policy );
137
199
request .setEntity (entity );
138
- client () .performRequest (request );
200
+ assertOK ( client .performRequest (request ) );
139
201
}
140
202
141
203
private void createIndexAsAdmin (String name , Settings settings , String mapping ) throws IOException {
@@ -144,4 +206,59 @@ private void createIndexAsAdmin(String name, Settings settings, String mapping)
144
206
+ ", \" mappings\" : {" + mapping + "} }" );
145
207
assertOK (adminClient ().performRequest (request ));
146
208
}
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
+ }
147
264
}
0 commit comments