Add support for ldap:///self bind rules

This is added mainly so the self service rules can be updated without
resorting to ldapmodify.

ticket 80
This commit is contained in:
Rob Crittenden
2010-08-10 13:22:50 -04:00
parent 897b296a69
commit e225ad4341
2 changed files with 74 additions and 11 deletions

View File

@@ -56,6 +56,10 @@ EXAMPLES:
The show command will show the raw DS ACI.
IMPORTANT: When modifying the target attributes of an existing ACI you
must include all existing attributes as well. When doing an aci-mod the
targetattr REPLACES the current attributes, it does not add to them.
"""
from ipalib import api, crud, errors
@@ -98,7 +102,10 @@ aci_output = (
def _make_aci(current, aciname, kw):
# Do some quick and dirty validation
"""
Given a name and a set of keywords construct an ACI.
"""
# Do some quick and dirty validation.
t1 = 'type' in kw
t2 = 'filter' in kw
t3 = 'subtree' in kw
@@ -113,10 +120,11 @@ def _make_aci(current, aciname, kw):
group = 'group' in kw
taskgroup = 'taskgroup' in kw
if group + taskgroup > 1:
raise errors.ValidationError(name='target', error=_('group and taskgroup are mutually exclusive'))
elif group + taskgroup == 0:
raise errors.ValidationError(name='target', error=_('One of group or taskgroup is required'))
selfaci = 'selfaci' in kw and kw['selfaci'] == True
if group + taskgroup + selfaci > 1:
raise errors.ValidationError(name='target', error=_('group, taskgroup and self are mutually exclusive'))
elif group + taskgroup + selfaci == 0:
raise errors.ValidationError(name='target', error=_('One of group, taskgroup or self is required'))
# Grab the dn of the group we're granting access to. This group may be a
# taskgroup or a user group.
@@ -137,11 +145,14 @@ def _make_aci(current, aciname, kw):
except errors.NotFound:
raise errors.NotFound(reason=_("Group '%s' does not exist") % kw['group'])
dn = entry_attrs['dn']
a = ACI(current)
a.name = aciname
a.permissions = kw['permissions']
a.set_bindrule('groupdn = "ldap:///%s"' % dn)
if 'selfaci' in kw and kw['selfaci']:
a.set_bindrule('userdn = "ldap:///self"')
else:
dn = entry_attrs['dn']
a.set_bindrule('groupdn = "ldap:///%s"' % dn)
if 'attrs' in kw:
a.set_target_attr(kw['attrs'])
if 'memberof' in kw:
@@ -205,11 +216,14 @@ def _aci_to_kw(ldap, a):
groupdn = a.bindrule['expression']
groupdn = groupdn.replace('ldap:///','')
(dn, entry_attrs) = ldap.get_entry(groupdn, ['cn'])
if api.env.container_taskgroup in dn:
kw['taskgroup'] = entry_attrs['cn'][0]
if groupdn == 'self':
kw['selfaci'] = True
else:
kw['group'] = entry_attrs['cn'][0]
(dn, entry_attrs) = ldap.get_entry(groupdn, ['cn'])
if api.env.container_taskgroup in dn:
kw['taskgroup'] = entry_attrs['cn'][0]
else:
kw['group'] = entry_attrs['cn'][0]
return kw
@@ -299,6 +313,11 @@ class aci(Object):
label=_('Target group'),
doc=_('Group to apply ACI to'),
),
Flag('selfaci?',
cli_name='self',
label=_('Target your own entry (self)'),
doc=_('Apply ACI to your own entry (self)'),
),
)
api.register(aci)
@@ -413,11 +432,18 @@ class aci_mod(crud.Update):
# a series of keywords. Then we replace any keywords that have been
# updated and convert that back into an ACI and write it out.
newkw = _aci_to_kw(ldap, aci)
if 'selfaci' in newkw and newkw['selfaci'] == True:
# selfaci is set in aci_to_kw to True only if the target is self
kw['selfaci'] = True
for k in kw.keys():
newkw[k] = kw[k]
if 'aciname' in newkw:
del newkw['aciname']
# _make_aci is what is run in aci_add and validates the input.
# Do this before we delete the existing ACI.
newaci = _make_aci(None, aciname, newkw)
self.api.Command['aci_del'](aciname)
result = self.api.Command['aci_add'](aciname, **newkw)['result']

View File

@@ -29,11 +29,14 @@ from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
aci1=u'test1'
taskgroup = u'testtaskgroup'
aci2=u'selftest1'
class test_aci(Declarative):
cleanup_commands = [
('aci_del', [aci1], {}),
('aci_del', [aci2], {}),
]
tests = [
@@ -219,4 +222,38 @@ class test_aci(Declarative):
),
dict(
desc='Create %r' % aci2,
command=(
'aci_add', [aci2], dict(permissions=u'write', attrs=(u'givenName',u'sn',u'cn'), selfaci=True)
),
expected=dict(
value=aci2,
summary=u'Created ACI "%s"' % aci2,
result=u'(targetattr = "givenName || sn || cn")(version 3.0;acl "selftest1";allow (write) userdn = "ldap:///self";)'),
),
dict(
desc='Update attributes in %r' % aci2,
command=(
'aci_mod', [aci2], dict(attrs=(u'givenName',u'sn',u'cn',u'uidNumber'))
),
expected=dict(
value=aci2,
summary=u'Modified ACI "%s"' % aci2,
result=u'(targetattr = "givenName || sn || cn || uidNumber")(version 3.0;acl "selftest1";allow (write) userdn = "ldap:///self";)'
),
),
dict(
desc='Update self ACI with a taskgroup %r' % aci2,
command=(
'aci_mod', [aci2], dict(attrs=(u'givenName',u'sn',u'cn',u'uidNumber'), taskgroup=taskgroup)
),
expected=errors.ValidationError(name='target', error='group, taskgroup and self are mutually exclusive'),
),
]