Size: 7769
Comment: patch update against moin--main--1.3 patch-935
|
Size: 8045
Comment: fixed lots of typos, please someone add posix acls
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
'''Applying access control lists using wiki hierarchy.''' | = Applying access control lists using wiki hierarchy = |
Line 3: | Line 3: |
= How does AccessControlList class work currently? = | == How does AccessControlList class work currently? == |
Line 5: | Line 5: |
Acl objects are made from acl lines in config and page. First acl_before line is copied, then page lines are copied from page, or acl_default if page does not have acl lines. Last, acl_after line is copied. Then, acl object is created from the lines. This object contain a list of right dictionaries. This object is created for each page and cached. | ACL objects are made from ACL lines in config and page. First acl_rights_before line is copied, then page lines are copied from page, or acl_rights_default if page does not have ACL lines. Last, acl_rights_after line is copied. Then, ACL object is created from the lines. This object contains a list of rights dictionaries and is created for each page and cached. |
Line 7: | Line 7: |
When accessing pages, user may mehtod is called, which retrive the acl object from the page and check for rights. | When accessing a page, user.may method is called, which retrieves the acl object from the page and checks for rights. |
Line 9: | Line 9: |
== problems == | === Problems === |
Line 11: | Line 11: |
=== acl_before, acl_default and acl_after are duplicated for every page === | ==== acl_rights_before, acl_rights_default and acl_rights_after are duplicated for every page ==== |
Line 13: | Line 13: |
Worst case example: in a 1000 pags wiki with no acls, we copy acl_before, acl_default and acl_after to any page acl, then parse the same lines 1000 times, and finally cache 1000 equal acl instances. | Worst case example: in a 1000 pages wiki with no acls, we copy acl_before, acl_default and acl_after to any page acl, then parse the same lines 1000 times, and finally cache 1000 equal acl instances. |
Line 15: | Line 15: |
With hierarchical acl, we would parse once acl_before, acl_after and acl_default, and keep them in memory, then cache None for every other page in the acl cache. | With hierarchical acl, we would parse acl_rights_before, acl_rights_after and acl_rights_default ''once'' and keep them in memory, then cache None for every other page in the acl cache. |
Line 19: | Line 19: |
* We should check this for 1.3.3, even if we don't do hierarchical in 1.3 | ==== Using ACLs is too much work ==== |
Line 21: | Line 21: |
=== Too much work to use === | You must add acl lines to any page you want to protect with different acl than the default acls. For example, if you would like to create some few pages for one project, you will have to add acl lines to each new page. If you want to change the project acl rights, you have to do it again for all the pages of the project. |
Line 23: | Line 23: |
You must add acl lines to any page you want to protect with different acl then the default acls. For example, if you would like to create few pages for one project, you will have to add acl lines to each new page. If you want to change the project acl rights, you have to do it again on all the pages of the projects. | One example is the acl rights of the help and system pages. To change these we use a script to edit all those pages text outside the wiki. |
Line 25: | Line 25: |
An example is the acl rights of the help and system pages. To change these we use a script the edit all those pages text outside the wiki. = Testcases = |
=== Testcases === |
Line 31: | Line 29: |
''Implementations'' * ... |
|
Line 34: | Line 30: |
= How hierarchial acl should work = | === How hierarchial ACLs should work === |
Line 42: | Line 38: |
* acl_rights_xx are splited from the page acl. Each acl_right_xx is parsed and saved in the wiki config, then can be checked separately. * acl_rights_default is treated as the wiki virtual root page acl, which all page inherit from. If a page does not have acl, it inherit from its parent, if the parent does not have acl, it inherit from acl_rights_default. * replace that lambda in security with real function * make that fuction avoid loading page acl if that not needed |
* acl_rights_xx are separated from the page acl object. Each acl_rights_xx is parsed and saved in the wiki config, then it can be checked separately. * acl_rights_default is treated as the wiki virtual root page acl, which all pages inherit from. If a page does not have acl, it inherits from its parent, if the parent does not have acl, it inherits from acl_rights_default. * replace that lambda in security module with a real function * make that fuction avoid loading page acl if not needed |
Line 47: | Line 43: |
Flow of acl chekcing: | Flow of acl checking: |
Line 52: | Line 48: |
1. Last, if no acl match, we deny the access. | 1. Last, if no acl matches, we deny access. |
Line 54: | Line 50: |
== Benefits == | === Benefits === |
Line 56: | Line 52: |
* Less work to define acl, define only few acls for whole wiki using sub pages. | * Less work to define ACLs, define only some few ACLs for the whole wiki using sub pages. |
Line 59: | Line 55: |
== Performance Issues == | === Performance Issues === |
Line 61: | Line 57: |
* In the best case when acl_rights_before match, we don't have to get acl from the page/s, which means preventing expensive disk access. | * In the best case when acl_rights_before matches, we don't have to get the ACL from the page/s, which means preventing expensive disk access. * This is rather rarely the case. before is often used for the wiki admin only. |
Line 63: | Line 60: |
* How can it be better cached than now? | |
Line 64: | Line 62: |
== Changes to current code == | === Changes to current code === |
Line 66: | Line 64: |
The current `AccessControlList.may` check a composite acl object, made from all acl_rights and page rights, and return True or False. The new may function will check a single acl object, and return 3 answers: True, False or None, which means "don't know". The basic acl check look like this: | The current `AccessControlList.may` checks a composite acl object, made from all acl_rights* and page rights, and returns True or False. The new .may function will check a single acl object, and return 3 answers: True, False or None, which means "don't know". The basic acl check looks like this: |
Line 78: | Line 76: |
== Posix file system like hierarchy == | === Posix file system like hierarchy === |
Line 80: | Line 78: |
The should work like file system permissions. Say there are the following pages, !TopSecret and !TopSecret/!PasswordFiles . If the user "protects" !TopSecret by removing read right to everyone but himself, it would '''naturally''' expect everything bellow !TopSecret to be procected. | This should work like file system permissions. Say there are the following pages, !TopSecret and !TopSecret/!PasswordFiles . If the user "protects" !TopSecret by removing read right to everyone but himself, he would '''naturally''' expect everything below !TopSecret to be protected. |
Line 92: | Line 90: |
Benefits: * Can't give more rights to a part of a tree, you can only add protection * Familiar and simple concept, less error prone |
Pro: * Familiar and simple concept, less error prone. Contra: * You can't make e.g. a subpage less restrictive than its upper pages. |
Line 96: | Line 95: |
== Traditional ACL hierarchy == | === Traditional ACL hierarchy === |
Line 110: | Line 109: |
Benefits: * More power, you can define any acl to any page, ignoring the parent acl Here is a patch for this solution: attachment:hierachical-acl.diff |
Pro: * More power, you can define any acl to any page, ignoring the parent acl. Here is a patch for this solution: attachment:hierachical-acl.diff |
Line 118: | Line 116: |
* ??? what does this mean ??? | |
Line 119: | Line 118: |
=== Patch update === | ==== Patch update ==== |
Line 131: | Line 130: |
My simple fix at the moment is to disable this lines. Maybe somebody can help here. I have no overview over the system classes yet. | My simple fix at the moment is to disable these lines. Maybe somebody can help here. I have no overview over the system classes yet. |
Line 138: | Line 137: |
Will not apply the default acls correctly. | will not apply the default acls correctly. |
Line 140: | Line 139: |
=== Patch update against moin--main--1.3 patch-935 === | ==== Patch update against moin--main--1.3 patch-935 ==== |
Line 144: | Line 143: |
== Inherit parent pages acl lines == Here when page acl is created, it copies all lines from parent pages, so the total lines page lines are acl_before + parents lines + page lines + acl_after |
=== Inherit parent pages acl lines === Here when a page acl is created, it copies all lines from parent pages, so the total acl lines per page are acl_before + parents lines + page lines + acl_after |
Line 153: | Line 152: |
= Reference = | == Reference == |
Line 155: | Line 154: |
== NTFS ACL == | === NTFS ACLs === |
Line 163: | Line 162: |
* The ACL of the object may enhance or narrow done the inherited ACL. This is possible because there is allow and revoke. | * The ACL of the object may enhance or narrow down the inherited ACL. This is possible because there is allow and revoke. === Posix ACLs === Maybe someone familiar with them can add how they work? |
Applying access control lists using wiki hierarchy
How does AccessControlList class work currently?
ACL objects are made from ACL lines in config and page. First acl_rights_before line is copied, then page lines are copied from page, or acl_rights_default if page does not have ACL lines. Last, acl_rights_after line is copied. Then, ACL object is created from the lines. This object contains a list of rights dictionaries and is created for each page and cached.
When accessing a page, user.may method is called, which retrieves the acl object from the page and checks for rights.
Problems
acl_rights_before, acl_rights_default and acl_rights_after are duplicated for every page
Worst case example: in a 1000 pages wiki with no acls, we copy acl_before, acl_default and acl_after to any page acl, then parse the same lines 1000 times, and finally cache 1000 equal acl instances.
With hierarchical acl, we would parse acl_rights_before, acl_rights_after and acl_rights_default once and keep them in memory, then cache None for every other page in the acl cache.
- This is independent from hierachical ACLs, isn't it? So we should think about implementing it as fast as possible in order to gain speed.
Using ACLs is too much work
You must add acl lines to any page you want to protect with different acl than the default acls. For example, if you would like to create some few pages for one project, you will have to add acl lines to each new page. If you want to change the project acl rights, you have to do it again for all the pages of the project.
One example is the acl rights of the help and system pages. To change these we use a script to edit all those pages text outside the wiki.
Testcases
Please add some test cases and write how your suggestion would catch these.
- There are project groups that need their own page hierachies. Every project group wants to protect some pages to be read just by the particular project group. Others should just be open to other projects. The remaining ones should stay public.
How hierarchial ACLs should work
before -> default -> parent page -> sub page -> after -> No!
Changes:
- acl_rights_xx are separated from the page acl object. Each acl_rights_xx is parsed and saved in the wiki config, then it can be checked separately.
- acl_rights_default is treated as the wiki virtual root page acl, which all pages inherit from. If a page does not have acl, it inherits from its parent, if the parent does not have acl, it inherits from acl_rights_default.
- replace that lambda in security module with a real function
- make that fuction avoid loading page acl if not needed
Flow of acl checking:
- acl_rights_before checked, so the admin can define rights nobody can override.
- acl_rights_default, pages and sub pages are checked - the order depending on the implementation
- acl_rights_after is checked, so we can add default rights to all pages.
- Last, if no acl matches, we deny access.
Benefits
- Less work to define ACLs, define only some few ACLs for the whole wiki using sub pages.
Needs very small cache which can be loaded from disk very fast - see MoinCaching.
Performance Issues
- In the best case when acl_rights_before matches, we don't have to get the ACL from the page/s, which means preventing expensive disk access.
- This is rather rarely the case. before is often used for the wiki admin only.
- In the worst case we have to check more than one page acl, which means multiple expensive disk accesses. We can solve this by better acl caching.
- How can it be better cached than now?
Changes to current code
The current AccessControlList.may checks a composite acl object, made from all acl_rights* and page rights, and returns True or False. The new .may function will check a single acl object, and return 3 answers: True, False or None, which means "don't know". The basic acl check looks like this:
1 allowed = acl.may(request, name, what)
2 if allowed is not None:
3 return allowed
The complete acl checking will move from AccessControlList.may to the SecurityPolicy.xxx, e.g. SecurityPolicy.read
Checking the page hierarchy can be done in two ways: Posix file system like, or traditional acls.
Posix file system like hierarchy
This should work like file system permissions. Say there are the following pages, TopSecret and !TopSecret/!PasswordFiles . If the user "protects" TopSecret by removing read right to everyone but himself, he would naturally expect everything below TopSecret to be protected.
For example, for the path a/b/c:
- check acl_rights_before
- check acl_rights_default
- check a
- check a/b
- check a/b/c
- check acl_rights_after
- return False
Pro:
- Familiar and simple concept, less error prone.
Contra:
- You can't make e.g. a subpage less restrictive than its upper pages.
Traditional ACL hierarchy
Check each page acl, starting with the longest path, so each page can override the parent.
For example, for the path a/b/c:
- check acl_rights_before
- check a/b/c
- check a/b
- check a
- check acl_rights_default
- check acl_rights_after
- return False
Pro:
- More power, you can define any acl to any page, ignoring the parent acl.
Here is a patch for this solution: attachment:hierachical-acl.diff
Notes:
- We don't need to check for some_acl, simply check acl_rights_default after the page hierarchy, in case no page acl matched.
- ??? what does this mean ???
Patch update
I was searching for solution to allow my users creating new pages and added this patch. The current version for Debian uses patch level 666 of MoinMoinWiki. So here the corresponding patch: attachment:hierachical-acl-666.diff
But after applying this patch i found a bug in wikiacl.py (addDefault is not available anymore):
154 if entries == ['Default']: 155 self.addDefault(cfg) 156 continue
My simple fix at the moment is to disable these lines. Maybe somebody can help here. I have no overview over the system classes yet. -- StephanZehrer DateTime(2005-06-12T13:11:59Z)
The original patch is wrong, addDefault is needed. Without it, acl lines like
#acl UserName:read,write Default
Patch update against moin--main--1.3 patch-935
I diffed the hierachical-acl patch one more time against current stable repository after fixing the addDefault problem pointed out above. I believe hierachical-acl is a much better model than the default one so I recommend inclusion in mainline (at least in the development tree). For example this automatically prevent spam blogging with the example in the Include macro. It works fine for me. attachment:hierachical-acl-moin--main--1.3-935.diff
Inherit parent pages acl lines
Here when a page acl is created, it copies all lines from parent pages, so the total acl lines per page are acl_before + parents lines + page lines + acl_after
attachment:inherit-parent-acl.diff
Updated patch to moin--main--1.3--patch-556
But I think the solution above which splits the acls and and does not need all this cache-mangeling here would be the better way of doing it. -- OliverGraf
Reference
NTFS ACLs
In NTFS' ACLs, it works like this:
- Each object has an ACL.
- Each object has a virtual flag "inherited_acl".
- Each object can contain its own ACL.
- Each entry of the ACL might be allow or revoke.
- If it is inherited, every change of the parent ACL is inherited.
- The ACL of the object may enhance or narrow down the inherited ACL. This is possible because there is allow and revoke.
Posix ACLs
Maybe someone familiar with them can add how they work?