diff options
-rw-r--r-- | conf/kolab.conf | 189 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | kolabd/__init__.py | 7 | ||||
-rw-r--r-- | pykolab/setup/components.py | 45 | ||||
-rw-r--r-- | pykolab/setup/setup_ldap.py | 106 |
5 files changed, 227 insertions, 122 deletions
diff --git a/conf/kolab.conf b/conf/kolab.conf index 3611bd8..2a7888c 100644 --- a/conf/kolab.conf +++ b/conf/kolab.conf @@ -1,5 +1,5 @@ [kolab] -primary_domain = example.org +primary_domain = kolabsys.com auth_mechanism = ldap imap_backend = cyrus-imap default_quota = 2097152 @@ -12,25 +12,22 @@ auth_attributes = mail, alias, uid [ldap] ldap_uri = ldap://localhost -base_dn = dc=example,dc=org - +base_dn = dc=kolabsys,dc=com user_base_dn = ou=People,%(base_dn)s user_filter = (objectclass=inetorgperson) user_scope = sub - kolab_user_filter = (objectclass=kolabinetorgperson) - group_base_dn = ou=Groups,%(base_dn)s group_filter = (|(objectclass=groupofuniquenames)(objectclass=groupofurls)) kolab_group_filter = (|(objectclass=kolabgroupofuniquenames)(objectclass=kolabgroupofurls)) - bind_dn = cn=Directory Manager -bind_pw = VerySecret - +bind_pw = 55WX2YOgYmt8EO5 domain_base_dn = cn=kolab,cn=config domain_filter = (&(associatedDomain=*)) domain_name_attribute = associateddomain domain_rootdn_attribute = inetdomainbasedn +service_bind_dn = uid=kolab-service,ou=Special Users,dc=kolabsys,dc=com +service_bind_pw = hAIOAhP8qIUEPbB [kolab_smtp_access_policy] uri = mysql://user:pass@localhost/kolab @@ -43,14 +40,13 @@ retention = 30 [kolab_wap] sql_uri = mysql://user:pass@localhost/kolab -;api_url = http://localhost/kolab-webadmin/api skin = default admin_auto_fields_rw = false [cyrus-imap] uri = imaps://localhost:993 admin_login = cyrus-admin -admin_password = VerySecret +admin_password = 5xosOaTm_Kg8Ax5 [cyrus-sasl] result_attribute = mail @@ -59,90 +55,91 @@ result_attribute = mail default_quota = 1048576 primary_mail = %(givenname)s.%(surname)s@%(domain)s secondary_mail = { - 0: { - "{0}.{1}@{2}": "format('%(givenname)s'[0:1].capitalize(), '%(surname)s', '%(domain)s')" - }, - 1: { - "{0}@{1}": "format('%(uid)s', '%(domain)s')" - }, - 2: { - "{0}@{1}": "format('%(givenname)s.%(surname)s', '%(domain)s')" - } - } + 0: { + "{0}.{1}@{2}": "format('%(givenname)s'[0:1].capitalize(), '%(surname)s', '%(domain)s')" + }, + 1: { + "{0}@{1}": "format('%(uid)s', '%(domain)s')" + }, + 2: { + "{0}@{1}": "format('%(givenname)s.%(surname)s', '%(domain)s')" + } + } autocreate_folders = { - 'Archive': { - 'quota': 0 - }, - 'Calendar': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "event.default", - }, - }, - 'Calendar/Personal Calendar': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "event", - }, - }, - 'Configuration': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "configuration.default", - }, - }, - 'Drafts': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "mail.drafts", - }, - }, - 'Contacts': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "contact.default", - }, - }, - 'Contacts/Personal Contacts': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "contact", - }, - }, - 'Journal': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "journal.default", - }, - }, - 'Notes': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': 'note.default', - }, - }, - 'Sent': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "mail.sentitems", - }, - }, - 'Spam': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "mail.junkemail", - }, - }, - 'Tasks': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "task.default", - }, - }, - 'Trash': { - 'annotations': { - '/vendor/kolab/folder-test': "true", - '/vendor/kolab/folder-type': "mail.trash", - }, - }, - } + 'Archive': { + 'quota': 0 + }, + 'Calendar': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "event.default", + }, + }, + 'Calendar/Personal Calendar': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "event", + }, + }, + 'Configuration': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "configuration.default", + }, + }, + 'Drafts': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "mail.drafts", + }, + }, + 'Contacts': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "contact.default", + }, + }, + 'Contacts/Personal Contacts': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "contact", + }, + }, + 'Journal': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "journal.default", + }, + }, + 'Notes': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': 'note.default', + }, + }, + 'Sent': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "mail.sentitems", + }, + }, + 'Spam': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "mail.junkemail", + }, + }, + 'Tasks': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "task.default", + }, + }, + 'Trash': { + 'annotations': { + '/vendor/kolab/folder-test': "true", + '/vendor/kolab/folder-type': "mail.trash", + }, + }, + } + diff --git a/configure.ac b/configure.ac index 5806d67..2a0817b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_INIT([pykolab], 0.3) -AC_SUBST([RELEASE], 0.23) +AC_SUBST([RELEASE], 0.24) AC_CONFIG_SRCDIR(pykolab/constants.py.in) diff --git a/kolabd/__init__.py b/kolabd/__init__.py index 8d25b91..ec05238 100644 --- a/kolabd/__init__.py +++ b/kolabd/__init__.py @@ -119,7 +119,12 @@ class KolabDaemon(object): log.debug(_("Listing domains..."), level=5) start = time.time() - domains = primary_auth.list_domains() + try: + domains = primary_auth.list_domains() + except: + time.sleep(60) + continue + if len(domains) == len(domain_auth.keys()): time.sleep(600) end = time.time() diff --git a/pykolab/setup/components.py b/pykolab/setup/components.py index bef460e..5e22b73 100644 --- a/pykolab/setup/components.py +++ b/pykolab/setup/components.py @@ -31,6 +31,8 @@ conf = pykolab.getConf() components = {} component_groups = {} +executed_components = [] + def __init__(): # We only want the base path components_base_path = os.path.dirname(__file__) @@ -120,9 +122,36 @@ def execute(component_name, *args, **kw): level=8 ) - for component in _list_components(): - if not component == 'help': - execute(component) + while 1: + for component in _list_components(): + execute_this = True + + if component in executed_components: + print "component", component, "already executed, continuing" + execute_this = False + + if component == "help": + execute_this = False + + if execute_this: + if components[component].has_key('after'): + print "component", component, "has after key, let's see what it holds" + for _component in components[component]['after']: + if not _component in executed_components: + print "component", component, "is waiting for component", _component + execute_this = False + + if execute_this: + execute(component) + executed_components.append(component) + + executed_all = True + for component in _list_components(): + if not component in executed_components and not component == "help": + executed_all = False + + if executed_all: + break return @@ -177,7 +206,7 @@ def register_group(dirname, module): exec("from %s.%s import __init__ as %s_%s_register" % (module,module_name,module,component_name)) exec("%s_%s_register()" % (module,component_name)) -def register(component_name, func, group=None, description=None, aliases=[]): +def register(component_name, func, group=None, description=None, after=[], before=[], aliases=[]): if not group == None: component = "%s_%s" % (group,component_name) else: @@ -194,12 +223,16 @@ def register(component_name, func, group=None, description=None, aliases=[]): if group == None: components[component_name] = { 'function': func, - 'description': description + 'description': description, + 'after': after, + 'before': before, } else: components[group][component_name] = { 'function': func, - 'description': description + 'description': description, + 'after': after, + 'before': before, } components[component] = components[group][component_name] diff --git a/pykolab/setup/setup_ldap.py b/pykolab/setup/setup_ldap.py index bf1d47a..9619e1a 100644 --- a/pykolab/setup/setup_ldap.py +++ b/pykolab/setup/setup_ldap.py @@ -112,21 +112,26 @@ ServerAdminPwd = %(admin_pass)s (stdoutdata, stderrdata) = setup_389.communicate() - # Copy in kolab schema - # - shutil.copy( - '/usr/share/doc/kolab-schema-3.0/kolab2.ldif', - '/etc/dirsrv/slapd-%s/schema/99kolab2.ldif' % (_input['hostname']) - ) + # Find the kolab schema. It's installed as %doc in the kolab-schema package. + # TODO: Chown nobody, nobody, chmod 440 + schema_file = None + for root, directories, filenames in os.walk('/usr/share/doc/'): + for filename in filenames: + if filename == 'kolab2.ldif': + schema_file = os.path.join(root,filename) + + if not schema_file == None: + shutil.copy( + schema_file, + '/etc/dirsrv/slapd-%s/schema/99kolab2.ldif' % ( + _input['hostname'] + ) + ) + else: + log.warning(_("Could not find the Kolab schema file")) subprocess.call(['service', 'dirsrv@%s' % (_input['hostname']), 'restart']) - # Write out kolab configuration - conf.command_set('kolab', 'primary_domain', _input['domain']) - conf.command_set('ldap', 'base_dn', _input['rootdn']) - conf.command_set('ldap', 'bind_dn', 'cn=Directory Manager') - conf.command_set('ldap', 'bind_pw', _input['dirmgr_pass']) - _input['cyrus_admin_pass'] = utils.ask_question( _("Cyrus Administrator password"), default=utils.generate_password(), @@ -139,6 +144,14 @@ ServerAdminPwd = %(admin_pass)s password=True ) + # Write out kolab configuration + conf.command_set('kolab', 'primary_domain', _input['domain']) + conf.command_set('ldap', 'base_dn', _input['rootdn']) + conf.command_set('ldap', 'bind_dn', 'cn=Directory Manager') + conf.command_set('ldap', 'bind_pw', _input['dirmgr_pass']) + conf.command_set('ldap', 'service_bind_dn', 'uid=kolab-service,ou=Special Users,%s' % (_input['rootdn'])) + conf.command_set('ldap', 'service_bind_pw', _input['kolab_service_pass']) + # Insert service users auth = pykolab.auth auth.connect() @@ -181,11 +194,6 @@ ServerAdminPwd = %(admin_pass)s # Do the actual synchronous add-operation to the ldapserver auth._auth.ldap.add_s(dn, ldif) - #dn: cn=kolab,cn=config - #objectClass: top - #objectClass: extensibleObject - #cn: kolab - dn = 'cn=kolab,cn=config' # A dict to help build the "body" of the object @@ -206,5 +214,67 @@ ServerAdminPwd = %(admin_pass)s ) # TODO: Add the primary domain to cn=kolab,cn=config - # TODO: Make sure 'uid' is unique + dn = "associateddomain=%s,cn=kolab,cn=config" % (domainname) + attrs = {} + attrs['objectclass'] = ['top','domainrelatedobject'] + attrs['associateddomain'] = '%s' % (domainname) + + ldif = ldap.modlist.addModlist(attrs) + + auth._auth.ldap.add_s(dn, ldif) + + # TODO: Allow no anonymous binds + dn = "cn=config" + modlist = [] + modlist.append((ldap.MOD_REPLACE, "nsslapd-allow-anonymous-access", "off")) + auth._auth.ldap.modify_s(dn, modlist) + + # TODO: Ensure the uid attribute is unique + # TODO^2: Consider renaming the general "attribute uniqueness to "uid attribute uniqueness" + dn = "cn=attribute uniqueness,cn=plugins,cn=config" + modlist = [] + modlist.append((ldap.MOD_REPLACE, "nsslapd-pluginEnabled", "on")) + auth._auth.ldap.modify_s(dn, modlist) + # TODO: Enable referential integrity plugin + dn = "cn=referential integrity postoperation,cn=plugins,cn=config" + modlist = [] + modlist.append((ldap.MOD_REPLACE, "nsslapd-pluginEnabled", "on")) + auth._auth.ldap.modify_s(dn, modlist) + + # TODO: Enable account policy plugin + dn = "cn=Account Policy Plugin,cn=plugins,cn=config" + modlist = [] + modlist.append((ldap.MOD_REPLACE, "nsslapd-pluginEnabled", "on")) + modlist.append((ldap.MOD_ADD, "nsslapd-pluginarg0", "cn=config,cn=Account Policy Plugin,cn=plugins,cn=config")) + auth._auth.ldap.modify_s(dn, modlist) + + dn = "cn=config,cn=Account Policy Plugin,cn=plugins,cn=config" + modlist = [] + modlist.append((ldap.MOD_REPLACE, "alwaysrecordlogin", "yes")) + modlist.append((ldap.MOD_ADD, "stateattrname", "lastLoginTime")) + modlist.append((ldap.MOD_ADD, "altstateattrname", "createTimestamp")) + auth._auth.ldap.modify_s(dn, modlist) + + # TODO: Add kolab-admin role + dn = "cn=kolab-admin,%s" % (_input['rootdn']) + attrs = {} + attrs['description'] = "Kolab Administrator" + attrs['objectClass'] = ['top','ldapsubentry','nsroledefinition','nssimpleroledefinition','nsmanagedroledefinition'] + attrs['cn'] = "kolab-admin" + ldif = ldap.modlist.addModlist(attrs) + + auth._auth.ldap.add_s(dn, ldif) + + # TODO: User writeable attributes on root_dn + dn = _input['rootdn'] + aci = [] + aci.append('(targetattr = "homePhone || preferredDeliveryMethod || jpegPhoto || postalAddress || carLicense || userPassword || mobile || kolabAllowSMTPRecipient || displayName || kolabDelegate || description || labeledURI || homePostalAddress || postOfficeBox || registeredAddress || postalCode || photo || title || street || kolabInvitationPolicy || pager || o || l || initials || kolabAllowSMTPSender || telephoneNumber || preferredLanguage || facsimileTelephoneNumber") (version 3.0;acl "Enable self write for common attributes";allow (read,compare,search,write)(userdn = "ldap:///self");)') + aci.append('(targetattr = "*") (version 3.0;acl "Directory Administrators Group";allow (all)(groupdn = "ldap:///cn=Directory Administrators,%(rootdn)s" or roledn = "ldap:///cn=kolab-admin,%(rootdn)s");)' % (_input)) + aci.append('(targetattr="*")(version 3.0; acl "Configuration Administrators Group"; allow (all) groupdn="ldap:///cn=Configuration Administrators,ou=Groups,ou=TopologyManagement,o=NetscapeRoot";)') + aci.append('(targetattr="*")(version 3.0; acl "Configuration Administrator"; allow (all) userdn="ldap:///uid=admin,ou=Administrators,ou=TopologyManagement,o=NetscapeRoot";)') + aci.append('(targetattr = "*")(version 3.0; acl "SIE Group"; allow (all) groupdn = "ldap:///cn=slapd-%(hostname)s,cn=389 Directory Server,cn=Server Group,cn=%(fqdn)s,ou=%(domain)s,o=NetscapeRoot";)' %(_input)) + aci.append('(targetattr = "*") (version 3.0;acl "Search Access";allow (read,compare,search)(userdn = "ldap:///all");)') + modlist = [] + modlist.append((ldap.MOD_REPLACE, "aci", aci)) + auth._auth.ldap.modify_s(dn, modlist) |