ory / ladon

A SDK for access control policies: authorization for the microservice and IoT age. Inspired by AWS IAM policies. Written for Go.

Home Page:https://www.ory.sh/?utm_source=github&utm_medium=banner&utm_campaign=ladon

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Issue with resource naming

adhicoder opened this issue · comments

I came across a peculiar issue with Ladon. One of the resources I used was name "Product:<.*>" It worked fine. But on renaming the resource to "product:<.*> ", the resource is not getting appended to the resources array. All other variations like "product:attributeGroup:<.*> ", "product:attributeGroup:attribute" work fine and get appended to the resources array. But on trying to insert"product:<.*> " with a lowercase "p" alone, it fails.
There is an issue if action name is "create" as well. It is only for these particular cases that it fails.
Is this a known bug? Is there a fix?

Which DB layer do you use?

I use SQL with the manager.

MySQL or PostgreSQL?

MySQL

Ok, it seems to be an issue with the unique constraint or rather that the field is case insensitive (as opposed to case sensitive). This isn't a big deal for security (README says: "All checks are case sensitive because subject values could be case sensitive IDs.") because we're checking this twice (we do not only rely on the manager implementation to give us correct results) but apparently it messes with the ability of the SQL manager to store values which have the same characters, but different capitalization.

Two possibilities for this issue:

  1. The fields are not case sensitive, in that case we have to convert them to something like VARCHAR BINARY or VARBINARY.
  2. We're using an operator (maybe LIKE?) somewhere that is case insensitive.

I suspect that this issue is with MySQL only (varchar is case sensitive in PostgreSQL afaik). Could you be so kind and add two failing test cases confirming this for both managers and spin it up in a PR? It will help tremendously in identifying the issue.

Just to be clear, the issue is not that an access request fails, but that the resource or action does not get inserted and stored in the policy at the time of creation during certain instances. Is this related to case insensitivity? It is hard to predict in which cases the insertion fails and in which cases it succeeds. Two of the failing cases are as follows:

{
  "id":"1",
  "description": "SimplePolicy",
  "subjects": ["admins","suppliers"],
  "actions" : ["update", "read"],
  "effect": "allow",
  "resources": [
     "product:<.*>"
   ]
}

is stored as

{
  "id":"1",
  "description": "SimplePolicy",
  "subjects": ["admins","suppliers"],
  "actions" : ["update", "read"],
  "effect": "allow",
  "resources": []
}

Another case is

{
  "id":"2",
  "description": "SimplerPolicy",
  "subjects": ["suppliers"],
  "actions" : ["create"],
  "effect": "allow",
  "resources": [
     "product:attributeGroup:<.*>"
   ]
}

which is stored as

{
  "id":"2",
  "description": "SimplerPolicy",
  "subjects": ["suppliers"],
  "actions" : [],
  "effect": "allow",
  "resources": [
     "product:attributeGroup:<.*>"
   ]
}

On the other hand, if "Update" is inserted in the actions field or "prodcuts:<.*>" is inserted in the resources field, it is stored properly. What is the reason for this?

If I understood correctly, "Product:<.*>" is already inserted before you add the policy with "id":"1", right? In that case yes, it is most likely due to case insensitivity. We have a unique constraint on resource/action/subject names so in order to avoid duplicates, the library looks if that resource already exists. If it does (which might be in your case due to case insentivity), then it might skips creation of that particular field and uses its ID only. Not sure why it's skipped completely then, but we'll figure it out.

This is all speculation though, it would be much more helpful if you could provide two failing test cases in a PR and then I can take a closer look at what's happening.

"Product:<.>" was not inserted beforehand, so it is not a conflict caused due to duplicates. "product:<.>" failed to insert even though it was the first policy in the database. I will raise the PR with the failing test cases soon, but if you have any thoughts on this other than duplicacy issues, please let me know.

Oh ok I see, that's really weird. No idea what may cause this. Does create return an error or something? Also which MySQL version are you using?

Failing test case is the way to go though :)

No, there is no error returned but the policy is created with an empty array for resources. I am using MYSQL Community Server 5.7.20.

I tried to test 'policy_test.go' with the command
go test -run 'policy_test.go'. This throws an error
Could not start resource: : dial unix /var/run/docker.sock: connect: no such file or directory.
Is there anything I need to do before running tests, like setting up docker? I am currently working on macOS. Pardon me if this is a silly question, but I am new to go and would appreciate help.

Not a silly question :) You have to install docker on your machine or the database connectivity won't work. There is currently no way to use a local/remote MySQL/PostgreSQL cluster that isn't managed by Docker. If you have that (and want that) I can quickly add this capability.

Once you have that, my recommendation is to run all tests go test ./... because you really want to look at the database tests. You can add your policies which don't work for you here. However, to really make things work you'll have to add some equality checks here as well, because right now we are only checking if all the policies exist, not if their values are equal.

I get the following stats after I ran the tests.

ok  	ladon	21.513s
ok  	ladon/compiler	0.029s
?   	ladon/integration	[no test files]
?   	ladon/manager/memory	[no test files]
?   	ladon/manager/sql	[no test files]

I don't think ladon/manager_test_helper.go is getting covered. This is because I changed an assert statement in the file and it must have failed, but there was no difference when I ran it. By the way, the package included for this file is package ladon rather than package ladon_test. Is that right? I did try adding the failed policies and adding equality checks but I don't think the test file is included in the tests.

Hm that's strange. Could you fire up a work in progress PR so I can take a look?

I have created a PR from my fork. As of now, I have created two example policies which are supposed to fail. I have modified the equality check as well. I have modified the assert so that it is supposed to fail but I think manager_test_helper.go is not being tested when I run go test ./... Please check if I am doing anything wrong so that I can fix the test.

Thank you, let's move the discussion to the PR then!

I replied on the PR, could you check please? Thanks.