Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions internal/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const (
// CheckRequestTimeoutErr error code returned when context deadline exceeds before eval
CheckRequestTimeoutErr string = "check_request_timeout"

// CheckRequestCancelledErr error code returned when context deadline exceeds before eval
CheckRequestCancelledErr string = "check_request_cancelled"

// InputParseErr error code returned when unable to convert input map to ast value
InputParseErr string = "input_parse_error"

Expand All @@ -33,6 +36,9 @@ const (

// EnvoyAuthResultErr error code returned when error in fetching result from auth eval
EnvoyAuthResultErr string = "envoyauth_result_error"

// UnknownContextErr error code returned when EvalContext is not provided
UnknownContextErr string = "unknown_context_error"
)

// Is allows matching internal errors using errors.Is
Expand Down
24 changes: 21 additions & 3 deletions internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,9 @@ func (p *envoyExtAuthzGrpcServer) check(ctx context.Context, req any) (*ext_auth
}, stop, nil
}

if ctx.Err() != nil {
err = errors.Wrap(ctx.Err(), "check request timed out before query execution")
internalErr = newInternalError(CheckRequestTimeoutErr, err)
if ctxErr := checkCtxError(ctx); ctxErr != nil {
err = ctxErr.err
internalErr = ctxErr
return nil, stop, internalErr
}

Expand Down Expand Up @@ -758,3 +758,21 @@ func v2Status(s *ext_type_v3.HttpStatus) *ext_type_v2.HttpStatus {
Code: ext_type_v2.StatusCode(s.Code),
}
}

// checkCtxError checks if the context has an error and returns an appropriate internal Error
func checkCtxError(ctx context.Context) *Error {
if ctx.Err() != nil {
var err error
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
err = errors.Wrap(ctx.Err(), "check request timed out before query execution")
return newInternalError(CheckRequestTimeoutErr, err)
} else if errors.Is(ctx.Err(), context.Canceled) {
err = errors.Wrap(ctx.Err(), "check request explicitly cancelled before query execution")
return newInternalError(CheckRequestCancelledErr, err)
} else {
err = errors.Wrap(ctx.Err(), "check request failed due to unknown context error")
return newInternalError(UnknownContextErr, err)
}
}
return nil
}
58 changes: 58 additions & 0 deletions internal/internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,64 @@ func TestCheckContextTimeout(t *testing.T) {
assertErrorCounterMetric(t, server, CheckRequestTimeoutErr)
}

type testServer struct {
*envoyExtAuthzGrpcServer
beforeCheck func()
}

func (s *testServer) Check(ctx context.Context, req *ext_authz.CheckRequest) (*ext_authz.CheckResponse, error) {
if s.beforeCheck != nil {
s.beforeCheck()
}
return s.envoyExtAuthzGrpcServer.Check(ctx, req)
}

func TestCheckContextCancelled(t *testing.T) {
var req ext_authz.CheckRequest
if err := util.Unmarshal([]byte(exampleAllowedRequest), &req); err != nil {
panic(err)
}

// create custom logger
customLogger := &testPlugin{}

ctx, cancel := context.WithCancel(t.Context())
server := &testServer{
envoyExtAuthzGrpcServer: testAuthzServer(&Config{EnablePerformanceMetrics: true}, withCustomLogger(customLogger)),
beforeCheck: func() {
cancel()
},
}
_, err := server.Check(ctx, &req)
if err == nil {
t.Fatal("Expected error but got nil")
}

expectedErrMsg := "check request explicitly cancelled before query execution: context canceled"
if err.Error() != expectedErrMsg {
t.Fatalf("Expected error message %q but got %q", expectedErrMsg, err.Error())
}

if len(customLogger.events) != 1 {
t.Fatal("Unexpected events:", customLogger.events)
}

event := customLogger.events[0]
if event.Error == nil {
t.Fatal("Expected error but got nil")
}

if event.Error.Error() != expectedErrMsg {
t.Fatalf("Expected error message %q but got %q", expectedErrMsg, event.Error.Error())
}

if len((*event.Input).(map[string]any)) == 0 {
t.Fatalf("Expected non empty input but got %v", *event.Input)
}

assertErrorCounterMetric(t, server.envoyExtAuthzGrpcServer, CheckRequestCancelledErr)
}

func TestCheckContextTimeoutMetricsDisabled(t *testing.T) {
var req ext_authz.CheckRequest
if err := util.Unmarshal([]byte(exampleAllowedRequest), &req); err != nil {
Expand Down