summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2010-08-10 13:22:50 -0400
committerRob Crittenden <rcritten@redhat.com>2010-08-19 10:49:42 -0400
commite225ad4341b8f91b0aa3d4be3f93b9082716828e (patch)
treef6045e821219e68e9683df6b01f25c7d732f4758
parent897b296a694224f9d00a4bfcc80f818c858fbfb5 (diff)
downloadfreeipa-e225ad4341b8f91b0aa3d4be3f93b9082716828e.tar.gz
freeipa-e225ad4341b8f91b0aa3d4be3f93b9082716828e.tar.xz
freeipa-e225ad4341b8f91b0aa3d4be3f93b9082716828e.zip
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
-rw-r--r--ipalib/plugins/aci.py48
-rw-r--r--tests/test_xmlrpc/test_aci_plugin.py37
2 files changed, 74 insertions, 11 deletions
diff --git a/ipalib/plugins/aci.py b/ipalib/plugins/aci.py
index f64589833..b6b40e260 100644
--- a/ipalib/plugins/aci.py
+++ b/ipalib/plugins/aci.py
@@ -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']
diff --git a/tests/test_xmlrpc/test_aci_plugin.py b/tests/test_xmlrpc/test_aci_plugin.py
index ddf2ed63a..e05e53a5a 100644
--- a/tests/test_xmlrpc/test_aci_plugin.py
+++ b/tests/test_xmlrpc/test_aci_plugin.py
@@ -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'),
+ ),
+
+
]