acquisition, traversal, acl_users and security
Hi all, I'm having a problem, but first let me explain generally what I'm trying to do. I'm want to provide alternative management screens to those found at /manage. The goal is also not to use any additional products that don't come with a vanilla zope install (actually, I've allowed myself the luxury of Formulator, but that doesn't matter for these purposes). So, I've added a folder called 'control' that contains all of my management screens. These work pretty nicely (even though I say so myself ;-) ). Now, users just need to append /control to their url and they get quite a user friendly editing experience. In the 'control' security tab, I've left everything on 'Acquire Permissions' except for 'View', which I've limited to 'Manager' only. This works well when the user logging in is defined in an acl_users that is a sibling of 'control', but does not work when the acl_users is defined further down the tree and 'control' is being acquired. e.g. - site_root_folder - acl_users - control - folder1 - acl_users /site_root_folder/control works; /site_root_folder/folder1/control raises Unauthorized when the user is defined in site_root_folder/folder1/acl_users instead of site_root_folder/acl_users. I did a little searching on this list, and I think found that this is an explicit feature of the zope security policy that is designed to stop people from circumventing security by using url traversal tricks - which I guess is effectively what I'm trying to do. So, my questions are: Is my diagnosis right? Is there any way around this problem without going to filesystem code? Does anybody have a suitable __of__ method (or somesuch) that would allow me to achieve what I want if I do have to use fs code? cheers, tim
At 09:57 AM 2/27/2003, Tim Hicks wrote:
In the 'control' security tab, I've left everything on 'Acquire Permissions' except for 'View', which I've limited to 'Manager' only. This works well when the user logging in is defined in an acl_users that is a sibling of 'control', but does not work when the acl_users is defined further down the tree and 'control' is being acquired.
This is more an HTTP issue than a Zope issue. A best practice here is to design your Folder hierarchy such that the most widely-available, least-restricted stuff is closer to the root and the more specialized, restricted stuff is off on the branches. But let's say you've got what you've got. Your user is authenticated three levels in and you want their privileges to apply two levels up. The easiest way to hack this is by giving a proxy role to the method in question. Another fairly easy trick is to use a method at their level that uses unrestrictedTraverse() to circumvent security policies on their behalf. But it may be just as easy to have one acl_users and work a little harder on creating finer-grained roles. Perhaps some of these roles are mostly entitled only to use methods that are several levels in... but one or two methods at the site root could be made to respond to those roles as well. For a decent-size site of any complexity, I'd recommend putting effort into designing your roles up front. It's going to be a lot easier to figure out who can do what later on if you save proxy roles and magic traversal for the truly exceptional cases. HTH, Dylan
Hi Dylan, thanks for your super-fast response :)... Dylan Reinhardt said:
At 09:57 AM 2/27/2003, Tim Hicks wrote:
In the 'control' security tab, I've left everything on 'Acquire Permissions' except for 'View', which I've limited to 'Manager' only. This works well when the user logging in is defined in an acl_users that is a sibling of 'control', but does not work when the acl_users is defined further down the tree and 'control' is being acquired.
This is more an HTTP issue than a Zope issue.
I'm not convinced about that. I didn't add last time that I did another test. I defined a user 'test' in site_root_folder/acl_users (without a role), then assigned a local role for the 'test' user in folder1. I also removed folder1/acl_users. This meant that authentication was being done by site_root_folder/acl_users, but I was still getting Unauthorized.
A best practice here is to design your Folder hierarchy such that the most widely-available, least-restricted stuff is closer to the root and the more specialized, restricted stuff is off on the branches.
Why is that? I don't see how that helps me. Anyway, I don't want these edit screens to dictate site structures etc. I really just want a drop-in replacement for /manage (which works everywhere).
But let's say you've got what you've got. Your user is authenticated three levels in and you want their privileges to apply two levels up.
Hmm, I don't want their priveleges to apply two levels up, I want the 'control' folder to recognise that it is (by acquisition) now in 'folder1' and then allow the 'Manager' defined in folder1/acl_users to 'View' folder1/control/index_html (which is a listing of folder1 contents).
The easiest way to hack this is by giving a proxy role to the method in question.
Do you mean giving control/index_html a proxy role of manager? I don't think that would work but I don't think that is what you mean.
Another fairly easy trick is to use a method at their level that uses unrestrictedTraverse() to circumvent security policies on their behalf.
Have you got an example of what you mean here? [... roles stuff ...] For the current project I'm working on, the roles are pre-defined and not changeable by me. Even so, the notion of not wanting the management screens to dictate site setup (as far as possible) still stands. cheers, tim
Let's give this another try... At 10:29 AM 2/27/2003, Tim Hicks wrote:
This is more an HTTP issue than a Zope issue.
I'm not convinced about that.
Under HTTP 1.1, IIRC, if a browser authenticates by a request to http://server/a/b/c then it should, by default, assume the same credentials apply to http://server/a/b/c/d but not to http://server/a/b which must be authenticated separately.
I didn't add last time that I did another test. I defined a user 'test' in site_root_folder/acl_users (without a role), then assigned a local role for the 'test' user in folder1. I also removed folder1/acl_users. This meant that authentication was being done by site_root_folder/acl_users, but I was still getting Unauthorized.
If I read you correctly, you deleted the user that had the local role, leaving the one without a local role. Creating two user objects at different levels does not provide one account that can apply at two levels... it provides two different users with different privileges at different places who just happen to have the same name. Which one you're working with will be determined by what you requested when you authenticated.
I don't want these edit screens to dictate site structures etc. I really just want a drop-in replacement for /manage (which works everywhere).
OK... I think I'm following you now. Say your hierarchy looks something like this; sites/ control/ vhost1/ acl_users/ index_html some_folder/ vhost2/ acl_users/ index_html You want to be able to call URLs like: http://vhost1/control http://vhost1/some_folder/control http://vhost2/control But you want the privileges that control runs under to be determined by where in the folder hierarchy the user is working. Right so far? If so, you're in luck. Virtually no difficult work will be required. The most important thing will be to create *one* user object per human user and to assure that each user object is put as high in the hierarchy as it is meant to apply. Restrict access to deeper folders by cranking up the roles required, not by creating additional acl_users. Now, when a user calls something like: http://vhost1/some_folder/control it is OK to leave control totally open to anonymous users. This way, the user's level of access to the contents of some_folder are still what determines the need for authentication. Thus, if control/index_html makes use of some restricted attribute of its acquisition parent, the parent's security will kick in if index_html's doesn't. Since we leave index_html totally open, we'll get the parent's security every time. Be sure not to give the contents of control any proxy roles in this scenario... that could be a very bad thing. Is that a bit closer to what you're looking for? This is top-of-the-head, untested, broad-strokes stuff, but hopefully useful. Dylan
But let's say you've got what you've got. Your user is authenticated three levels in and you want their privileges to apply two levels up.
Hmm, I don't want their priveleges to apply two levels up, I want the 'control' folder to recognise that it is (by acquisition) now in 'folder1' and then allow the 'Manager' defined in folder1/acl_users to 'View' folder1/control/index_html (which is a listing of folder1 contents).
The easiest way to hack this is by giving a proxy role to the method in question.
Do you mean giving control/index_html a proxy role of manager? I don't think that would work but I don't think that is what you mean.
Another fairly easy trick is to use a method at their level that uses unrestrictedTraverse() to circumvent security policies on their behalf.
Have you got an example of what you mean here?
[... roles stuff ...]
For the current project I'm working on, the roles are pre-defined and not changeable by me. Even so, the notion of not wanting the management screens to dictate site setup (as far as possible) still stands.
cheers,
tim
Hi again, Dylan Reinhardt said:
Let's give this another try...
[... HTTP 1.1 stuff ...]
I don't want these edit screens to dictate site structures etc. I really just want a drop-in replacement for /manage (which works everywhere).
OK... I think I'm following you now.
Say your hierarchy looks something like this;
sites/ control/ vhost1/ acl_users/ index_html some_folder/ vhost2/ acl_users/ index_html
You want to be able to call URLs like:
http://vhost1/control http://vhost1/some_folder/control http://vhost2/control
But you want the privileges that control runs under to be determined by where in the folder hierarchy the user is working. Right so far?
That's absolutely what I want :).
If so, you're in luck. Virtually no difficult work will be required. The most important thing will be to create *one* user object per human user and to assure that each user object is put as high in the hierarchy as it is meant to apply. Restrict access to deeper folders by cranking up the roles required, not by creating additional acl_users.
Now, when a user calls something like:
http://vhost1/some_folder/control
it is OK to leave control totally open to anonymous users. This way, the user's level of access to the contents of some_folder are still what determines the need for authentication.
Yeah, this solution came to me this morning as well, although I haven't tried it yet. The only downside I can see is that all users would be able to see the management screens. This may potentially reveal more information than is desirable (depending on what the management screens show of course). Seeing as I have a single page template macro controlling layout of all pages within 'control', perhaps I could put a little code at the top there to check permissions and block anonymous users. I'll have to experiment.
Thus, if control/index_html makes use of some restricted attribute of its acquisition parent, the parent's security will kick in if index_html's doesn't. Since we leave index_html totally open, we'll get the parent's security every time. Be sure not to give the contents of control any proxy roles in this scenario... that could be a very bad thing.
Indeed.
Is that a bit closer to what you're looking for?
Yeah, that's great. I really appreciate your input.
This is top-of-the-head, untested, broad-strokes stuff, but hopefully useful.
Cheers, tim
At 05:21 AM 2/28/2003, Tim Hicks wrote:
The only downside I can see is that all users would be able to see the management screens. This may potentially reveal more information than is desirable (depending on what the management screens show of course).
One fairly easy hack would be to drop a specially named method in each root folder that returns some string value. Let's call it my_access_rights. Then secure that object with the set of privileges you want to pertain to those able to manage folder contents. Put a different one at each point where your access scheme changes. With that in place, make sure each of your management screens do something like: <dtml-call my_access_rights> If it's not accessible (or isn't there at all) your user is probably trying to play outside the sandbox. Luckily, the interface will kick out an error instead of rendering. You'll probably want a special standard_error_message for the control folder. HTH, Dylan
participants (2)
-
Dylan Reinhardt -
Tim Hicks