Skip to content

Commit 7b1b81a

Browse files
[Test] Add API key yaml tests to entsearch yaml test suite (#96881)
This commit adds YAML tests for Search Application Search API using API key restricted to `search_application_query` workflow. Relates to #96744
1 parent f988e92 commit 7b1b81a

File tree

3 files changed

+378
-1
lines changed

3 files changed

+378
-1
lines changed

x-pack/plugin/ent-search/qa/rest/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ dependencies {
77

88
restResources {
99
restApi {
10-
include '_common', 'cluster', 'nodes', 'indices', 'index', 'query_ruleset', 'search_application', 'xpack'
10+
include '_common', 'cluster', 'nodes', 'indices', 'index', 'query_ruleset', 'search_application', 'xpack', 'security', 'search'
1111
}
1212
}
1313

x-pack/plugin/ent-search/qa/rest/roles.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ admin:
3333
user:
3434
cluster:
3535
- post_behavioral_analytics_event
36+
- manage_api_key
3637
indices:
3738
- names: [
3839
"test-search-application",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
setup:
2+
- do:
3+
indices.create:
4+
index: test-search-index1
5+
body:
6+
settings:
7+
index:
8+
number_of_shards: 1
9+
number_of_replicas: 0
10+
11+
- do:
12+
indices.create:
13+
index: test-search-index2
14+
body:
15+
settings:
16+
index:
17+
number_of_shards: 1
18+
number_of_replicas: 0
19+
20+
- do:
21+
indices.create:
22+
index: test-index
23+
body:
24+
settings:
25+
index:
26+
number_of_shards: 1
27+
number_of_replicas: 0
28+
29+
- do:
30+
search_application.put:
31+
name: test-search-application
32+
body:
33+
indices: [ "test-search-index1", "test-search-index2" ]
34+
analytics_collection_name: "test-analytics"
35+
template:
36+
script:
37+
source:
38+
query:
39+
term:
40+
"{{field_name}}": "{{field_value}}"
41+
params:
42+
field_name: field1
43+
field_value: value1
44+
dictionary:
45+
additionalProperties: false
46+
required: [ "field_name" ]
47+
properties:
48+
field_name:
49+
type: string
50+
field_value:
51+
type: string
52+
53+
- do:
54+
search_application.put:
55+
name: test-search-application-1
56+
body:
57+
indices: [ "test-search-index1", "test-search-index2" ]
58+
analytics_collection_name: "test-analytics"
59+
template:
60+
script:
61+
source:
62+
query:
63+
term:
64+
"{{field_name}}": "{{field_value}}"
65+
params:
66+
field_name: field1
67+
field_value: value1
68+
dictionary:
69+
additionalProperties: false
70+
properties:
71+
field_name:
72+
type: string
73+
field_value:
74+
type: string
75+
- do:
76+
search_application.put:
77+
name: test-search-application-with-list
78+
body:
79+
indices: [ "test-search-index1", "test-search-index2" ]
80+
template:
81+
script:
82+
source: "{ \"query\": { \"multi_match\":{ \"query\": \"{{query_string}}\", \"fields\": [{{#text_fields}}\"{{name}}^{{boost}}\",{{/text_fields}}] } } }"
83+
params:
84+
query_string: "elastic"
85+
text_fields:
86+
- name: field1
87+
boost: 1
88+
- name: field2
89+
boost: 2
90+
- name: field3
91+
boost: 3
92+
lang: "mustache"
93+
94+
- do:
95+
index:
96+
index: test-search-index1
97+
id: doc1
98+
body:
99+
field1: value1
100+
field2: value1
101+
refresh: true
102+
103+
- do:
104+
index:
105+
index: test-search-index2
106+
id: doc2
107+
body:
108+
field1: value1
109+
field3: value3
110+
refresh: true
111+
112+
- do:
113+
search_application.put_behavioral_analytics:
114+
name: my-test-analytics-collection
115+
---
116+
teardown:
117+
- do:
118+
search_application.delete:
119+
name: test-search-application
120+
ignore: 404
121+
122+
- do:
123+
search_application.delete:
124+
name: test-search-application-1
125+
ignore: 404
126+
127+
- do:
128+
search_application.delete:
129+
name: test-search-application-with-list
130+
ignore: 404
131+
132+
- do:
133+
indices.delete:
134+
index: test-search-index1
135+
ignore: 404
136+
137+
- do:
138+
indices.delete:
139+
index: test-search-index2
140+
ignore: 404
141+
142+
- do:
143+
indices.delete:
144+
index: test-index
145+
ignore: 404
146+
147+
- do:
148+
search_application.delete_behavioral_analytics:
149+
name: my-test-analytics-collection
150+
151+
---
152+
"Query Search Application with API key":
153+
- skip:
154+
features: headers
155+
156+
- do:
157+
headers: { Authorization: "Basic ZW50c2VhcmNoLXVzZXI6ZW50c2VhcmNoLXVzZXItcGFzc3dvcmQ=" } # user
158+
security.create_api_key:
159+
body: >
160+
{
161+
"name": "search-application-api-key",
162+
"role_descriptors": {
163+
"role": {
164+
"cluster": [ "manage_behavioral_analytics" ],
165+
"index": [
166+
{
167+
"names": ["*"],
168+
"privileges": ["read"]
169+
}
170+
],
171+
"restriction": {
172+
"workflows": ["search_application_query"]
173+
}
174+
}
175+
}
176+
}
177+
178+
- match: { name: "search-application-api-key" }
179+
- set: { encoded: api_key_encoded }
180+
- set: { id: api_key_id }
181+
182+
# Query Search Application with default parameters:
183+
- do:
184+
headers:
185+
Authorization: ApiKey ${api_key_encoded}
186+
search_application.search:
187+
name: test-search-application-1
188+
189+
- match: { hits.total.value: 2 }
190+
- match: { hits.hits.0._id: "doc1" }
191+
- match: { hits.hits.1._id: "doc2" }
192+
193+
194+
# Query Search Application overriding part of the parameters:
195+
- do:
196+
headers:
197+
Authorization: ApiKey ${api_key_encoded}
198+
search_application.search:
199+
name: test-search-application
200+
body:
201+
params:
202+
field_name: field2
203+
204+
205+
- match: { hits.total.value: 1 }
206+
- match: { hits.hits.0._id: "doc1" }
207+
208+
# Query Search Application overriding all parameters:
209+
- do:
210+
headers:
211+
Authorization: ApiKey ${api_key_encoded}
212+
search_application.search:
213+
name: test-search-application
214+
body:
215+
params:
216+
field_name: field3
217+
field_value: value3
218+
219+
220+
- match: { hits.total.value: 1 }
221+
- match: { hits.hits.0._id: "doc2" }
222+
223+
# Query Search Application with list of parameters:
224+
- do:
225+
headers:
226+
Authorization: ApiKey ${api_key_encoded}
227+
search_application.search:
228+
name: test-search-application-with-list
229+
body:
230+
params:
231+
query_string: value3
232+
text_fields:
233+
- name: field1
234+
boost: 1
235+
- name: field2
236+
boost: 2
237+
- name: field3
238+
boost: 3
239+
240+
241+
- match: { hits.total.value: 1 }
242+
- match: { hits.hits.0._id: "doc2" }
243+
244+
# Query Search Application with invalid parameter validation:
245+
- do:
246+
catch: "bad_request"
247+
headers:
248+
Authorization: ApiKey ${api_key_encoded}
249+
search_application.search:
250+
name: test-search-application
251+
body:
252+
params:
253+
field_name: field3
254+
field_value: 35
255+
256+
# Query Search Application without required parameter:
257+
- do:
258+
catch: "bad_request"
259+
headers:
260+
Authorization: ApiKey ${api_key_encoded}
261+
search_application.search:
262+
name: test-search-application
263+
body:
264+
params:
265+
field_value: test
266+
267+
# Query Search Application - not found:
268+
- do:
269+
catch: forbidden
270+
headers:
271+
Authorization: ApiKey ${api_key_encoded}
272+
search_application.search:
273+
name: nonexisting-test-search-application
274+
body:
275+
params:
276+
field_name: field3
277+
field_value: value3
278+
279+
# Get Analytics Collection should be rejected due to a workflow restriction
280+
- do:
281+
catch: forbidden
282+
headers:
283+
Authorization: ApiKey ${api_key_encoded}
284+
search_application.get_behavioral_analytics:
285+
name:
286+
- match: { status: 403 }
287+
- match: { error.type: security_exception }
288+
- match: { error.root_cause.0.type: role_restriction_exception }
289+
- match: { error.root_cause.0.reason: "access restricted by workflow" }
290+
291+
# Get API key should not be allowed
292+
- do:
293+
catch: forbidden
294+
headers:
295+
Authorization: ApiKey ${api_key_encoded}
296+
security.get_api_key:
297+
id: "$api_key_id"
298+
- match: { status: 403 }
299+
- match: { error.type: security_exception }
300+
- match: { error.root_cause.0.type: role_restriction_exception }
301+
- match: { error.root_cause.0.reason: "access restricted by workflow" }
302+
303+
# Authenticate with API key should not be allowed
304+
- do:
305+
catch: forbidden
306+
headers:
307+
Authorization: ApiKey ${api_key_encoded}
308+
security.authenticate: {}
309+
- match: { status: 403 }
310+
- match: { error.type: security_exception }
311+
- match: { error.root_cause.0.type: role_restriction_exception }
312+
- match: { error.root_cause.0.reason: "access restricted by workflow" }
313+
314+
# Direct index search should be rejected due to a workflow restriction
315+
- do:
316+
catch: forbidden
317+
headers:
318+
Authorization: ApiKey ${api_key_encoded}
319+
search:
320+
index: test-search-index1
321+
body:
322+
query:
323+
term:
324+
field1: value1
325+
- match: { status: 403 }
326+
- match: { error.type: security_exception }
327+
- match: { error.root_cause.0.type: role_restriction_exception }
328+
- match: { error.root_cause.0.reason: "access restricted by workflow" }
329+
330+
# Creating an API key which can only search 'test-search-application-1'
331+
- do:
332+
headers: { Authorization: "Basic ZW50c2VhcmNoLXVzZXI6ZW50c2VhcmNoLXVzZXItcGFzc3dvcmQ=" } # user
333+
security.create_api_key:
334+
body: >
335+
{
336+
"name": "search-application-1-api-key",
337+
"role_descriptors": {
338+
"role": {
339+
"index": [
340+
{
341+
"names": ["test-search-application-1"],
342+
"privileges": ["read"]
343+
}
344+
],
345+
"restriction": {
346+
"workflows": ["search_application_query"]
347+
}
348+
}
349+
}
350+
}
351+
352+
- match: { name: "search-application-1-api-key" }
353+
- set: { encoded: api_key_encoded_1 }
354+
- set: { id: api_key_id_1 }
355+
356+
# Query Search Application 'test-search-application' should be denied since API key (api_key_encoded_1) does not have required index privilege
357+
- do:
358+
catch: forbidden
359+
headers:
360+
Authorization: ApiKey ${api_key_encoded_1}
361+
search_application.search:
362+
name: test-search-application
363+
- match: { status: 403 }
364+
- match: { error.type: security_exception }
365+
- match: { error.reason: "action [indices:data/read/xpack/application/search_application/search] is unauthorized for API key id [${api_key_id_1}] of user [entsearch-user] on indices [test-search-application], this action is granted by the index privileges [read,all]" }
366+
367+
# Query Search Application 'test-search-application-1' with new API key (api_key_encoded_1) should be allowed:
368+
- do:
369+
headers:
370+
Authorization: ApiKey ${api_key_encoded_1}
371+
search_application.search:
372+
name: test-search-application-1
373+
374+
- match: { hits.total.value: 2 }
375+
- match: { hits.hits.0._id: "doc1" }
376+
- match: { hits.hits.1._id: "doc2" }

0 commit comments

Comments
 (0)