diff --git a/envoyauth/response.go b/envoyauth/response.go index be0097af1..fbf187f37 100644 --- a/envoyauth/response.go +++ b/envoyauth/response.go @@ -114,6 +114,43 @@ func (result *EvalResult) IsAllowed() (bool, error) { return false, result.invalidDecisionErr() } +// GetRequestQueryParametersToRemove - returns the query parameters to remove from the original request before dispatching +// it to the upstream +func (result *EvalResult) GetRequestQueryParametersToRemove() ([]string, error) { + queryParamsToRemove := []string{} + + switch decision := result.Decision.(type) { + case bool: + return queryParamsToRemove, nil + case map[string]interface{}: + var ok bool + var val interface{} + + if val, ok = decision["query_parameters_to_remove"]; !ok { + return queryParamsToRemove, nil + } + + switch val := val.(type) { + case []string: + return val, nil + case []interface{}: + for _, vval := range val { + param, ok := vval.(string) + if !ok { + return nil, fmt.Errorf("type assertion error, expected query_parameters_to_remove value to be of type 'string' but got '%T'", vval) + } + + queryParamsToRemove = append(queryParamsToRemove, param) + } + return queryParamsToRemove, nil + default: + return nil, fmt.Errorf("type assertion error, expected query_parameters_to_remove to be of type '[]string' but got '%T'", val) + } + } + + return nil, result.invalidDecisionErr() +} + // GetRequestHTTPHeadersToRemove - returns the http headers to remove from the original request before dispatching // it to the upstream func (result *EvalResult) GetRequestHTTPHeadersToRemove() ([]string, error) { diff --git a/internal/internal.go b/internal/internal.go index b5dffdf53..0fcbaf91a 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -525,11 +525,20 @@ func (p *envoyExtAuthzGrpcServer) check(ctx context.Context, req interface{}) (* return nil, stop, internalErr } + var queryParamsToRemove []string + queryParamsToRemove, err = result.GetRequestQueryParametersToRemove() + if err != nil { + err = errors.Wrap(err, "failed to get request query parameters to remove") + internalErr = newInternalError(EnvoyAuthResultErr, err) + return nil, stop, internalErr + } + resp.HttpResponse = &ext_authz_v3.CheckResponse_OkResponse{ OkResponse: &ext_authz_v3.OkHttpResponse{ - Headers: responseHeaders, - HeadersToRemove: headersToRemove, - ResponseHeadersToAdd: responseHeadersToAdd, + Headers: responseHeaders, + HeadersToRemove: headersToRemove, + ResponseHeadersToAdd: responseHeadersToAdd, + QueryParametersToRemove: queryParamsToRemove, }, } } else { diff --git a/internal/internal_test.go b/internal/internal_test.go index f4edb1f28..852a554df 100644 --- a/internal/internal_test.go +++ b/internal/internal_test.go @@ -8,8 +8,6 @@ import ( "context" "errors" "fmt" - ext_type_v2 "github.com/envoyproxy/go-control-plane/envoy/type" - ext_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" "net/http" "net/http/httptest" "reflect" @@ -21,6 +19,8 @@ import ( ext_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" ext_authz_v2 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v2" ext_authz "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3" + ext_type_v2 "github.com/envoyproxy/go-control-plane/envoy/type" + ext_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" _structpb "github.com/golang/protobuf/ptypes/struct" "github.com/prometheus/client_golang/prometheus" "google.golang.org/genproto/googleapis/rpc/code" @@ -1518,6 +1518,50 @@ func TestCheckAllowBooleanDecisionDynamicMetadataDecisionID(t *testing.T) { assertDynamicMetadataDecisionID(t, output.GetDynamicMetadata()) } +func TestCheckAllowObjectDecisionReqQueryParamsToRemove(t *testing.T) { + var req ext_authz.CheckRequest + if err := util.Unmarshal([]byte(exampleAllowedRequest), &req); err != nil { + panic(err) + } + + module := ` + package envoy.authz + + default allow = true + + query_parameters_to_remove := ["foo", "bar"] + + result["allowed"] = allow + result["query_parameters_to_remove"] = query_parameters_to_remove` + + server := testAuthzServerWithModule(module, "envoy/authz/result", nil, withCustomLogger(&testPlugin{})) + ctx := context.Background() + output, err := server.Check(ctx, &req) + if err != nil { + t.Fatal(err) + } + + if output.Status.Code != int32(code.Code_OK) { + t.Fatalf("Expected request to be allowed but got: %v", output) + } + + response := output.GetOkResponse() + if response == nil { + t.Fatal("Expected OkHttpResponse struct but got nil") + } + + queryParams := response.GetQueryParametersToRemove() + if len(queryParams) != 2 { + t.Fatalf("Expected two query params but got %v", len(queryParams)) + } + + expectedQueryParams := []string{"foo", "bar"} + + if !reflect.DeepEqual(expectedQueryParams, queryParams) { + t.Fatalf("Expected query params %v but got %v", expectedQueryParams, queryParams) + } +} + func TestCheckAllowObjectDecisionReqHeadersToRemove(t *testing.T) { var req ext_authz.CheckRequest if err := util.Unmarshal([]byte(exampleAllowedRequestParsedPath), &req); err != nil {