SoftInstigate / restheart

Rapid API Development with MongoDB
https://restheart.org
GNU Affero General Public License v3.0
807 stars 171 forks source link

Cannot add security rule with filter query string #336

Closed jarodhanko closed 5 years ago

jarodhanko commented 5 years ago

Expected Behavior

The request to "/testdb/testcoll/?filter={'userid':'admin'}" should match the security rule

It works fine with pattern="/testdb/testcoll/\?.*" but as soon as I add something after the ? it is no longer matches the security rule.

Current Behavior

Requests return 403 forbidden if the security rule contains a filter query parameter.

Context

I am try to enforce security within a collection where it needs to limit access by userid. I'll be using a request tranformer to ensure the user cannot access other user documents, but I would like to be able to enforce this through a rule as well (I have some similar security rules that I need to enforce this way). I am not actually enforcing the username filter yet since I can't get it to match the request in the first place.

Environment

OS: Ubuntu Server 18.04.1 LTS Java Version: openjdk 10.0.2 Mongo Version: 4.0.6 Restheart Version: 3.8.0 (or compiled from github/master)

Request

GET http://192.168.XXX.XXX:8080/testdb/testcoll/?filter=%7B'userid':'admin'%7D HTTP/1.1 Authorization: Basic dXNlcjI6Y2hhbmdlaXQ= Host: 192.168.XXX.XXX:8080 Request-Id: |e413cc706a19824689859cc0065a6d57.99d67253_99d67254_1.1.44. Connection: Keep-Alive

Response

HTTP/1.1 403 Forbidden X-Powered-By: restheart.org Auth-Token-Location: /_authtokens/user2 Access-Control-Expose-Headers: Location, ETag, Auth-Token, Auth-Token-Valid-Until, Auth-Token-Location, X-Powered-By Date: Fri, 22 Feb 2019 15:01:44 GMT Auth-Token: 4f7l6qp5b4tw4hp3qwvf0v754hs2hg71eome5l6a33nspuapzv Connection: keep-alive Access-Control-Allow-Origin: * Auth-Token-Valid-Until: 2019-02-22T15:16:44.357154Z Access-Control-Allow-Credentials: true Content-Length: 0

Steps to Reproduce

  1. Create a mongodb with a db "testdb" and a collection "testcoll" testcoll: [ { _id: $oid, userid: "admin", data: "asdf" }, { _id: $oid, userid: "notadmin", data: "fdsa" } ]
  2. update default.properties mongo-uri with correct username:password
  3. Clone restheart from github
  4. Use my provided default.properties, restheart.yml, security.yml which are pretty much the example files with a couple small changes
  5. sudo mongod --fork --syslog --auth
  6. sudo java -Dfile.encoding=UTF-8 -server -jar restheart.jar etc/restheart.yml --envFile etc/default.properties --fork
  7. GET "/testdb/testcoll/?filter={'userid':'admin'}" using Authentication Header Authentication: Basic dXNlcjI6Y2hhbmdlaXQ= base64(user2:changeit)
  8. Result is 403 Forbidden

security.yml.txt default.properties.txt restheart.yml.txt

Patterns to try: pattern - "/testdb/testcoll/\?filter." result - 403 pattern - "/testdb/testcoll/\?." result - 200 pattern - "/testdb/testcoll/." result - 200 pattern - "/testdb/testcoll/.f.* result - 403

My only thought was that %R and %U are not including the query string in the pattern, but it still matches ? which is weird if that was the case.

Let me know if I am just configuring something incorrectly or if my regex is written improperly. In my actual environment I am using JWT auth and DbIdentityManager but the problem seems to occur even without these being enabled.

ujibang commented 5 years ago

you can use a predicate on the Query parameter Attribute %{q,query_param_name}

see http://undertow.io/undertow-docs/undertow-docs-1.2.0/predicates-attributes-handlers.html for more information

jarodhanko commented 5 years ago

Thanks I got it working using %q (using {%q, filter} didn't seem to do anything different for some reason. I don't understand what the first character of the regex is through. The regex that ended up working is

regex[pattern="/testdb/testcoll/\?.*", value="%R", full-match=true] and regex[pattern=".{1}\?.*filter=%7B'userid':'(.+?)'%7D.*", value="{%q}", full-match=true] and equals[%u, "${1}"]

I don't understand why there is a character before ?filter= and { and } are url encoded but ? is simply escaped. In any case, I think it will do what I need it to do.