Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F118314549
D732.1775753537.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
20 KB
Referenced Files
None
Subscribers
None
D732.1775753537.diff
View Options
diff --git a/.arclint b/.arclint
--- a/.arclint
+++ b/.arclint
@@ -19,11 +19,13 @@
"E131": "disabled",
"E201": "disabled",
"E202": "disabled",
+ "E221": "disabled",
"E225": "disabled",
"E231": "disabled",
"E251": "disabled",
"E261": "disabled",
"E265": "disabled",
+ "E266": "disabled",
"E302": "disabled",
"E303": "disabled",
"E402": "disabled",
diff --git a/pykolab/auth/__init__.py b/pykolab/auth/__init__.py
--- a/pykolab/auth/__init__.py
+++ b/pykolab/auth/__init__.py
@@ -49,7 +49,6 @@
Login is a simple list of username, password, service and,
optionally, the realm.
"""
-
if len(login) == 3:
# The realm has not been specified. See if we know whether or not
# to use virtual_domains, as this may be a cause for the realm not
@@ -58,12 +57,12 @@
# TODO: Insert debug statements
#if use_virtual_domains == "userid":
- #print "# Derive domain from login[0]"
+ # print "# Derive domain from login[0]"
#elif not use_virtual_domains:
- #print "# Explicitly do not user virtual domains??"
+ # print "# Explicitly do not user virtual domains??"
#else:
- ## Do use virtual domains, derive domain from login[0]
- #print "# Derive domain from login[0]"
+ # ## Do use virtual domains, derive domain from login[0]
+ # print "# Derive domain from login[0]"
if len(login[0].split('@')) > 1:
domain = login[0].split('@')[1]
@@ -86,7 +85,7 @@
back to the primary domain specified by the configuration.
"""
- log.debug(_("Called for domain %r") % (domain), level=8)
+ log.debug(_("Called for domain %r") % (domain), level=5)
if not self._auth == None:
return
@@ -99,14 +98,10 @@
section = 'kolab'
domain = conf.get('kolab', 'primary_domain')
else:
+ log.debug(_("Getting list of domains for %s ...") % (domain), level=5)
self.list_domains(domain)
section = domain
- log.debug(
- _("Using section %s and domain %s") % (section,domain),
- level=8
- )
-
if not self.domains == None and self.domains.has_key(domain):
section = self.domains[domain]
domain = self.domains[domain]
@@ -116,13 +111,6 @@
level=8
)
- log.debug(
- _("Connecting to Authentication backend for domain %s") % (
- domain
- ),
- level=8
- )
-
if not conf.has_section(section):
section = 'kolab'
@@ -142,21 +130,32 @@
level=8
)
+ _auth_mechanism = conf.get(section, 'auth_mechanism')
+
# Get the actual authentication and authorization backend.
- if conf.get(section, 'auth_mechanism') == 'ldap':
- log.debug(_("Starting LDAP..."), level=8)
+ if _auth_mechanism == 'ldap':
+ log.debug(_("Initializing LDAP..."), level=8)
from pykolab.auth import ldap
self._auth = ldap.LDAP(self.domain)
- elif conf.get(section, 'auth_mechanism') == 'sql':
+ elif _auth_mechanism == 'sql':
+ log.debug(_("Initializing SQL..."), level=8)
from pykolab.auth import sql
self._auth = sql.SQL(self.domain)
else:
- log.debug(_("Starting LDAP..."), level=8)
+ log.debug(_("Fallback to LDAP. Initializing ..."), level=5)
from pykolab.auth import ldap
self._auth = ldap.LDAP(self.domain)
+ log.debug(
+ _("Connecting to Authentication %s backend for domain %s") % (
+ _auth_mechanism,
+ domain
+ ),
+ level=5
+ )
+
self._auth.connect()
def disconnect(self, domain=None):
@@ -277,6 +276,8 @@
for secondary in secondaries:
self.domains[secondary.lower()] = primary.lower()
+ log.debug(_("List of domains for %s is: %s") % (domain, ", ".join(self.domains)), level=8)
+
return self.domains
def synchronize(self, mode=0, callback=None):
@@ -291,6 +292,9 @@
def primary_domain_for_naming_context(self, domain):
return self._auth._primary_domain_for_naming_context(domain)
+ def add_entry(self, domain, entry):
+ return self._auth._add_entry(entry)
+
def get_entry_attribute(self, domain, entry, attribute):
return self._auth.get_entry_attribute(entry, attribute)
diff --git a/pykolab/auth/ldap/__init__.py b/pykolab/auth/ldap/__init__.py
--- a/pykolab/auth/ldap/__init__.py
+++ b/pykolab/auth/ldap/__init__.py
@@ -1525,6 +1525,26 @@
log.debug(_("bind_priv() called but already bound"), level=8)
return True
+ def _add_entry(self, entry):
+ """
+ Add generic type of entry.
+
+ Initialy created for setup-kolab to be able to add AD schema
+ by parsing Kolab AD schema ldif file
+
+ entry - dictionary, same as search results
+ """
+ self._bind()
+
+ entry_dn, entry_attrs = entry
+
+ log.debug(_("Entry DN: %s, with attributes: %s") % (entry_dn, entry_attrs), level=8)
+
+ self.ldap.add_s(
+ entry_dn,
+ entry_attrs
+ )
+
def _change_add_group(self, entry, change):
"""
An entry of type group was added.
diff --git a/pykolab/setup/setup_ldap.py b/pykolab/setup/setup_ldap.py
--- a/pykolab/setup/setup_ldap.py
+++ b/pykolab/setup/setup_ldap.py
@@ -22,6 +22,7 @@
import os
import pwd
import shutil
+import socket
import subprocess
import tempfile
import time
@@ -35,6 +36,8 @@
from pykolab.constants import *
from pykolab.translate import _
+from Cheetah.Template import Template
+
log = pykolab.getLogger('pykolab.setup')
conf = pykolab.getConf()
@@ -95,9 +98,251 @@
def description():
return _("Setup LDAP.")
+def get_answers():
+
+ answers = {}
+
+ # Get cn=Directory Manger password
+ if conf.directory_manager_pwd is not None:
+ # password was set with command line options
+ answers['dirmgr_pass'] = conf.directory_manager_pwd
+ else:
+ # Ask for password
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Please supply a password for the LDAP Directory Manager
+ user, which is the administrator user you will be using
+ to at least initially log in to the Web Admin, and that
+ Kolab uses to perform administrative tasks.
+ """)
+ )
+
+ answers['dirmgr_pass'] = utils.ask_question(
+ _("Directory Manager password"),
+ default=utils.generate_password(),
+ password=True,
+ confirm=True
+ )
+
+ # Ask only if LDAP is DS
+ if not conf.with_openldap and not conf.with_ad:
+ # Get Dirsrv Admin server admin user pass
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Please supply a password for the LDAP administrator user
+ 'admin', used to login to the graphical console of 389
+ Directory server.
+ """)
+ )
+
+ answers['admin_pass'] = utils.ask_question(
+ _("Administrator password"),
+ default=utils.generate_password(),
+ password=True,
+ confirm=True
+ )
+
+
+ # Set users for DS LDAP
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Please choose the system user and group the service
+ should use to run under. These should be existing,
+ unprivileged, local system POSIX accounts with no shell.
+ """)
+ )
+
+ try:
+ pw = pwd.getpwnam("dirsrv")
+ except:
+ answers['userid'] = utils.ask_question(_("User"), default="nobody")
+ answers['group'] = utils.ask_question(_("Group"), default="nobody")
+ else:
+ answers['userid'] = utils.ask_question(_("User"), default="dirsrv")
+ answers['group'] = utils.ask_question(_("Group"), default="dirsrv")
+
+ elif conf.with_ad and not conf.with_openldap:
+ # Get answers for Active Directory setup
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Specify basic Active Directory connection information.
+ """)
+ )
+
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Please provide Active Directory server URI. Setup will use it to load
+ Kolab schema into AD and then will configure Kolab to run with AD as
+ LDAP server. Schema can be loaded to schema master server only wherefore
+ this needs to be URI specifying AD schema master. You can change AD server
+ URI later, in kolab.conf file.
+ """)
+ )
+
+ answers['ad_server'] = utils.ask_question(
+ _("AD server URI"),
+ default="ldap://adserver.domain:389"
+ )
+
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Enter primary domain name which you would like to use for your Kolab installation.
+ """)
+ )
+
+ answers['domain'] = utils.ask_question(
+ _("Domain name to use"),
+ default=socket.getfqdn().split('.', 1)[1]
+ )
+
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Provide Root DN of your Active Directory LDAP tree.
+ """)
+ )
+
+ answers['rootdn'] = utils.ask_question(
+ _("Specify Active Directory root DN"),
+ default=utils.standard_root_dn(answers['domain'])
+ )
+
+ answers['bind_dn'] = utils.ask_question(
+ _("AD Administrator bind DN"),
+ default="CN=Administrator,CN=Users,%s" % answers['rootdn']
+ )
+
+ return answers
+
+def ad_schema_import(*args, **kwargs):
+ import ldif
+ import time
+ from ldap import modlist
+ from ldap import dn
+ from StringIO import StringIO
+
+ conf.ldap_uri = kwargs['uri']
+ ad_domain = kwargs['domain']
+ ad_bind_dn = kwargs['binddn']
+ ad_bind_pw = kwargs['passwd']
+
+ # create LDAP connection
+ conn = Auth()
+ conn.connect()
+
+ ad_schema_naming_context = conn.get_entry_attribute(ad_domain, "", "schemaNamingContext")
+
+ log.debug("AD Schema Naming context is %s" % ad_schema_naming_context, level=8)
+
+ # Find out AD schema master server. Only this server has writable copy of
+ # AD schema. First need to get fsmoRoleOwner attribute value.
+ ad_fsmo_attribute = conn.get_entry_attribute(ad_domain, ad_schema_naming_context, "fSMORoleOwner")
+
+ log.debug(_("AD FSMO Role Owner entry is: %s") % ad_fsmo_attribute, level=8)
+
+ # Now get parent of fsmoRoleOwner
+ if ad_fsmo_attribute is not None:
+ ad_fsmo_dn = dn.explode_dn(ad_fsmo_attribute)
+ ad_fsmo_parent = ','.join(ad_fsmo_dn[1:])
+
+ log.debug(_("AD FSMO entry parent is: %s") % ad_fsmo_parent, level=8)
+
+ # Look for dNSHostName attribute of the parent
+ if ad_fsmo_parent is not None:
+ ad_schema_master = conn.get_entry_attribute(ad_domain, ad_fsmo_parent, "dNSHostName")
+ log.debug(_("AD schema master server is: %s") % ad_schema_master, level=8)
+
+ (
+ _ad_protocol,
+ _ad_server,
+ _ad_port,
+ _ad_base_dn,
+ _ad_attr,
+ _ad_scope,
+ _ad_filter
+ ) = utils.parse_ldap_uri(conf.ldap_uri)
+
+ if not _ad_server == ad_schema_master:
+ log.debug(_("AD schema master %s is not the same as %s.") % (ad_schema_master, _ad_server), level=5)
+ log.error(_("Cannot install Kolab schema on AD server which is not schema master"))
+ sys.exit(1)
+
+ template_file = None
+ if os.path.isfile('/etc/kolab/templates/kolab-ad-schema.tpl'):
+ template_file = '/etc/kolab/templates/kolab-ad-schema.tpl'
+ elif os.path.isfile('/usr/share/kolab/templates/kolab-ad-schema.tpl'):
+ template_file = '/usr/share/kolab/templates/kolab-ad-schema.tpl'
+ elif os.path.isfile(os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'kolab-ad-schema.tpl' ))):
+ template_file = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'kolab-ad-schema.tpl' ))
+
+ if not template_file == None:
+ log.debug(_("Using template file %r") % (template_file), level=8)
+ fp = open(template_file, 'r')
+ template_definition = fp.read()
+ fp.close()
+
+ schema_template = Template(template_definition, searchList={'AD_SCHEMA_NAMING_CONTEXT': ad_schema_naming_context})
+ log.debug(
+ _("Successfully compiled template %r, ready to add schema to AD server") % (template_file),
+ level=8
+ )
+
+ schema_ldif = StringIO(schema_template.__str__())
+
+ parser = ldif.LDIFRecordList(schema_ldif)
+ parser.parse()
+
+ # If silent install or install without asking questions
+ # when no need to ask confirmation
+ if kwargs['confirm']:
+
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ Setup is going to add Kolab schema elements to
+ Active Directory. This is ireversable operation.
+ """)
+ )
+
+ confirmed = utils.ask_confirmation(
+ _("Modify Active Directory schema?"),
+ default="n"
+ )
+
+ else:
+ # this is silent install
+ confirmed = True
+
+ if confirmed:
+ for dn, attributes in parser.all_records:
+ log.debug("Adding DN: %s" % dn, level=5)
+ try:
+ add_attributes = modlist.addModlist(attributes)
+ conn.add_entry(None, (dn, add_attributes))
+ except ldap.ALREADY_EXISTS:
+ log.warning(_("Schema element already exist: %s") % dn)
+ continue
+ except ldap.NO_SUCH_ATTRIBUTE:
+ log.warning(_("Could not add %s schema element. Force update and retry.") % dn)
+ try:
+ conn.set_entry_attribute(None, "", "schemaUpdateNow", "1")
+ time.sleep(2)
+ conn.add_entry(None, (dn, add_attributes))
+ except:
+ log.error(_("Failed to add %s Kolab schema element.") % dn)
+ sys.exit(1)
+ except Exception, errorMsg:
+ log.error(_("Could not add schema element: %s") % dn)
+ log.error(_("Error: %s") % errorMsg )
+ sys.exit(1)
+ else:
+ log.error(_("Kolab schema must be installed before you continue."))
+ sys.exit(1)
+
def execute(*args, **kw):
ask_questions = True
+ log.error("_________ %s ________" % conf.config_file)
+ log.error("_________ %s ________" % conf.defaults.config_file)
+
if not conf.config_file == conf.defaults.config_file:
ask_questions = False
@@ -108,7 +353,7 @@
_input = {}
if conf.with_openldap and not conf.with_ad:
-
+ conf.command_set('ldap', 'type', 'openldap')
conf.command_set('ldap', 'unique_attribute', 'entryuuid')
fp = open(conf.defaults.config_file, "w+")
@@ -118,14 +363,50 @@
return
elif conf.with_ad and not conf.with_openldap:
- conf.command_set('ldap', 'auth_attributes', 'samaccountname')
- conf.command_set('ldap', 'modifytimestamp_format', '%%Y%%m%%d%%H%%M%%S.0Z')
- conf.command_set('ldap', 'unique_attribute', 'userprincipalname')
+
+ if ask_questions:
+ _input = get_answers()
+ else:
+ if conf.fqdn is None:
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ FQDN not specified. Either use config file or
+ --fqdn option to specify domain to use.
+ """)
+ )
+ sys.exit(1)
+ else:
+ _input['domain'] = conf.fqdn
+ _input['rootdn'] = utils.standard_root_dn(_input['domain'])
+ _input['bind_dn'] = conf.get('ldap', 'bind_dn')
+ _input['dirmgr_pass'] = conf.get('ldap', 'bind_pw')
+ _input['ad_server'] = conf.get('ldap', 'ldap_uri')
+
+ conf.command_set('ldap', 'type', 'ad')
+ conf.command_set('ldap', 'auth_attributes', 'mail, kolabAlias, uid, samaccountname')
+ conf.command_set('ldap', 'modifytimestamp_format', '%Y%m%d%H%M%S.0Z')
+ conf.command_set('ldap', 'unique_attribute', 'objectguid')
# TODO: These attributes need to be checked
conf.command_set('ldap', 'mail_attributes', 'mail')
- conf.command_set('ldap', 'mailserver_attributes', 'mailhost')
- conf.command_set('ldap', 'quota_attribute', 'mailquota')
+ conf.command_set('ldap', 'mailserver_attributes', 'kolabMailhost')
+ conf.command_set('ldap', 'quota_attribute', 'kolabMailquota')
+
+ # TODO: These attributes need to be checked
+ conf.command_set('ldap', 'ldap_uri', _input['ad_server'])
+ conf.command_set('ldap', 'bind_dn', _input['bind_dn'])
+ conf.command_set('ldap', 'bind_pw', _input['dirmgr_pass'])
+ conf.command_set('ldap', 'service_bind_dn', _input['bind_dn'])
+ conf.command_set('ldap', 'service_bind_pw', _input['dirmgr_pass'])
+ conf.command_set('ldap', 'primary_domain', _input['domain'])
+
+ ad_schema_import(
+ domain=_input['domain'],
+ uri=_input['ad_server'],
+ binddn=_input['bind_dn'],
+ passwd=_input['dirmgr_pass'],
+ confirm=ask_questions
+ )
return
@@ -158,57 +439,7 @@
_input = {}
if ask_questions:
- print >> sys.stderr, utils.multiline_message(
- _("""
- Please supply a password for the LDAP administrator user
- 'admin', used to login to the graphical console of 389
- Directory server.
- """)
- )
-
- _input['admin_pass'] = utils.ask_question(
- _("Administrator password"),
- default=utils.generate_password(),
- password=True,
- confirm=True
- )
-
- if conf.directory_manager_pwd is not None:
- _input['dirmgr_pass'] = conf.directory_manager_pwd
- else:
- print >> sys.stderr, utils.multiline_message(
- _("""
- Please supply a password for the LDAP Directory Manager
- user, which is the administrator user you will be using
- to at least initially log in to the Web Admin, and that
- Kolab uses to perform administrative tasks.
- """)
- )
-
- _input['dirmgr_pass'] = utils.ask_question(
- _("Directory Manager password"),
- default=utils.generate_password(),
- password=True,
- confirm=True
- )
-
- print >> sys.stderr, utils.multiline_message(
- _("""
- Please choose the system user and group the service
- should use to run under. These should be existing,
- unprivileged, local system POSIX accounts with no shell.
- """)
- )
-
- try:
- pw = pwd.getpwnam("dirsrv")
- except:
- _input['userid'] = utils.ask_question(_("User"), default="nobody")
- _input['group'] = utils.ask_question(_("Group"), default="nobody")
- else:
- _input['userid'] = utils.ask_question(_("User"), default="dirsrv")
- _input['group'] = utils.ask_question(_("Group"), default="dirsrv")
-
+ _input = get_answers()
else:
_input['admin_pass'] = conf.get('ldap', 'bind_pw')
_input['dirmgr_pass'] = conf.get('ldap', 'bind_pw')
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 9, 4:52 PM (42 m, 51 s ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18852385
Default Alt Text
D732.1775753537.diff (20 KB)
Attached To
Mode
D732: This is first attempt to add a AD schema import / load to kolab setup tools. The idea is that when setup-kolab is run with --with-ad it should ask questions about where the AD server is and how to connect to it. Then it should compile a AD schema...
Attached
Detach File
Event Timeline