Hi all,
I'm banging my head against a wall trying to get one particular ACL setup. We want our users, with the exception of those that have a restricted shell, to be able to change their own shell values. A typical user looks like:
dn: uid=user,ou=people,dc=cs,dc=brown,dc=edu objectClass: top objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount objectClass: krb5Principal objectClass: sambaSamAccount objectClass: ownCloudUser objectClass: mailUser ... loginShell: /bin/bash
We'd ideally like to have an ACL in place that looks like:
access to dn.subtree="ou=people,dc=cs,dc=brown,dc=edu" attrs=loginShell val.regex="/bin/[^f][^s][^h]" by ssf=128 self write by * read
The idea being that a user with a loginShell value of /bin/fsh would NOT be allowed to change their shell value. However, with this rule in place, no user is able to change their shell value. Even if I change the rule to be:
access to dn.subtree="ou=people,dc=cs,dc=brown,dc=edu" attrs=loginShell val.exact="/bin/bash" by ssf=128 self write by * read
users with loginShell of /bin/bash still can't change their own values. If I drop the val.<type>="<whatever>" restriction, users can change their shell values just fine. This the first time I've ever used and ACL with a val.<type>= restriction, but I've scoured the internet and I can't for the life of me figure out what I'm doing wrong. I'm happy to have someone here give me a dope slap... I'm just tired of the headaches ;)
Thanks!
Mark
Mark Dieterich wrote:
by ssf=128 self write
I don't think this works. Probably should be just
It works just fine with the ssf=128 in there if I drop the val.<type> statement.
by self write
Regardless, I dropped it and still ended up with the same insufficient access error.
Then I'd try to remove the quotes around your regex.
Ciao, Michael.
Am Fri, 11 Oct 2013 16:35:34 -0400 schrieb Mark Dieterich mkd@cs.brown.edu:
Hi all,
I'm banging my head against a wall trying to get one particular ACL setup. We want our users, with the exception of those that have a restricted shell, to be able to change their own shell values. A typical user looks like:
dn: uid=user,ou=people,dc=cs,dc=brown,dc=edu objectClass: top objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount objectClass: krb5Principal objectClass: sambaSamAccount objectClass: ownCloudUser objectClass: mailUser ... loginShell: /bin/bash
We'd ideally like to have an ACL in place that looks like:
access to dn.subtree="ou=people,dc=cs,dc=brown,dc=edu" attrs=loginShell val.regex="/bin/[^f][^s][^h]" by ssf=128 self write by * read
The idea being that a user with a loginShell value of /bin/fsh would NOT be allowed to change their shell value. However, with this rule in place, no user is able to change their shell value. Even if I change the rule to be:
access to dn.subtree="ou=people,dc=cs,dc=brown,dc=edu" attrs=loginShell val.exact="/bin/bash" by ssf=128 self write by * read
users with loginShell of /bin/bash still can't change their own values. If I drop the val.<type>="<whatever>" restriction, users can change their shell values just fine. This the first time I've ever used and ACL with a val.<type>= restriction, but I've scoured the internet and I can't for the life of me figure out what I'm doing wrong. I'm happy to have someone here give me a dope slap... I'm just tired of the headaches ;)
You should probably check with slapacl(8).
-Dieter
You should probably check with slapacl(8).
Thanks Dieter, this might prove to be helpful. Investigating with slapacl, I see some interesting behavior. Without the "val.exact=/bin/bash" requirement, the user is allowed write access and the relevant portions of the ACL trace looks like:
525edc6e => acl_mask: access to entry "uid=testmkd,ou=people,dc=cs,dc=brown,dc=edu", attr "loginShell" requested 525edc6e => acl_mask: to all values by "uid=testmkd,ou=people,dc=cs,dc=brown,dc=edu", (=0) 525edc6e <= check a_dn_pat: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525edc6e => acl_string_expand: pattern: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525edc6e => acl_string_expand: expanded: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525edc6e <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525edc6e <= check a_dn_pat: self 525edc6e <= check a_authz.sai_ssf: ACL 128 > OP 128 525edc6e <= acl_mask: [3] applying write(=wrscxd) (stop) 525edc6e <= acl_mask: [3] mask: write(=wrscxd) 525edc6e => slap_access_allowed: write access granted by write(=wrscxd) 525edc6e => access_allowed: write access granted by write(=wrscxd) write access to loginShell: ALLOWED
and with the "val.exact=/bin/bash" requirement, it looks like:
525ed68a => acl_mask: access to entry "uid=user,ou=people,dc=cs,dc=brown,dc=edu", attr "loginShell" requested 525ed68a => acl_mask: to all values by "uid=user,ou=people,dc=cs,dc=brown,dc=edu", (=0) 525ed68a <= check a_dn_pat: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525ed68a => acl_string_expand: pattern: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525ed68a => acl_string_expand: expanded: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525ed68a <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525ed68a <= check a_dn_pat: uid=.*,ou=people,dc=cs,dc=brown,dc=edu,cn=gssapi,cn=auth 525ed68a <= check a_dn_pat: * 525ed68a <= acl_mask: [4] applying read(=rscxd) (stop) 525ed68a <= acl_mask: [4] mask: read(=rscxd) 525ed68a => slap_access_allowed: write access denied by read(=rscxd) 525ed68a => access_allowed: no more rules write access to loginShell: DENIED
Note the difference in the line following "cn=replica,dc=cs..." Again, the entire ACL stanza in question is:
access to dn.subtree="ou=people,dc=cs,dc=brown,dc=edu" attrs=loginShell val.exact="/bin/bash" by ssf=128 dn.regex="uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth" write by ssf=128 dn="cn=replica,dc=cs,dc=brown,dc=edu" write by ssf=128 self write by * read
I'm at a loss as to why adding the "val.exact=/bin/bash" requirement changes the acl trace from doing:
525edc6e <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525edc6e <= check a_dn_pat: self
to
525ed68a <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525ed68a <= check a_dn_pat: uid=.*,ou=people,dc=cs,dc=brown,dc=edu,cn=gssapi,cn=auth
with the val.exact statement, it doesn't even seem to evaluate the "self" permissions. Am I missing something fundamental here?
Thanks!
Mark
On 10/16/2013 08:38 PM, Mark Dieterich wrote:
You should probably check with slapacl(8).
Thanks Dieter, this might prove to be helpful. Investigating with slapacl, I see some interesting behavior. Without the "val.exact=/bin/bash" requirement, the user is allowed write access and the relevant portions of the ACL trace looks like:
525edc6e => acl_mask: access to entry "uid=testmkd,ou=people,dc=cs,dc=brown,dc=edu", attr "loginShell" requested 525edc6e => acl_mask: to all values by "uid=testmkd,ou=people,dc=cs,dc=brown,dc=edu", (=0) 525edc6e <= check a_dn_pat: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525edc6e => acl_string_expand: pattern: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525edc6e => acl_string_expand: expanded: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525edc6e <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525edc6e <= check a_dn_pat: self 525edc6e <= check a_authz.sai_ssf: ACL 128 > OP 128 525edc6e <= acl_mask: [3] applying write(=wrscxd) (stop) 525edc6e <= acl_mask: [3] mask: write(=wrscxd) 525edc6e => slap_access_allowed: write access granted by write(=wrscxd) 525edc6e => access_allowed: write access granted by write(=wrscxd) write access to loginShell: ALLOWED
and with the "val.exact=/bin/bash" requirement, it looks like:
525ed68a => acl_mask: access to entry "uid=user,ou=people,dc=cs,dc=brown,dc=edu", attr "loginShell" requested 525ed68a => acl_mask: to all values by "uid=user,ou=people,dc=cs,dc=brown,dc=edu", (=0) 525ed68a <= check a_dn_pat: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525ed68a => acl_string_expand: pattern: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525ed68a => acl_string_expand: expanded: uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth 525ed68a <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525ed68a <= check a_dn_pat: uid=.*,ou=people,dc=cs,dc=brown,dc=edu,cn=gssapi,cn=auth 525ed68a <= check a_dn_pat: * 525ed68a <= acl_mask: [4] applying read(=rscxd) (stop) 525ed68a <= acl_mask: [4] mask: read(=rscxd) 525ed68a => slap_access_allowed: write access denied by read(=rscxd) 525ed68a => access_allowed: no more rules write access to loginShell: DENIED
Note the difference in the line following "cn=replica,dc=cs..." Again, the entire ACL stanza in question is:
access to dn.subtree="ou=people,dc=cs,dc=brown,dc=edu" attrs=loginShell val.exact="/bin/bash" by ssf=128 dn.regex="uid=.*/admin,cn=cs.brown.edu,cn=GSSAPI,cn=auth" write by ssf=128 dn="cn=replica,dc=cs,dc=brown,dc=edu" write by ssf=128 self write by * read
I'm at a loss as to why adding the "val.exact=/bin/bash" requirement changes the acl trace from doing:
525edc6e <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525edc6e <= check a_dn_pat: self
to
525ed68a <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525ed68a <= check a_dn_pat: uid=.*,ou=people,dc=cs,dc=brown,dc=edu,cn=gssapi,cn=auth
with the val.exact statement, it doesn't even seem to evaluate the "self" permissions. Am I missing something fundamental here?
When modifying a value with a "replace" modify, first access is checked without values, to make sure one has the right to delete whatever value is present. With the ACL you configured there is no such privilege. You need to split your operation in two: first delete the specific value you want to delete, then add a new value. Both need to comply with the pattern specified in your ACL. For example, if you configure
access to attrs=homeDirectory val.regex="^/bin/[^f][^s][^h]" by self write
then you need to perform
dn: uid=user,ou=people,dc=cs,dc=brown,dc=edu changetype: modify delete: homeDirectory homeDirectory: /bin/bash - add: homeDirectory homeDirectory: /bin/csh
p.
I'm at a loss as to why adding the "val.exact=/bin/bash" requirement changes the acl trace from doing:
525edc6e <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525edc6e <= check a_dn_pat: self
to
525ed68a <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525ed68a <= check a_dn_pat: uid=.*,ou=people,dc=cs,dc=brown,dc=edu,cn=gssapi,cn=auth
with the val.exact statement, it doesn't even seem to evaluate the "self" permissions. Am I missing something fundamental here?
When modifying a value with a "replace" modify, first access is checked without values, to make sure one has the right to delete whatever value is present. With the ACL you configured there is no such privilege. You need to split your operation in two: first delete the specific value you want to delete, then add a new value. Both need to comply with the pattern specified in your ACL.
If I read this correctly, what you are saying is any val.<type>=<test> is completely ignored during the first check of a "replace" modify? This seams like slapd is changing the semantics of my intended ACL. If I truly don't want a user to be able to modify/delete a record unless it matches a given set of values, then what's stopping them from working around any ACL restriction I put in place with the explicit delete & add procedure you outlined? As an aside, I went ahead and tested the explicit delete and add procedure, it failed as well.
I was using slapacl for my tests and I'm not sure how it knows whether the intended procedure is a delete, add, or modify. All I was telling it to test for was whether it could write a particular attribute.
Thanks,
Mark
On 10/18/2013 02:53 PM, Mark Dieterich wrote:
I'm at a loss as to why adding the "val.exact=/bin/bash" requirement changes the acl trace from doing:
525edc6e <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525edc6e <= check a_dn_pat: self
to
525ed68a <= check a_dn_pat: cn=replica,dc=cs,dc=brown,dc=edu 525ed68a <= check a_dn_pat: uid=.*,ou=people,dc=cs,dc=brown,dc=edu,cn=gssapi,cn=auth
with the val.exact statement, it doesn't even seem to evaluate the "self" permissions. Am I missing something fundamental here?
When modifying a value with a "replace" modify, first access is checked without values, to make sure one has the right to delete whatever value is present. With the ACL you configured there is no such privilege. You need to split your operation in two: first delete the specific value you want to delete, then add a new value. Both need to comply with the pattern specified in your ACL.
If I read this correctly, what you are saying is any val.<type>=<test> is completely ignored during the first check of a "replace" modify? This seams like slapd is changing the semantics of my intended ACL. If I truly don't want a user to be able to modify/delete a record unless it matches a given set of values, then what's stopping them from working around any ACL restriction I put in place with the explicit delete & add procedure you outlined? As an aside, I went ahead and tested the explicit delete and add procedure, it failed as well.
I was using slapacl for my tests and I'm not sure how it knows whether the intended procedure is a delete, add, or modify. All I was telling it to test for was whether it could write a particular attribute.
Just for the records, I set
access to attrs=description val.regex="^/bin/[^f][^s][^h]" by users write by * read
access to * by * read
(I didn't feel like populating the database with homeDirectory and so), and it worked: users were able to add/delete "/bin/bash", but not "/bin/fsh".
Glad you found a workaround, though.
p.
Thanks,
Mark
access to attrs=description val.regex="^/bin/[^f][^s][^h]" by users write by * read
Thanks for the followup, I'll have to play around some more.
(I didn't feel like populating the database with homeDirectory and so), and it worked: users were able to add/delete "/bin/bash", but not "/bin/fsh".
I think what I wanted was subtly different than this though. I need for users who have an existing value of "/bin/fsh" to be prevented from deleting or modifying their entry. The crux of my issue here appears to be that I didn't understand that the val.<type>=<value> constraint is only evaluated on the add portion of an operation, i.e. as a way of controlling possible values you can input. Instead, I thought it was part of the query operation, i.e. this is an ACL applying to a certain attribute under the condition where a certain regular expression applies to the value of the attribute.
The sets notation gave me what I needed.
Thanks!
Mark
Why don't you use filter=(shell=/bin/fsh) then? Maybe I did not get you right.
Doh! Because I was clearly trying to make the problem too hard. This works great as well... wish I had been better at explaining what I was after in the first place. Well, I learned a lot about sets in the process.
Thanks!
Mark
I never figured out how to get any of the val.<type>=<value> restrictions to meet my needs, so I resorted to using sets to accomplish what I wanted. In case anyone else is every trying to do something similar, here is what I ended up with for an ACL statement:
access to dn.regex="uid=.*,ou=people,dc=cs,dc=brown,dc=edu" attrs=loginShell by ssf=128 set="(this & user)/loginShell & ([/bin/csh] | [/bin/sh] | ...) write
By doing this, I ensure the user is editing their own entry and that the current value of the loginShell variable is amongst the list of shells I permit people to change away from. I also have an explicit constraint on loginShell:
constraint_attribute loginShell regex ^(/bin/csh|/bin/sh|...)
earlier in the configuration, which limits what users can set their shell to.
Hope this saves some people from the week or so of ACL fun I've been enjoying ;)
Thanks to everyone who posted suggestions!
Mark
On 2013-10-11 22:35, Mark Dieterich wrote:
[...] val.regex="/bin/[^f][^s][^h]"
It's Monday morning, and I haven't had a second coffee yet, but: I'm not exactly sure that this regex is working the way you expect it to work.
It will match "/bin/bash" (that's ok), it will NOT match "/bin/fsh" (also ok), but it will also NOT match "/bin/ash" or "/bin/foo".
hth, off to get some coffee,
[...] val.regex="/bin/[^f][^s][^h]"
It will match "/bin/bash" (that's ok), it will NOT match "/bin/fsh" (also ok), but it will also NOT match "/bin/ash" or "/bin/foo".
Good point. Fortunately for us, I think this pattern works for all shells currently used in our environment. I tried a negative lookahead, which is what I really want, but slapd complained about the syntax.
Mark
openldap-technical@openldap.org