Skip to content

Commit 5733363

Browse files
author
Yogesh Gaikwad
committed
Check whether index is same and only one write index exists for alias
When same alias points to multiple indices we can write to only one index with `is_write_index` value `true`. The special handling for PutMappingRequest filtered out such aliases making the request unauthorized. The check has been modified to consider write index flag and only when the requested index matches with the one with write index alias. Closes elastic#40831
1 parent 196aa13 commit 5733363

File tree

3 files changed

+210
-1
lines changed

3 files changed

+210
-1
lines changed

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,17 @@ static String getPutMappingIndexOrAlias(PutMappingRequest request, List<String>
248248
if (aliasMetaData != null) {
249249
Optional<String> foundAlias = aliasMetaData.stream()
250250
.map(AliasMetaData::alias)
251+
.filter(aliasName -> {
252+
List<IndexMetaData> indexMetadata = metaData.getAliasAndIndexLookup().get(aliasName).getIndices();
253+
if (indexMetadata.size() == 1) {
254+
return true;
255+
} else {
256+
IndexMetaData idxMeta = ((AliasOrIndex.Alias) metaData.getAliasAndIndexLookup().get(aliasName))
257+
.getWriteIndex();
258+
return idxMeta != null && idxMeta.getIndex().getName().equals(concreteIndexName);
259+
}
260+
})
251261
.filter(authorizedIndicesList::contains)
252-
.filter(aliasName -> metaData.getAliasAndIndexLookup().get(aliasName).getIndices().size() == 1)
253262
.findFirst();
254263
resolvedAliasOrIndex = foundAlias.orElse(concreteIndexName);
255264
} else {

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import org.junit.Before;
7373

7474
import java.util.Arrays;
75+
import java.util.Collections;
7576
import java.util.HashMap;
7677
import java.util.HashSet;
7778
import java.util.List;
@@ -138,6 +139,9 @@ public void setup() {
138139
.put(indexBuilder("-index11").settings(settings))
139140
.put(indexBuilder("-index20").settings(settings))
140141
.put(indexBuilder("-index21").settings(settings))
142+
.put(indexBuilder("logs-00001").putAlias(AliasMetaData.builder("logs-alias").writeIndex(false)).settings(settings))
143+
.put(indexBuilder("logs-00002").putAlias(AliasMetaData.builder("logs-alias").writeIndex(false)).settings(settings))
144+
.put(indexBuilder("logs-00003").putAlias(AliasMetaData.builder("logs-alias").writeIndex(true)).settings(settings))
141145
.put(indexBuilder(securityIndexName).settings(settings)).build();
142146

143147
if (withAlias) {
@@ -1355,6 +1359,23 @@ public void testDynamicPutMappingRequestFromAlias() {
13551359
request = new PutMappingRequest(Strings.EMPTY_ARRAY).setConcreteIndex(new Index(index, UUIDs.base64UUID()));
13561360
putMappingIndexOrAlias = IndicesAndAliasesResolver.getPutMappingIndexOrAlias(request, authorizedIndices, metaData);
13571361
assertEquals(index, putMappingIndexOrAlias);
1362+
1363+
}
1364+
1365+
public void testDynamicPutMappingRequestForOneAliasForMultipleIndices() {
1366+
String index = "logs-00003";
1367+
PutMappingRequest request = new PutMappingRequest(Strings.EMPTY_ARRAY).setConcreteIndex(new Index(index, UUIDs.base64UUID()));
1368+
List<String> authorizedIndices = Collections.singletonList("logs-alias");
1369+
assert metaData.getAliasAndIndexLookup().get("logs-alias").getIndices().size() == 3;
1370+
String putMappingIndexOrAlias = IndicesAndAliasesResolver.getPutMappingIndexOrAlias(request, authorizedIndices, metaData);
1371+
assertEquals("logs-alias", putMappingIndexOrAlias);
1372+
1373+
index = "logs-00002";
1374+
request = new PutMappingRequest(Strings.EMPTY_ARRAY).setConcreteIndex(new Index(index, UUIDs.base64UUID()));
1375+
authorizedIndices = Collections.singletonList("logs-alias");
1376+
assert metaData.getAliasAndIndexLookup().get("logs-alias").getIndices().size() == 3;
1377+
putMappingIndexOrAlias = IndicesAndAliasesResolver.getPutMappingIndexOrAlias(request, authorizedIndices, metaData);
1378+
assertEquals(index, putMappingIndexOrAlias);
13581379
}
13591380

13601381
// TODO with the removal of DeleteByQuery is there another way to test resolving a write action?
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
---
2+
3+
setup:
4+
- skip:
5+
features: headers
6+
7+
- do:
8+
cluster.health:
9+
wait_for_status: yellow
10+
11+
- do:
12+
security.put_role:
13+
name: "foo_alias_role"
14+
body: >
15+
{
16+
"indices": [
17+
{ "names": ["foo_alias"], "privileges": ["write", "manage"] }
18+
]
19+
}
20+
21+
- do:
22+
security.put_user:
23+
username: "test_user"
24+
body: >
25+
{
26+
"password" : "x-pack-test-password",
27+
"roles" : [ "foo_alias_role" ],
28+
"full_name" : "user with privileges to write, manage via alias"
29+
}
30+
31+
- do:
32+
cluster.put_settings:
33+
body: >
34+
{
35+
"transient" : { "indices.lifecycle.poll_interval" : "1s" }
36+
}
37+
38+
- do:
39+
ilm.put_lifecycle:
40+
policy: "foo-policy"
41+
body: >
42+
{
43+
"policy" : {
44+
"phases" : {
45+
"hot" : {
46+
"min_age": "0ms",
47+
"actions" : {
48+
"rollover" : {
49+
"max_docs" : 2
50+
}
51+
}
52+
}
53+
}
54+
}
55+
}
56+
57+
- do:
58+
indices.put_template:
59+
name: "foo-template"
60+
body: >
61+
{
62+
"index_patterns": ["foo-logs-*"],
63+
"settings": {
64+
"number_of_shards": 1,
65+
"number_of_replicas": 0,
66+
"index.lifecycle.name": "foo-policy",
67+
"index.lifecycle.rollover_alias": "foo_alias"
68+
}
69+
}
70+
71+
- do:
72+
indices.create:
73+
index: foo-logs-000001
74+
body: >
75+
{
76+
"aliases": {
77+
"foo_alias" : { }
78+
}
79+
}
80+
81+
---
82+
teardown:
83+
- do:
84+
security.delete_user:
85+
username: "test_user"
86+
ignore: 404
87+
88+
- do:
89+
security.delete_role:
90+
name: "foo_alias_role"
91+
ignore: 404
92+
93+
- do:
94+
indices.delete_alias:
95+
index: "foo-logs-*"
96+
name: [ "foo_alias" ]
97+
ignore: 404
98+
99+
- do:
100+
indices.delete:
101+
index: [ "foo-logs-*" ]
102+
ignore: 404
103+
104+
---
105+
"Test ilm, index via write alias of index":
106+
107+
# index using alias
108+
- do:
109+
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
110+
create:
111+
id: 1
112+
index: foo_alias
113+
body: >
114+
{
115+
"name" : "doc1"
116+
}
117+
118+
- do:
119+
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
120+
create:
121+
id: 2
122+
index: foo_alias
123+
body: >
124+
{
125+
"name" : "doc2"
126+
}
127+
128+
- do:
129+
indices.refresh: {}
130+
131+
# sleep so ilm task gets triggered
132+
# this is a hacky way to sleep for 1s, since we will never have 10 nodes
133+
- do:
134+
catch: request_timeout
135+
cluster.health:
136+
wait_for_nodes: 10
137+
timeout: "2s"
138+
- match:
139+
timed_out: true
140+
141+
# ILM should have triggered rollover by now
142+
143+
# ensure new index is created
144+
- do:
145+
indices.exists:
146+
index: foo-logs-000002
147+
148+
- is_true: ''
149+
150+
# index using alias
151+
- do:
152+
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
153+
create:
154+
id: 3
155+
index: foo_alias
156+
body: >
157+
{
158+
"name" : "doc3"
159+
}
160+
161+
- do:
162+
indices.refresh: {}
163+
164+
# verify the indexes
165+
- do:
166+
search:
167+
rest_total_hits_as_int: true
168+
index: foo-logs-000001
169+
170+
- match: { hits.total: 2 }
171+
- match: { hits.hits.0._index: "foo-logs-000001"}
172+
173+
- do:
174+
search:
175+
rest_total_hits_as_int: true
176+
index: foo-logs-000002
177+
178+
- match: { hits.total: 1 }
179+
- match: { hits.hits.0._index: "foo-logs-000002"}

0 commit comments

Comments
 (0)