mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-24 16:10:02 -06:00
Automatically update IPA LDAP on rpm upgrades
Re-enable ldapi code in ipa-ldap-updater and remove the searchbase restriction when run in --upgrade mode. This allows us to autobind giving root Directory Manager powers. This also: * corrects the ipa-ldap-updater man page * remove automatic --realm, --server, --domain options * handle upgrade errors properly * saves a copy of dse.ldif before we change it so it can be recovered * fixes an error discovered by pylint ticket 1087
This commit is contained in:
parent
ba5e0c4307
commit
ca5332951c
@ -279,7 +279,10 @@ if [ $1 = 1 ]; then
|
||||
/sbin/chkconfig --add ipa
|
||||
/sbin/chkconfig --add ipa_kpasswd
|
||||
fi
|
||||
/usr/sbin/ipa-upgradeconfig || :
|
||||
if [ $1 -gt 1 ] ; then
|
||||
/usr/sbin/ipa-upgradeconfig || :
|
||||
/usr/sbin/ipa-ldap-updater --upgrade >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%preun server
|
||||
if [ $1 = 0 ]; then
|
||||
@ -478,6 +481,9 @@ fi
|
||||
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/default.conf
|
||||
|
||||
%changelog
|
||||
* Thu Mar 17 2011 Rob Crittenden <rcritten@redhat.com> - 1.99-46
|
||||
- Automatically apply updates when the package is upgraded.
|
||||
|
||||
* Thu Feb 17 2011 Jakub Hrozek <jhrozek@redhat.com> - 1.99-45
|
||||
- Set minimum version of python-nss to 0.11 to make sure IPv6 support is in
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
# TODO
|
||||
# save undo files?
|
||||
|
||||
import os
|
||||
import sys
|
||||
try:
|
||||
from ipapython.config import IPAOptionParser
|
||||
@ -30,6 +31,7 @@ try:
|
||||
from ipaserver.install import installutils
|
||||
from ipaserver.install.ldapupdate import LDAPUpdate, BadSyntax, UPDATES_DIR
|
||||
from ipaserver.install.upgradeinstance import IPAUpgrade
|
||||
from ipapython import sysrestore
|
||||
import logging
|
||||
import krbV
|
||||
except ImportError:
|
||||
@ -57,12 +59,9 @@ def parse_options():
|
||||
parser.add_option("-u", '--upgrade', action="store_true", dest="upgrade",
|
||||
default=False, help="Upgrade an installed server in offline mode")
|
||||
|
||||
config.add_standard_options(parser)
|
||||
options, args = parser.parse_args()
|
||||
safe_options = parser.get_safe_opts(options)
|
||||
|
||||
config.init_config(options)
|
||||
|
||||
return safe_options, options, args
|
||||
|
||||
def get_dirman_password():
|
||||
@ -75,11 +74,19 @@ def get_dirman_password():
|
||||
|
||||
def main():
|
||||
loglevel = logging.INFO
|
||||
badsyntax = False
|
||||
|
||||
safe_options, options, args = parse_options()
|
||||
if options.debug:
|
||||
loglevel = logging.DEBUG
|
||||
|
||||
if os.getegid() == 0:
|
||||
fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
|
||||
if not fstore.has_files():
|
||||
sys.exit("IPA is not configured on this system.")
|
||||
elif not os.path.exists('/etc/ipa/default.conf'):
|
||||
sys.exit("IPA is not configured on this system.")
|
||||
|
||||
dirman_password = ""
|
||||
if options.password:
|
||||
pw = ipautil.template_file(options.password, [])
|
||||
@ -93,6 +100,8 @@ def main():
|
||||
files = args
|
||||
|
||||
if options.upgrade:
|
||||
if os.getegid() != 0:
|
||||
sys.exit('Upgrade can only be done as root')
|
||||
logging.basicConfig(level=loglevel,
|
||||
format='%(levelname)s %(message)s',
|
||||
filename='/var/log/ipaupgrade.log')
|
||||
@ -101,7 +110,15 @@ def main():
|
||||
upgrade = IPAUpgrade(realm, files, live_run=not options.test)
|
||||
upgrade.create_instance()
|
||||
modified = upgrade.modified
|
||||
badsyntax = upgrade.badsyntax
|
||||
else:
|
||||
if os.getegid() == 0 and options.ldapi:
|
||||
sys.exit('ldapi cannot be used by root')
|
||||
# Clear all existing log handlers, this is need to log as root
|
||||
loggers = logging.getLogger()
|
||||
if loggers.handlers:
|
||||
for handler in loggers.handlers:
|
||||
loggers.removeHandler(handler)
|
||||
logging.basicConfig(level=loglevel,
|
||||
format='%(levelname)s %(message)s')
|
||||
ld = LDAPUpdate(dm_password=dirman_password, sub_dict={}, live_run=not options.test, ldapi=options.ldapi)
|
||||
@ -109,7 +126,9 @@ def main():
|
||||
files = ld.get_all_files(UPDATES_DIR)
|
||||
modified = ld.update(files)
|
||||
|
||||
if modified and options.test:
|
||||
if badsyntax:
|
||||
return 1
|
||||
elif modified and options.test:
|
||||
return 2
|
||||
else:
|
||||
return 0
|
||||
@ -128,7 +147,3 @@ except SystemExit, e:
|
||||
sys.exit(e)
|
||||
except KeyboardInterrupt, e:
|
||||
sys.exit(1)
|
||||
except config.IPAConfigError, e:
|
||||
print "An IPA server to update cannot be found. Has one been configured yet?"
|
||||
print "The error was: %s" % e
|
||||
sys.exit(1)
|
||||
|
@ -1,21 +1,21 @@
|
||||
.\" A man page for ipa-ldap-updater
|
||||
.\" Copyright (C) 2008 Red Hat, Inc.
|
||||
.\"
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the GNU General Public License as published by
|
||||
.\" the Free Software Foundation, either version 3 of the License, or
|
||||
.\" (at your option) any later version.
|
||||
.\"
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it will be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
.\" General Public License for more details.
|
||||
.\"
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License
|
||||
.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.\"
|
||||
.\" Author: Rob Crittenden <rcritten@redhat.com>
|
||||
.\"
|
||||
.\"
|
||||
.TH "ipa-ldap-updater" "1" "Sep 12 2008" "freeipa" ""
|
||||
.SH "NAME"
|
||||
ipa\-ldap\-updater \- Update the IPA LDAP configuration
|
||||
@ -34,7 +34,9 @@ There are 4 keywords:
|
||||
* default: the starting value
|
||||
* add: add a value (or values) to an attribute
|
||||
* remove: remove a value (or values) from an attribute
|
||||
* only: set an attribute to this
|
||||
* only: set an attribute to this
|
||||
* deleteentry: remove the entry
|
||||
* replace: replace an existing value, format is old: new
|
||||
|
||||
Values is a comma\-separated field so multi\-values may be added at one time. Double or single quotes may be put around individual values that contain embedded commas.
|
||||
|
||||
@ -48,8 +50,9 @@ The available template variables are:
|
||||
* $FQDN \- the fully\-qualified domain name of the IPA server being updated (ipa.example.com)
|
||||
* $DOMAIN \- the domain name (example.com)
|
||||
* $SUFFIX \- the IPA LDAP suffix (dc=example,dc=com)
|
||||
* $ESCAPED_SUFFIX \- the ldap-escaped IPA LDAP suffix
|
||||
* $LIBARCH \- set to 64 on x86_64 systems to be used for plugin paths
|
||||
* $TIME \- an integer representation of current time
|
||||
* $TIME \- an integer representation of current time
|
||||
|
||||
A few rules:
|
||||
|
||||
@ -59,17 +62,23 @@ A few rules:
|
||||
4. removing a value that doesn't exist is ok. It is simply ignored.
|
||||
5. If a DN doesn't exist it is created from the 'default' entry and all updates are applied
|
||||
6. If a DN does exist the default values are skipped
|
||||
7. Only the first rule on a line is respected
|
||||
7. Only the first rule on a line is respected
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
.TP
|
||||
\fB\-d\fR, \fB\-\-debug
|
||||
Enable debug logging when more verbose output is needed
|
||||
.TP
|
||||
.TP
|
||||
\fB\-t\fR, \fB\-\-test\fR
|
||||
Run through the update without changing anything. If changes are available then the command returns 2. If no updates are available it returns 0.
|
||||
.TP
|
||||
.TP
|
||||
\fB\-y\fR
|
||||
File containing the Directory Manager password
|
||||
.TP
|
||||
\fB\-l\fR, \fB\-\-ldapi\fR
|
||||
Connect to the LDAP server using the ldapi socket
|
||||
.TP
|
||||
\fB\-u\fR, \fB\-\-\-upgrade\fR
|
||||
Upgrade an installed server in offline mode (implies \-\-ldapi)
|
||||
.SH "EXIT STATUS"
|
||||
0 if the command was successful
|
||||
|
||||
|
@ -109,7 +109,7 @@ class LDAPUpdate:
|
||||
|
||||
if online:
|
||||
# Try out the password
|
||||
#if not self.ldapi:
|
||||
if not self.ldapi:
|
||||
try:
|
||||
conn = ipaldap.IPAdmin(fqdn, ldapi=True, realm=self.realm)
|
||||
conn.do_simple_bind(binddn="cn=directory manager", bindpw=self.dm_password)
|
||||
@ -120,13 +120,16 @@ class LDAPUpdate:
|
||||
raise RuntimeError("Unable to connect to LDAP server %s" % fqdn)
|
||||
except ldap.INVALID_CREDENTIALS:
|
||||
raise RuntimeError("The password provided is incorrect for LDAP server %s" % fqdn)
|
||||
# THIS IS COMMENTED OUT, BECAUSE:
|
||||
# external_bind does work, but even as root, you don't always have
|
||||
# enought power to do everything we need due to strict ACI rules
|
||||
#
|
||||
#else:
|
||||
# conn = ipaldap.IPAdmin(ldapi=True, realm=self.realm)
|
||||
# conn.do_external_bind(self.pw_name)
|
||||
else:
|
||||
conn = ipaldap.IPAdmin(ldapi=True, realm=self.realm)
|
||||
try:
|
||||
if os.getegid() == 0:
|
||||
# autobind
|
||||
conn.do_external_bind(self.pw_name)
|
||||
else:
|
||||
conn.do_sasl_gssapi_bind()
|
||||
except ldap.LOCAL_ERROR, e:
|
||||
raise RuntimeError('%s' % e.args[0].get('info', '').strip())
|
||||
else:
|
||||
raise RuntimeError("Offline updates are not supported.")
|
||||
|
||||
@ -476,7 +479,7 @@ class LDAPUpdate:
|
||||
try:
|
||||
(old, new) = v.split(':', 1)
|
||||
except ValueError:
|
||||
raise BadSyntax, "bad syntax in replace, needs to be in the format old: new in %s" % new_entry.dn
|
||||
raise BadSyntax, "bad syntax in replace, needs to be in the format old: new in %s" % v
|
||||
try:
|
||||
e.remove(old)
|
||||
e.append(new)
|
||||
@ -596,6 +599,9 @@ class LDAPUpdate:
|
||||
except errors.DatabaseError, e:
|
||||
logging.error("Update failed: %s", e)
|
||||
updated = False
|
||||
except errors.ACIError, e:
|
||||
logging.error("Update failed: %s", e)
|
||||
updated = False
|
||||
|
||||
if ("cn=index" in entry.dn and
|
||||
"cn=userRoot" in entry.dn):
|
||||
@ -654,14 +660,17 @@ class LDAPUpdate:
|
||||
|
||||
try:
|
||||
if self.online:
|
||||
# THIS IS COMMENTED OUT, BECAUSE:
|
||||
# external_bind does work, but even as root, you don't always have
|
||||
# enought power to do everything we need due to strict ACI rules
|
||||
#
|
||||
#if self.ldapi:
|
||||
# self.conn = ipaldap.IPAdmin(ldapi=True, realm=self.realm)
|
||||
# self.conn.do_external_bind(self.pw_name)
|
||||
#else:
|
||||
if self.ldapi:
|
||||
self.conn = ipaldap.IPAdmin(ldapi=True, realm=self.realm)
|
||||
try:
|
||||
if os.getegid() == 0:
|
||||
# autobind
|
||||
self.conn.do_external_bind(self.pw_name)
|
||||
else:
|
||||
self.conn.do_sasl_gssapi_bind()
|
||||
except ldap.LOCAL_ERROR, e:
|
||||
raise RuntimeError('%s' % e.args[0].get('info', '').strip())
|
||||
else:
|
||||
self.conn = ipaldap.IPAdmin(self.sub_dict['FQDN'],
|
||||
ldapi=self.ldapi,
|
||||
realm=self.realm)
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import random
|
||||
|
||||
from ipaserver.install import installutils
|
||||
from ipaserver.install import dsinstance
|
||||
@ -41,12 +43,19 @@ class IPAUpgrade(service.Service):
|
||||
live_run: boolean that defines if we are in test or live mode.
|
||||
"""
|
||||
|
||||
ext = ''
|
||||
rand = random.Random()
|
||||
for i in range(8):
|
||||
h = "%02x" % rand.randint(0,255)
|
||||
ext += h
|
||||
service.Service.__init__(self, "dirsrv")
|
||||
serverid = dsinstance.realm_to_serverid(realm_name)
|
||||
self.filename = '%s%s/%s' % (DSBASE, serverid, DSE)
|
||||
self.savefilename = '%s%s/%s.ipa.%s' % (DSBASE, serverid, DSE, ext)
|
||||
self.live_run = live_run
|
||||
self.files = files
|
||||
self.modified = False
|
||||
self.badsyntax = False
|
||||
|
||||
def create_instance(self):
|
||||
self.step("stopping directory server", self.stop)
|
||||
@ -61,21 +70,26 @@ class IPAUpgrade(service.Service):
|
||||
self.start_creation("Upgrading IPA:")
|
||||
|
||||
def __save_config(self):
|
||||
shutil.copy2(self.filename, self.savefilename)
|
||||
port = installutils.get_directive(self.filename, 'nsslapd-port',
|
||||
separator=':')
|
||||
security = installutils.get_directive(self.filename, 'nsslapd-security',
|
||||
separator=':')
|
||||
autobind = installutils.get_directive(self.filename,
|
||||
'nsslapd-ldapiautobind', separator=':')
|
||||
searchbase = installutils.get_directive(self.filename,
|
||||
'nsslapd-ldapientrysearchbase', separator=':')
|
||||
|
||||
self.backup_state('nsslapd-port', port)
|
||||
self.backup_state('nsslapd-security', security)
|
||||
self.backup_state('nsslapd-ldapiautobind', autobind)
|
||||
self.backup_state('nsslapd-ldapientrysearchbase', searchbase)
|
||||
|
||||
def __restore_config(self):
|
||||
port = self.restore_state('nsslapd-port')
|
||||
security = self.restore_state('nsslapd-security')
|
||||
autobind = self.restore_state('nsslapd-ldapiautobind')
|
||||
searchbase = self.restore_state('nsslapd-ldapientrysearchbase')
|
||||
|
||||
installutils.set_directive(self.filename, 'nsslapd-port',
|
||||
port, quotes=False, separator=':')
|
||||
@ -83,6 +97,9 @@ class IPAUpgrade(service.Service):
|
||||
security, quotes=False, separator=':')
|
||||
installutils.set_directive(self.filename, 'nsslapd-ldapiautobind',
|
||||
autobind, quotes=False, separator=':')
|
||||
installutils.set_directive(self.filename,
|
||||
'nsslapd-ldapientrysearchbase',
|
||||
searchbase, quotes=False, separator=':')
|
||||
|
||||
def __disable_listeners(self):
|
||||
installutils.set_directive(self.filename, 'nsslapd-port',
|
||||
@ -91,12 +108,18 @@ class IPAUpgrade(service.Service):
|
||||
'off', quotes=False, separator=':')
|
||||
installutils.set_directive(self.filename, 'nsslapd-ldapiautobind',
|
||||
'on', quotes=False, separator=':')
|
||||
installutils.set_directive(self.filename, 'nsslapd-ldapientrysearchbase',
|
||||
'', quotes=False, separator=':')
|
||||
|
||||
def __upgrade(self):
|
||||
ld = ldapupdate.LDAPUpdate(dm_password='', ldapi=True, live_run=self.live_run)
|
||||
if len(self.files) == 0:
|
||||
self.files = ld.get_all_files(ldapupdate.UPDATES_DIR)
|
||||
self.modified = ld.update(self.files)
|
||||
try:
|
||||
ld = ldapupdate.LDAPUpdate(dm_password='', ldapi=True, live_run=self.live_run)
|
||||
if len(self.files) == 0:
|
||||
self.files = ld.get_all_files(ldapupdate.UPDATES_DIR)
|
||||
self.modified = ld.update(self.files)
|
||||
except ldapupdate.BadSyntax:
|
||||
self.modified = False
|
||||
self.badsyntax = True
|
||||
|
||||
def main():
|
||||
if os.getegid() != 0:
|
||||
|
Loading…
Reference in New Issue
Block a user