Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keto engine doesn't build correctly the payload to call keto for URL with query parameters #250

Closed
GuillaumeSmaha opened this issue Sep 5, 2019 · 0 comments

Comments

@GuillaumeSmaha
Copy link
Contributor

GuillaumeSmaha commented Sep 5, 2019

Describe the bug

Keto engine doesn't build correctly the payload to call keto for URL with query parameters.

When Oathkeeper tries to match a rule with a incoming request, it uses the request without the query parameters:

if !c.MatchString(fmt.Sprintf("%s://%s%s", u.Scheme, u.Host, u.Path)) {

Assuming this behaviour, the rules which doesn't handle the query parameters in a regex will fail to call keto if a query parameter is added
Because on these lines, the full URL is used not like for the oathkeeper matching rules:

Action: compiled.ReplaceAllString(r.URL.String(), cf.RequiredAction),
Resource: compiled.ReplaceAllString(r.URL.String(), cf.RequiredResource),

Reproducing the bug

For this rule in oathkeeper:

[{
    "id": "users-cars-list",
    "upstream": {
    "url": "http://localhost:8080",
    "preserve_host": true
    },
    "match": {
    "url": "http://localhost/v1/users/<[-0-9a-f]+>/cars",
    "methods": ["GET", "HEAD", "OPTIONS"]
    },
    "authenticators": [{
    "handler": "oauth2_introspection",
    "config": {}
    }],
    "authorizer": {
    "handler": "keto_engine_acp_ory",
    "config": {
        "required_action": "read",
        "required_resource": "users:$1",
        "subject": "users:{{ .Subject }}",
        "flavor": "exact"
    }
    },
    "credentials_issuer": {
    "handler": "headers",
    "config": {
        "headers": {
        "X-UID": "{{ print .Subject }}"
        }
    }
    }
}]

Calls to http://localhost/users/aaaa-bbbb-cccc/cars or http://localhost/users/aaaa-bbbb-cccc/cars?limit=10 will be accepted by oathkeeper but Keto engine can't match the rule with the full URL in the second example.

I create a small code example to reproduce the bug in keto engine:

package main

import (
	"fmt"
	"log"

	"github.com/ory/ladon/compiler"
)

func buildPayload(rule, urlstr, action string) {
	r, err := compiler.CompileRegex(rule, '<', '>')
	if err != nil {
		log.Fatalf(err.Error())
	}

	result := r.ReplaceAllString(urlstr, action)
	fmt.Printf("%s is building this payload on %s for this action '%s': %s\n", rule, urlstr, action, result)
}

func main() {
	buildPayload("http://localhost/users/<[-0-9a-f]+>/cars", "http://localhost/users/aaaa-bbbb-cccc/cars", "read")
	buildPayload("http://localhost/users/<[-0-9a-f]+>/cars", "http://localhost/users/aaaa-bbbb-cccc/cars?limit=10", "read")
}

produce this ouput:

http://localhost/users/<[-0-9a-f]+>/cars is building this payload on http://localhost/users/aaaa-bbbb-cccc/cars for this action 'read': read
http://localhost/users/<[-0-9a-f]+>/cars is building this payload on http://localhost/users/aaaa-bbbb-cccc/cars?limit=10 for this action 'read': http://localhost/users/aaaa-bbbb-cccc/cars?limit=10

Server logs
Oathkeeper logs:

time="2019-09-05T19:36:56Z" level=warning msg="Access request granted" access_url="http://localhost:8080/v1/users/aaaa-bbbb-cccc/cars" granted=true
time="2019-09-05T19:36:56Z" level=info msg="completed handling request" measure#oathkeeper-proxy.latency=54877373 method=GET remote="127.0.0.1:55978" request=/v1/users/aaaa-bbbb-cccc/cars status=200 text_status=OK took=54.877373ms

time="2019-09-05T19:37:08Z" level=info msg="started handling request" method=GET remote="127.0.0.1:55978" request="/v1/users/aaaa-bbbb-cccc/cars?limit=10"
time="2019-09-05T19:37:08Z" level=warning msg="The authorization handler encountered an error" access_url="http://localhost/v1/users/aaaa-bbbb-cccc/cars?limit=10" authorization_handler=keto_engine_acp_ory error="Access credentials are not sufficient to access this resource" granted=false reason_id=authorization_handler_error
time="2019-09-05T19:37:08Z" level=warning msg="Access request denied" access_url="http://localhost/v1/users/aaaa-bbbb-cccc/cars?limit=10" error="Access credentials are not sufficient to access this resource" granted=false
time="2019-09-05T19:37:08Z" level=error msg="An error occurred while handling a request" code=403 debug= details="map[]" error="Access credentials are not sufficient to access this resource" reason= request-id= status=Forbidden trace="Stack trace: \ngithub.com/ory/oathkeeper/proxy.(*AuthorizerKetoWarden).Authorize\n\t/go/src/github.com/ory/oathkeeper/proxy/authorizer_keto_warden.go:142\ngithub.com/ory/oathkeeper/proxy.(*RequestHandler).HandleRequest\n\t/go/src/github.com/ory/oathkeeper/proxy/request_handler.go:147\ngithub.com/ory/oathkeeper/proxy.(*Proxy).Director\n\t/go/src/github.com/ory/oathkeeper/proxy/proxy.go:121\nnet/http/httputil.(*ReverseProxy).ServeHTTP\n\t/usr/local/go/src/net/http/httputil/reverseproxy.go:216\ngithub.com/urfave/negroni.Wrap.func1\n\t/go/pkg/mod/github.com/urfave/[email protected]/negroni.go:46\ngithub.com/urfave/negroni.HandlerFunc.ServeHTTP\n\t/go/pkg/mod/github.com/urfave/[email protected]/negroni.go:29\ngithub.com/urfave/negroni.middleware.ServeHTTP\n\t/go/pkg/mod/github.com/urfave/[email protected]/negroni.go:38\ngithub.com/ory/x/metricsx.(*Service).ServeHTTP\n\t/go/pkg/mod/github.com/ory/[email protected]/metricsx/middleware.go:260\ngithub.com/urfave/negroni.middleware.ServeHTTP\n\t/go/pkg/mod/github.com/urfave/[email protected]/negroni.go:38\ngithub.com/meatballhat/negroni-logrus.(*Middleware).ServeHTTP\n\t/go/pkg/mod/github.com/meatballhat/[email protected]/middleware.go:136\ngithub.com/urfave/negroni.middleware.ServeHTTP\n\t/go/pkg/mod/github.com/urfave/[email protected]/negroni.go:38\ngithub.com/urfave/negroni.(*Negroni).ServeHTTP\n\t/go/pkg/mod/github.com/urfave/[email protected]/negroni.go:96\nnet/http.serverHandler.ServeHTTP\n\t/usr/local/go/src/net/http/server.go:2774\nnet/http.(*conn).serve\n\t/usr/local/go/src/net/http/server.go:1878\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1337" writer=JSON
time="2019-09-05T19:37:08Z" level=info msg="completed handling request" measure#oathkeeper-proxy.latency=26918996 method=GET remote="127.0.0.1:55978" request="/v1/users/aaaa-bbbb-cccc/cars?limit=10" status=403 text_status=Forbidden took=26.918996ms

Keto logs (I added a print of the request payload):

time="2019-09-05T19:36:56Z" level=info msg="started handling request" method=POST remote="127.0.0.1:46930" request=/engines/acp/ory/exact/allowed
2019/09/05 19:36:56 Request:
	Resource: users:aaaa-bbbb-cccc
	Action: read
	Subject: users:aaaa-bbbb-cccc
	Context: map[remoteIpAddress:127.0.0.1 requestedAt:2019-09-05T19:36:56.255031511Z]
time="2019-09-05T19:36:56Z" level=info msg="completed handling request" measure#keto.latency=13811253 method=POST remote="127.0.0.1:46930" request=/engines/acp/ory/exact/allowed status=200 text_status=OK took=13.811253ms


time="2019-09-05T19:37:08Z" level=info msg="started handling request" method=POST remote="127.0.0.1:46930" request=/engines/acp/ory/exact/allowed
2019/09/05 19:37:08 Request:
	Resource: http://localhost/v1/users/aaaa-bbbb-cccc/cars?limit=10
	Action: http://localhost/v1/users/aaaa-bbbb-cccc/cars?limit=10
	Subject: users:aaaa-bbbb-cccc
	Context: map[remoteIpAddress:127.0.0.1 requestedAt:2019-09-05T19:37:08.851267513Z]
time="2019-09-05T19:37:08Z" level=info msg="completed handling request" measure#keto.latency=13596698 method=POST remote="127.0.0.1:46930" request=/engines/acp/ory/exact/allowed status=403 text_status=Forbidden took=13.596698ms

Expected behavior

Keto engine should ignore query parameters like oathkeeper matching rule

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant