team-carepay/traefik-opa-plugin

Internal Server Error when no policy defined

Closed this issue · 4 comments

Hello,

Context
I'm trying to add traefik-opa-plugin, but I get an error when using it

Configuration
I vahe created a repo containing the configuration to reproduce.
docker-compose is required

  • Please, clone git@github.com:sskorupski/traefik-opa-poc.git
  • Open traefik.yml and put replace TRAEFIK_PILOT_TOKEN by you pilot.traefik token
  • execute docker-compose up -d

Expected behavior
An HttpRequest on GET http://localhost:8081/httpd, should result in 200 or 403 http response code (according to the policies)

Actual behavior
An HttpRequest on GET http://localhost:8081/httpd, results in Internal Server Error with the following stack trace in the logs:

time="2021-07-12T11:07:45+02:00" level=error msg="Recovered from panic in HTTP handler [172.19.0.1:52144 - /httpd-opa]: reflect: Method on nil interface value" middlewareName=traefik-internal-recovery middlewareType=Recovery
time="2021-07-12T11:07:45+02:00" level=error msg="Stack: goroutine 482 [running]:
github.com/traefik/traefik/v2/pkg/middlewares/recovery.recoverFunc(0x7f2a42547ac0, 0xc0007329e0, 0xc000503e00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/recovery/recovery.go:46 +0x272
panic(0x2e9e720, 0x3ac3400)
	/usr/local/go/src/runtime/panic.go:965 +0x1b9
github.com/traefik/yaegi/interp.runCfg.func1(0xc00079b080, 0xc00048eb00, 0xc000c14eb8)
	/go/pkg/mod/github.com/traefik/yaegi@v0.9.19/interp/run.go:185 +0x253
panic(0x2e9e720, 0x3ac3400)
	/usr/local/go/src/runtime/panic.go:965 +0x1b9
reflect.Value.Method(0x305b320, 0xc000c464a0, 0x194, 0x0, 0xc000f1080d, 0x181, 0x100)
	/usr/local/go/src/reflect/value.go:1328 +0x167
github.com/traefik/yaegi/interp.getIndexBinMethod.func1(0xc00079b080, 0xc000cbb980)
	/go/pkg/mod/github.com/traefik/yaegi@v0.9.19/interp/run.go:1520 +0xb9
github.com/traefik/yaegi/interp.runCfg(0xc00048eb00, 0xc00079b080) 
	/go/pkg/mod/github.com/traefik/yaegi@v0.9.19/interp/run.go:191 +0x87
github.com/traefik/yaegi/interp.genFunctionWrapper.func2.1(0xc000c41a70, 0x2, 0x2, 0xc000c41a70, 0xc000c150c0, 0x404730)
	/go/pkg/mod/github.com/traefik/yaegi@v0.9.19/interp/run.go:948 +0x3e8
github.com/traefik/yaegi/stdlib._net_http_Handler.ServeHTTP(0xc000bff8f0, 0x7f2a42547ac0, 0xc0007329e0, 0xc000c48000)
	/go/pkg/mod/github.com/traefik/yaegi@v0.9.19/stdlib/go1_16_net_http.go:261 +0x44
github.com/traefik/traefik/v2/pkg/middlewares/accesslog.(*FieldHandler).ServeHTTP(0xc000891b00, 0x7f2a42547ac0, 0xc0007329e0, 0xc000c48000)
	/go/src/github.com/traefik/traefik/pkg/middlewares/accesslog/field_middleware.go:38 +0x144
github.com/gorilla/mux.(*Router).ServeHTTP(0xc000780cc0, 0x7f2a42547ac0, 0xc0007329e0, 0xc000503e00)
	/go/pkg/mod/github.com/containous/mux@v0.0.0-20181024131434-c33f32e26898/mux.go:133 +0x106
github.com/traefik/traefik/v2/pkg/middlewares/recovery.(*recovery).ServeHTTP(0xc000df7040, 0x7f2a42547ac0, 0xc0007329e0, 0xc000503e00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/recovery/recovery.go:32 +0x87
github.com/traefik/traefik/v2/pkg/middlewares/accesslog.AddOriginFields(0x7f2a42547b10, 0xc0007329d8, 0xc000503e00, 0x3b19960, 0xc000df7040, 0xc000c25380)
	/go/src/github.com/traefik/traefik/pkg/middlewares/accesslog/field_middleware.go:55 +0x1a6
github.com/traefik/traefik/v2/pkg/middlewares/accesslog.(*FieldHandler).ServeHTTP(0xc000891cc0, 0x7f2a42547b10, 0xc0007329d8, 0xc000503e00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/accesslog/field_middleware.go:36 +0x10b
github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator.(*RequestDecorator).ServeHTTP(0xc00088af10, 0x7f2a42547b10, 0xc0007329d8, 0xc000503d00, 0xc000c15600)
	/go/src/github.com/traefik/traefik/pkg/middlewares/requestdecorator/request_decorator.go:47 +0x3a2
github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator.WrapHandler.func1.1(0x7f2a42547b10, 0xc0007329d8, 0xc000503d00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/requestdecorator/request_decorator.go:84 +0x87
net/http.HandlerFunc.ServeHTTP(0xc000c8ab00, 0x7f2a42547b10, 0xc0007329d8, 0xc000503d00)
	/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/traefik/traefik/v2/pkg/middlewares/metrics.(*metricsMiddleware).ServeHTTP(0xc000c29030, 0x7f2a42547ac0, 0xc0007329d0, 0xc000503d00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/metrics/metrics.go:121 +0x5b5
github.com/traefik/traefik/v2/pkg/middlewares/accesslog.(*Handler).ServeHTTP(0xc0001946c0, 0x3b7b210, 0xc0005f8540, 0xc000503c00, 0x3b198e0, 0xc000c29030)
	/go/src/github.com/traefik/traefik/pkg/middlewares/accesslog/logger.go:226 +0xb1a
github.com/traefik/traefik/v2/pkg/middlewares/accesslog.WrapHandler.func1.1(0x3b7b210, 0xc0005f8540, 0xc000503c00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/accesslog/logger.go:70 +0x5a
net/http.HandlerFunc.ServeHTTP(0xc000c8ab40, 0x3b7b210, 0xc0005f8540, 0xc000503c00)
	/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/traefik/traefik/v2/pkg/middlewares.(*HTTPHandlerSwitcher).ServeHTTP(0xc000207c58, 0x3b7b210, 0xc0005f8540, 0xc000503c00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/handler_switcher.go:23 +0x70
github.com/traefik/traefik/v2/pkg/middlewares/forwardedheaders.(*XForwarded).ServeHTTP(0xc0001ba370, 0x3b7b210, 0xc0005f8540, 0xc000503c00)
	/go/src/github.com/traefik/traefik/pkg/middlewares/forwardedheaders/forwarded_header.go:183 +0xfa
golang.org/x/net/http2/h2c.h2cHandler.ServeHTTP(0x3b19820, 0xc0001ba370, 0xc0001b0e00, 0x3b7b210, 0xc0005f8540, 0xc000503c00)
	/go/pkg/mod/golang.org/x/net@v0.0.0-20210220033124-5f55cee0dc0d/http2/h2c/h2c.go:98 +0x31d
net/http.serverHandler.ServeHTTP(0xc0004702a0, 0x3b7b210, 0xc0005f8540, 0xc000503c00)
	/usr/local/go/src/net/http/server.go:2887 +0xa3
net/http.(*conn).serve(0xc00047d680, 0x3b86b40, 0xc00043a740)
	/usr/local/go/src/net/http/server.go:1952 +0x8cd
created by net/http.(*Server).Serve
	/usr/local/go/src/net/http/server.go:3013 +0x39b
" middlewareName=traefik-internal-recovery middlewareType=Recovery

Did I miss something in my configuration or is there a plugin compatibility issue ?

Please could you have a look and give me a ffedback ?

Best regards

Hi,
I found the origin of my problem.

When I start opa, I don't provide any policy file.
So when a request is executed to http://localhost:8181/v1/data/example, the following result is returned: {}

So when the opa plugin was executing, we get an error on line 70( err := json.Unmarshal(body, &result)) as the result is come from the result field of OPA POST request which is empty in my case.

I'm a beginner working with OPA, I don't know yet if we can tell OPA to have a default behavior when no policy is defined to prevent this behavior.

However I'm not sure returning an Internal Server Error is a good practice in this particular case.

Thanks for the report, indeed the code should be more 'defensive' and be ready for unexpected responses. I'll add a test for this situation and amend the code.

I've added some checks in the code, you might also want to checkout https://github.com/team-carepay/traefik-jwt-plugin , that plugin supports OPA as well, but has other features such as parsing and verifying JWT tokens. It also has support for injecting JWT or OPA results in the HTTP headers.

Thanks ! I really appreciate !