Changeset View
Changeset View
Standalone View
Standalone View
pykolab/setup/setup_ldap.py
Show All 11 Lines | |||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | # GNU General Public License for more details. | ||||
# You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
# | # | ||||
from __future__ import print_function | |||||
import ldap | import ldap | ||||
import ldap.modlist | import ldap.modlist | ||||
import os | import os | ||||
import pwd | import pwd | ||||
import shutil | import shutil | ||||
import subprocess | import subprocess | ||||
import tempfile | import tempfile | ||||
import time | import time | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
def execute(*args, **kw): | def execute(*args, **kw): | ||||
ask_questions = True | ask_questions = True | ||||
if not conf.config_file == conf.defaults.config_file: | if not conf.config_file == conf.defaults.config_file: | ||||
ask_questions = False | ask_questions = False | ||||
if conf.without_ldap: | if conf.without_ldap: | ||||
print >> sys.stderr, _("Skipping setup of LDAP, as specified") | print(_("Skipping setup of LDAP, as specified"), file=sys.stderr) | ||||
return | return | ||||
_input = {} | _input = {} | ||||
if conf.with_openldap and not conf.with_ad: | if conf.with_openldap and not conf.with_ad: | ||||
conf.command_set('ldap', 'unique_attribute', 'entryuuid') | conf.command_set('ldap', 'unique_attribute', 'entryuuid') | ||||
Show All 11 Lines | elif conf.with_ad and not conf.with_openldap: | ||||
# TODO: These attributes need to be checked | # TODO: These attributes need to be checked | ||||
conf.command_set('ldap', 'mail_attributes', 'mail') | conf.command_set('ldap', 'mail_attributes', 'mail') | ||||
conf.command_set('ldap', 'mailserver_attributes', 'mailhost') | conf.command_set('ldap', 'mailserver_attributes', 'mailhost') | ||||
conf.command_set('ldap', 'quota_attribute', 'mailquota') | conf.command_set('ldap', 'quota_attribute', 'mailquota') | ||||
return | return | ||||
elif conf.with_ad and conf.with_openldap: | elif conf.with_ad and conf.with_openldap: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
You can not configure Kolab to run against OpenLDAP | You can not configure Kolab to run against OpenLDAP | ||||
and Active Directory simultaneously. | and Active Directory simultaneously. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
sys.exit(1) | sys.exit(1) | ||||
# Pre-execution checks | # Pre-execution checks | ||||
for path, directories, files in os.walk('/etc/dirsrv/'): | for path, directories, files in os.walk('/etc/dirsrv/'): | ||||
for direct in directories: | for direct in directories: | ||||
if direct.startswith('slapd-'): | if direct.startswith('slapd-'): | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
It seems 389 Directory Server has an existing | It seems 389 Directory Server has an existing | ||||
instance configured. This setup script does not | instance configured. This setup script does not | ||||
intend to destroy or overwrite your data. Please | intend to destroy or overwrite your data. Please | ||||
make sure /etc/dirsrv/ and /var/lib/dirsrv/ are | make sure /etc/dirsrv/ and /var/lib/dirsrv/ are | ||||
clean so that this setup does not have to worry. | clean so that this setup does not have to worry. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
sys.exit(1) | sys.exit(1) | ||||
_input = {} | _input = {} | ||||
if ask_questions: | if ask_questions: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Please supply a password for the LDAP administrator user | Please supply a password for the LDAP administrator user | ||||
'admin', used to login to the graphical console of 389 | 'admin', used to login to the graphical console of 389 | ||||
Directory server. | Directory server. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
_input['admin_pass'] = utils.ask_question( | _input['admin_pass'] = utils.ask_question( | ||||
_("Administrator password"), | _("Administrator password"), | ||||
default=utils.generate_password(), | default=utils.generate_password(), | ||||
password=True, | password=True, | ||||
confirm=True | confirm=True | ||||
) | ) | ||||
if conf.directory_manager_pwd is not None: | if conf.directory_manager_pwd is not None: | ||||
_input['dirmgr_pass'] = conf.directory_manager_pwd | _input['dirmgr_pass'] = conf.directory_manager_pwd | ||||
else: | else: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Please supply a password for the LDAP Directory Manager | Please supply a password for the LDAP Directory Manager | ||||
user, which is the administrator user you will be using | user, which is the administrator user you will be using | ||||
to at least initially log in to the Web Admin, and that | to at least initially log in to the Web Admin, and that | ||||
Kolab uses to perform administrative tasks. | Kolab uses to perform administrative tasks. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
_input['dirmgr_pass'] = utils.ask_question( | _input['dirmgr_pass'] = utils.ask_question( | ||||
_("Directory Manager password"), | _("Directory Manager password"), | ||||
default=utils.generate_password(), | default=utils.generate_password(), | ||||
password=True, | password=True, | ||||
confirm=True | confirm=True | ||||
) | ) | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Please choose the system user and group the service | Please choose the system user and group the service | ||||
should use to run under. These should be existing, | should use to run under. These should be existing, | ||||
unprivileged, local system POSIX accounts with no shell. | unprivileged, local system POSIX accounts with no shell. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
try: | try: | ||||
pw = pwd.getpwnam("dirsrv") | pw = pwd.getpwnam("dirsrv") | ||||
except: | except: | ||||
_input['userid'] = utils.ask_question(_("User"), default="nobody") | _input['userid'] = utils.ask_question(_("User"), default="nobody") | ||||
_input['group'] = utils.ask_question(_("Group"), default="nobody") | _input['group'] = utils.ask_question(_("Group"), default="nobody") | ||||
else: | else: | ||||
_input['userid'] = utils.ask_question(_("User"), default="dirsrv") | _input['userid'] = utils.ask_question(_("User"), default="dirsrv") | ||||
Show All 26 Lines | else: | ||||
_input['fqdn'] = fqdn | _input['fqdn'] = fqdn | ||||
_input['hostname'] = hostname.split('.')[0] | _input['hostname'] = hostname.split('.')[0] | ||||
_input['domain'] = domainname | _input['domain'] = domainname | ||||
_input['nodotdomain'] = _input['domain'].replace('.','_') | _input['nodotdomain'] = _input['domain'].replace('.','_') | ||||
_input['rootdn'] = utils.standard_root_dn(_input['domain']) | _input['rootdn'] = utils.standard_root_dn(_input['domain']) | ||||
if ask_questions: | if ask_questions: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
This setup procedure plans to set up Kolab Groupware for | This setup procedure plans to set up Kolab Groupware for | ||||
the following domain name space. This domain name is | the following domain name space. This domain name is | ||||
obtained from the reverse DNS entry on your network | obtained from the reverse DNS entry on your network | ||||
interface. Please confirm this is the appropriate domain | interface. Please confirm this is the appropriate domain | ||||
name space. | name space. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
answer = utils.ask_confirmation("%s" % (_input['domain'])) | answer = utils.ask_confirmation("%s" % (_input['domain'])) | ||||
if not answer: | if not answer: | ||||
positive_answer = False | positive_answer = False | ||||
while not positive_answer: | while not positive_answer: | ||||
_input['domain'] = utils.ask_question(_("Domain name to use")) | _input['domain'] = utils.ask_question(_("Domain name to use")) | ||||
if not _input['domain'] == None and not _input['domain'] == "": | if not _input['domain'] == None and not _input['domain'] == "": | ||||
positive_answer = True | positive_answer = True | ||||
else: | else: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Invalid input. Please try again. | Invalid input. Please try again. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
_input['nodotdomain'] = _input['domain'].replace('.','_') | _input['nodotdomain'] = _input['domain'].replace('.','_') | ||||
_input['rootdn'] = utils.standard_root_dn(_input['domain']) | _input['rootdn'] = utils.standard_root_dn(_input['domain']) | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
The standard root dn we composed for you follows. Please | The standard root dn we composed for you follows. Please | ||||
confirm this is the root dn you wish to use. | confirm this is the root dn you wish to use. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
answer = utils.ask_confirmation("%s" % (_input['rootdn'])) | answer = utils.ask_confirmation("%s" % (_input['rootdn'])) | ||||
if not answer: | if not answer: | ||||
positive_answer = False | positive_answer = False | ||||
while not positive_answer: | while not positive_answer: | ||||
_input['rootdn'] = utils.ask_question(_("Root DN to use")) | _input['rootdn'] = utils.ask_question(_("Root DN to use")) | ||||
if not _input['rootdn'] == None and not _input['rootdn'] == "": | if not _input['rootdn'] == None and not _input['rootdn'] == "": | ||||
positive_answer = True | positive_answer = True | ||||
else: | else: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Invalid input. Please try again. | Invalid input. Please try again. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
# TODO: Loudly complain if the fqdn does not resolve back to this system. | # TODO: Loudly complain if the fqdn does not resolve back to this system. | ||||
data = """ | data = """ | ||||
[General] | [General] | ||||
FullMachineName = %(fqdn)s | FullMachineName = %(fqdn)s | ||||
SuiteSpotUserID = %(userid)s | SuiteSpotUserID = %(userid)s | ||||
SuiteSpotGroup = %(group)s | SuiteSpotGroup = %(group)s | ||||
Show All 38 Lines | """ % (_input) | ||||
command = [ | command = [ | ||||
setup_ds_admin, | setup_ds_admin, | ||||
'--debug', | '--debug', | ||||
'--silent', | '--silent', | ||||
'--force', | '--force', | ||||
'--file=%s' % (filename) | '--file=%s' % (filename) | ||||
] | ] | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Setup is now going to set up the 389 Directory Server. This | Setup is now going to set up the 389 Directory Server. This | ||||
may take a little while (during which period there is no | may take a little while (during which period there is no | ||||
output and no progress indication). | output and no progress indication). | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
log.info(_("Setting up 389 Directory Server")) | log.info(_("Setting up 389 Directory Server")) | ||||
setup_389 = subprocess.Popen( | setup_389 = subprocess.Popen( | ||||
command, | command, | ||||
stdout=subprocess.PIPE, | stdout=subprocess.PIPE, | ||||
stderr=subprocess.PIPE | stderr=subprocess.PIPE | ||||
) | ) | ||||
(stdoutdata, stderrdata) = setup_389.communicate() | (stdoutdata, stderrdata) = setup_389.communicate() | ||||
if not setup_389.returncode == 0: | if not setup_389.returncode == 0: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
An error was detected in the setup procedure for 389 | An error was detected in the setup procedure for 389 | ||||
Directory Server. This setup will write out stderr and | Directory Server. This setup will write out stderr and | ||||
stdout to /var/log/kolab/setup.error.log and | stdout to /var/log/kolab/setup.error.log and | ||||
/var/log/kolab/setup.out.log respectively, before it | /var/log/kolab/setup.out.log respectively, before it | ||||
exits. | exits. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
fp = open('/var/log/kolab/setup.error.log', 'w') | fp = open('/var/log/kolab/setup.error.log', 'w') | ||||
fp.write(stderrdata) | fp.write(stderrdata) | ||||
fp.close() | fp.close() | ||||
fp = open('/var/log/kolab/setup.out.log', 'w') | fp = open('/var/log/kolab/setup.out.log', 'w') | ||||
fp.write(stdoutdata) | fp.write(stdoutdata) | ||||
fp.close() | fp.close() | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | elif os.path.isfile('/sbin/chkconfig'): | ||||
subprocess.call(['/sbin/chkconfig', 'dirsrv', 'on']) | subprocess.call(['/sbin/chkconfig', 'dirsrv', 'on']) | ||||
elif os.path.isfile('/usr/sbin/update-rc.d'): | elif os.path.isfile('/usr/sbin/update-rc.d'): | ||||
subprocess.call(['/usr/sbin/update-rc.d', 'dirsrv', 'defaults']) | subprocess.call(['/usr/sbin/update-rc.d', 'dirsrv', 'defaults']) | ||||
else: | else: | ||||
log.error(_("Could not configure to start on boot, the " + \ | log.error(_("Could not configure to start on boot, the " + \ | ||||
"directory server service.")) | "directory server service.")) | ||||
if ask_questions: | if ask_questions: | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Please supply a Cyrus Administrator password. This | Please supply a Cyrus Administrator password. This | ||||
password is used by Kolab to execute administrative | password is used by Kolab to execute administrative | ||||
tasks in Cyrus IMAP. You may also need the password | tasks in Cyrus IMAP. You may also need the password | ||||
yourself to troubleshoot Cyrus IMAP and/or perform | yourself to troubleshoot Cyrus IMAP and/or perform | ||||
other administrative tasks against Cyrus IMAP directly. | other administrative tasks against Cyrus IMAP directly. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
_input['cyrus_admin_pass'] = utils.ask_question( | _input['cyrus_admin_pass'] = utils.ask_question( | ||||
_("Cyrus Administrator password"), | _("Cyrus Administrator password"), | ||||
default=utils.generate_password(), | default=utils.generate_password(), | ||||
password=True, | password=True, | ||||
confirm=True | confirm=True | ||||
) | ) | ||||
print >> sys.stderr, utils.multiline_message( | print(utils.multiline_message( | ||||
_(""" | _(""" | ||||
Please supply a Kolab Service account password. This | Please supply a Kolab Service account password. This | ||||
account is used by various services such as Postfix, | account is used by various services such as Postfix, | ||||
and Roundcube, as anonymous binds to the LDAP server | and Roundcube, as anonymous binds to the LDAP server | ||||
will not be allowed. | will not be allowed. | ||||
""") | """) | ||||
) | ), file=sys.stderr) | ||||
_input['kolab_service_pass'] = utils.ask_question( | _input['kolab_service_pass'] = utils.ask_question( | ||||
_("Kolab Service password"), | _("Kolab Service password"), | ||||
default=utils.generate_password(), | default=utils.generate_password(), | ||||
password=True, | password=True, | ||||
confirm=True | confirm=True | ||||
) | ) | ||||
▲ Show 20 Lines • Show All 212 Lines • Show Last 20 Lines |