Skip to content

Commit ed4bd47

Browse files
author
Mikhail Sedov
committed
feat: simplify query_parameters_to_set format
Change query_parameters_to_set to use a map format. The format supports both single values and arrays for setting multiple query parameters with the same key. Example usage in OPA policies: ```rego package envoy.authz default allow = true query_parameters_to_set = { "user_id": "123", "tenant": "acme" } query_parameters_to_set = { "role": ["admin", "user"], "scope": ["read", "write"] } query_parameters_to_set = { "user_id": "123", "role": ["admin", "user"] } result["allowed"] = allow result["query_parameters_to_set"] = query_parameters_to_set ``` Signed-off-by: Mikhail Sedov <[email protected]>
1 parent 5a61b48 commit ed4bd47

File tree

3 files changed

+125
-56
lines changed

3 files changed

+125
-56
lines changed

envoyauth/response.go

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -406,32 +406,34 @@ func (result *EvalResult) GetRequestQueryParametersToSet() ([]*ext_core_v3.Query
406406
return nil, nil
407407
}
408408

409-
params, ok := val.([]interface{})
409+
params, ok := val.(map[string]interface{})
410410
if !ok {
411-
return nil, fmt.Errorf("type assertion error, expected query_parameters_to_set to be of type 'array' but got '%T'", val)
411+
return nil, fmt.Errorf("type assertion error, expected query_parameters_to_set to be a map but got '%T'", val)
412412
}
413413

414-
result := make([]*ext_core_v3.QueryParameter, 0, len(params))
415-
for _, param := range params {
416-
paramMap, ok := param.(map[string]interface{})
417-
if !ok {
418-
return nil, fmt.Errorf("type assertion error, expected query parameter to be of type 'object' but got '%T'", param)
419-
}
420-
421-
key, ok := paramMap["key"].(string)
422-
if !ok {
423-
return nil, fmt.Errorf("type assertion error, expected query parameter key to be of type 'string'")
424-
}
425-
426-
value, ok := paramMap["value"].(string)
427-
if !ok {
428-
return nil, fmt.Errorf("type assertion error, expected query parameter value to be of type 'string'")
414+
var result []*ext_core_v3.QueryParameter
415+
416+
for key, value := range params {
417+
switch v := value.(type) {
418+
case string:
419+
result = append(result, &ext_core_v3.QueryParameter{
420+
Key: key,
421+
Value: v,
422+
})
423+
case []interface{}:
424+
for _, item := range v {
425+
strItem, ok := item.(string)
426+
if !ok {
427+
return nil, fmt.Errorf("type assertion error: expected array element to be string but got '%T'", item)
428+
}
429+
result = append(result, &ext_core_v3.QueryParameter{
430+
Key: key,
431+
Value: strItem,
432+
})
433+
}
434+
default:
435+
return nil, fmt.Errorf("type assertion error, expected value to be string or array but got '%T'", value)
429436
}
430-
431-
result = append(result, &ext_core_v3.QueryParameter{
432-
Key: key,
433-
Value: value,
434-
})
435437
}
436438

437439
return result, nil

envoyauth/response_test.go

Lines changed: 74 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"reflect"
7+
"sort"
78
"strings"
89
"testing"
910

@@ -238,50 +239,48 @@ func TestGetQueryParametersToSet(t *testing.T) {
238239
nil,
239240
true,
240241
},
241-
"invalid_param_type": {
242+
"invalid_value_type": {
242243
map[string]interface{}{
243-
"query_parameters_to_set": []interface{}{
244-
"invalid",
244+
"query_parameters_to_set": map[string]interface{}{
245+
"test": 123,
245246
},
246247
},
247248
nil,
248249
true,
249250
},
250-
"invalid_key_type": {
251+
"invalid_array_value_type": {
251252
map[string]interface{}{
252-
"query_parameters_to_set": []interface{}{
253-
map[string]interface{}{
254-
"key": 123,
255-
"value": "test",
256-
},
253+
"query_parameters_to_set": map[string]interface{}{
254+
"test": []interface{}{123},
257255
},
258256
},
259257
nil,
260258
true,
261259
},
262-
"invalid_value_type": {
260+
"single_value": {
263261
map[string]interface{}{
264-
"query_parameters_to_set": []interface{}{
265-
map[string]interface{}{
266-
"key": "test",
267-
"value": 123,
268-
},
262+
"query_parameters_to_set": map[string]interface{}{
263+
"param1": "value1",
264+
"param2": "value2",
269265
},
270266
},
271-
nil,
272-
true,
267+
[]*ext_core_v3.QueryParameter{
268+
{
269+
Key: "param1",
270+
Value: "value1",
271+
},
272+
{
273+
Key: "param2",
274+
Value: "value2",
275+
},
276+
},
277+
false,
273278
},
274-
"valid_params": {
279+
"array_values": {
275280
map[string]interface{}{
276-
"query_parameters_to_set": []interface{}{
277-
map[string]interface{}{
278-
"key": "param1",
279-
"value": "value1",
280-
},
281-
map[string]interface{}{
282-
"key": "param2",
283-
"value": "value2",
284-
},
281+
"query_parameters_to_set": map[string]interface{}{
282+
"param1": []interface{}{"value1", "value2"},
283+
"param2": []interface{}{"value3", "value4"},
285284
},
286285
},
287286
[]*ext_core_v3.QueryParameter{
@@ -290,9 +289,40 @@ func TestGetQueryParametersToSet(t *testing.T) {
290289
Value: "value1",
291290
},
292291
{
293-
Key: "param2",
292+
Key: "param1",
294293
Value: "value2",
295294
},
295+
{
296+
Key: "param2",
297+
Value: "value3",
298+
},
299+
{
300+
Key: "param2",
301+
Value: "value4",
302+
},
303+
},
304+
false,
305+
},
306+
"mixed_values": {
307+
map[string]interface{}{
308+
"query_parameters_to_set": map[string]interface{}{
309+
"param1": "single",
310+
"param2": []interface{}{"multi1", "multi2"},
311+
},
312+
},
313+
[]*ext_core_v3.QueryParameter{
314+
{
315+
Key: "param1",
316+
Value: "single",
317+
},
318+
{
319+
Key: "param2",
320+
Value: "multi1",
321+
},
322+
{
323+
Key: "param2",
324+
Value: "multi2",
325+
},
296326
},
297327
false,
298328
},
@@ -319,6 +349,22 @@ func TestGetQueryParametersToSet(t *testing.T) {
319349
t.Fatalf("Expected %d parameters but got %d", len(tc.exp), len(result))
320350
}
321351

352+
// sort first by key, then by value
353+
354+
sort.Slice(result, func(i, j int) bool {
355+
if result[i].Key == result[j].Key {
356+
return result[i].Value < result[j].Value
357+
}
358+
return result[i].Key < result[j].Key
359+
})
360+
361+
sort.Slice(tc.exp, func(i, j int) bool {
362+
if tc.exp[i].Key == tc.exp[j].Key {
363+
return tc.exp[i].Value < tc.exp[j].Value
364+
}
365+
return tc.exp[i].Key < tc.exp[j].Key
366+
})
367+
322368
for i, param := range result {
323369
if param.Key != tc.exp[i].Key || param.Value != tc.exp[i].Value {
324370
t.Fatalf("Parameter mismatch at index %d. Expected %v but got %v", i, tc.exp[i], param)

internal/internal_test.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net/http"
1212
"net/http/httptest"
1313
"reflect"
14+
"sort"
1415
"strings"
1516
"sync"
1617
"testing"
@@ -1573,10 +1574,10 @@ func TestCheckAllowObjectDecisionReqQueryParamsToSet(t *testing.T) {
15731574
15741575
default allow = true
15751576
1576-
query_parameters_to_set := [
1577-
{"key": "foo", "value": "value1"},
1578-
{"key": "bar", "value": "value2"}
1579-
]
1577+
query_parameters_to_set := {
1578+
"foo": "value1",
1579+
"bar": ["value2", "value3"]
1580+
}
15801581
15811582
result["allowed"] = allow
15821583
result["query_parameters_to_set"] = query_parameters_to_set`
@@ -1598,8 +1599,8 @@ func TestCheckAllowObjectDecisionReqQueryParamsToSet(t *testing.T) {
15981599
}
15991600

16001601
queryParams := response.GetQueryParametersToSet()
1601-
if len(queryParams) != 2 {
1602-
t.Fatalf("Expected two query params but got %v", len(queryParams))
1602+
if len(queryParams) != 3 {
1603+
t.Fatalf("Expected three query params but got %v", len(queryParams))
16031604
}
16041605

16051606
expectedQueryParamsToSet := []*ext_core.QueryParameter{
@@ -1611,8 +1612,28 @@ func TestCheckAllowObjectDecisionReqQueryParamsToSet(t *testing.T) {
16111612
Key: "bar",
16121613
Value: "value2",
16131614
},
1615+
{
1616+
Key: "bar",
1617+
Value: "value3",
1618+
},
16141619
}
16151620

1621+
// sort first by key, then by value
1622+
1623+
sort.Slice(queryParams, func(i, j int) bool {
1624+
if queryParams[i].Key == queryParams[j].Key {
1625+
return queryParams[i].Value < queryParams[j].Value
1626+
}
1627+
return queryParams[i].Key < queryParams[j].Key
1628+
})
1629+
1630+
sort.Slice(expectedQueryParamsToSet, func(i, j int) bool {
1631+
if expectedQueryParamsToSet[i].Key == expectedQueryParamsToSet[j].Key {
1632+
return expectedQueryParamsToSet[i].Value < expectedQueryParamsToSet[j].Value
1633+
}
1634+
return expectedQueryParamsToSet[i].Key < expectedQueryParamsToSet[j].Key
1635+
})
1636+
16161637
for i, param := range queryParams {
16171638
if !reflect.DeepEqual(expectedQueryParamsToSet[i], param) {
16181639
t.Fatalf("Expected query param %v but got %v", expectedQueryParamsToSet[i], param)

0 commit comments

Comments
 (0)