Imported Upstream version 4.0.5

This commit is contained in:
Mario Fetka
2021-07-25 07:50:50 +02:00
parent 8ff3be4216
commit 3bfaa6e020
2049 changed files with 317193 additions and 1632423 deletions

View File

@@ -19,22 +19,18 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import print_function
import logging
import sys
import os
from ipaplatform.paths import paths
from ipaserver.install import (replication, installutils, bindinstance,
cainstance)
from ipalib import api, errors
from ipalib.util import has_managed_topology
from ipapython import ipautil, ipaldap, version
from ipapython.dn import DN
import krbV
from ipapython.ipa_log_manager import *
logger = logging.getLogger(os.path.basename(__file__))
from ipaserver.install import (replication, installutils, bindinstance,
cainstance, certs)
from ipalib import api, errors, util
from ipalib.constants import CACERT
from ipapython import ipautil, ipaldap, version, dogtag
from ipapython.dn import DN
# dict of command name and tuples of min/max num of args needed
commands = {
@@ -52,7 +48,7 @@ commands = {
def parse_options():
from optparse import OptionParser # pylint: disable=deprecated-module
from optparse import OptionParser
parser = OptionParser(version=version.VERSION)
parser.add_option("-H", "--host", dest="host", help="starting host")
@@ -95,10 +91,8 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
try:
# connect to main IPA LDAP server
ldap_uri = ipaldap.get_ldap_uri(host, 636, cacert=paths.IPA_CA_CRT)
conn = ipaldap.LDAPClient(ldap_uri, cacert=paths.IPA_CA_CRT)
conn.simple_bind(bind_dn=ipaldap.DIRMAN_DN,
bind_password=dirman_passwd)
conn = ipaldap.IPAdmin(host, 636, cacert=CACERT)
conn.do_simple_bind(bindpw=dirman_passwd)
dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), ipautil.realm_to_suffix(realm))
entries = conn.get_entries(dn, conn.SCOPE_ONELEVEL)
@@ -111,7 +105,7 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
except errors.NotFound:
peers[ent.single_value['cn']] = ['CA not configured', '']
except Exception as e:
except Exception, e:
sys.exit(
"Failed to get data from '%s' while trying to list replicas: %s" %
(host, e))
@@ -119,31 +113,31 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
conn.unbind()
if not replica:
for k, p in peers.items():
print('%s: %s' % (k, p[0]))
for k, p in peers.iteritems():
print '%s: %s' % (k, p[0])
return
try:
repl = replication.get_cs_replication_manager(realm, replica, dirman_passwd)
except Exception as e:
except Exception, e:
sys.exit(str(e))
entries = repl.find_replication_agreements()
for entry in entries:
print('%s' % entry.single_value.get('nsds5replicahost'))
print '%s' % entry.single_value.get('nsds5replicahost')
if verbose:
print(" last init status: %s" % entry.single_value.get(
'nsds5replicalastinitstatus'))
print(" last init ended: %s" % str(
print " last init status: %s" % entry.single_value.get(
'nsds5replicalastinitstatus')
print " last init ended: %s" % str(
ipautil.parse_generalized_time(
entry.single_value['nsds5replicalastinitend'])))
print(" last update status: %s" % entry.single_value.get(
'nsds5replicalastupdatestatus'))
print(" last update ended: %s" % str(
entry.single_value['nsds5replicalastinitend']))
print " last update status: %s" % entry.single_value.get(
'nsds5replicalastupdatestatus')
print " last update ended: %s" % str(
ipautil.parse_generalized_time(
entry.single_value['nsds5replicalastupdateend'])))
entry.single_value['nsds5replicalastupdateend']))
def del_link(realm, replica1, replica2, dirman_passwd, force=False):
@@ -168,9 +162,9 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False):
repl1.hostnames = [replica1, replica2]
except errors.NetworkError as e:
except errors.NetworkError, e:
sys.exit("Unable to connect to %s: %s" % (replica1, e))
except Exception as e:
except Exception, e:
sys.exit("Failed to get data from '%s': %s" % (replica1, e))
try:
@@ -183,20 +177,20 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False):
# Now that we've confirmed that both hostnames are vaild, make sure
# that we aren't removing the last link from either side.
if not force and len(repl_list) <= 1:
print("Cannot remove the last replication link of '%s'" % replica2)
print("Please use the 'del' command to remove it from the domain")
print "Cannot remove the last replication link of '%s'" % replica2
print "Please use the 'del' command to remove it from the domain"
sys.exit(1)
if not force and len(repl_list1) <= 1:
print("Cannot remove the last replication link of '%s'" % replica1)
print("Please use the 'del' command to remove it from the domain")
print "Cannot remove the last replication link of '%s'" % replica1
print "Please use the 'del' command to remove it from the domain"
sys.exit(1)
# Find the DN of the replication agreement to remove
replica2_dn = None
for entry in repl_list:
if entry.single_value.get('nsDS5ReplicaHost') == replica1:
replica2_dn = entry.dn
for e in repl_list:
if e.single_value.get('nsDS5ReplicaHost') == replica1:
replica2_dn = e.dn
break
# This should never happen
@@ -204,11 +198,11 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False):
sys.exit("'%s' has no replication agreement for '%s'" % (replica1, replica2))
except errors.NotFound:
print("'%s' has no replication agreement for '%s'" % (replica2, replica1))
print "'%s' has no replication agreement for '%s'" % (replica2, replica1)
if not force:
return
except Exception as exc:
print("Failed to get data from '%s': %s" % (replica2, exc))
except Exception, e:
print "Failed to get data from '%s': %s" % (replica2, e)
if not force:
sys.exit(1)
@@ -217,32 +211,35 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False):
try:
repl2.delete_agreement(replica1, replica2_dn)
repl2.delete_referral(replica1, repl1.port)
except Exception as exc:
print("Unable to remove agreement on %s: %s" % (replica2, exc))
except Exception, e:
print "Unable to remove agreement on %s: %s" % (replica2, e)
failed = True
if failed:
if force:
print("Forcing removal on '%s'" % replica1)
print "Forcing removal on '%s'" % replica1
else:
sys.exit(1)
if not repl2 and force:
print("Forcing removal on '%s'" % replica1)
print "Forcing removal on '%s'" % replica1
repl1.delete_agreement(replica2, replica1_dn)
repl1.delete_referral(replica2, repl2.port)
print("Deleted replication agreement from '%s' to '%s'" % (replica1, replica2))
print "Deleted replication agreement from '%s' to '%s'" % (replica1, replica2)
def del_master(realm, hostname, options):
force_del = False
delrepl = None
# 1. Connect to the local dogtag DS server
try:
thisrepl = replication.get_cs_replication_manager(realm, options.host,
options.dirman_passwd)
except Exception as e:
except Exception, e:
sys.exit("Failed to connect to server %s: %s" % (options.host, e))
# 2. Ensure we have an agreement with the master
@@ -253,12 +250,13 @@ def del_master(realm, hostname, options):
try:
delrepl = replication.get_cs_replication_manager(realm, hostname,
options.dirman_passwd)
except Exception as e:
except Exception, e:
if not options.force:
print("Unable to delete replica %s: %s" % (hostname, e))
print "Unable to delete replica %s: %s" % (hostname, e)
sys.exit(1)
else:
print("Unable to connect to replica %s, forcing removal" % hostname)
print "Unable to connect to replica %s, forcing removal" % hostname
force_del = True
# 4. Get list of agreements.
if delrepl is None:
@@ -273,44 +271,45 @@ def del_master(realm, hostname, options):
for r in replica_names:
try:
del_link(realm, r, hostname, options.dirman_passwd, force=True)
except Exception as e:
except Exception, e:
sys.exit("There were issues removing a connection: %s" % e)
# 6. Pick CA renewal master
ca = cainstance.CAInstance(api.env.realm)
ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR)
if ca.is_renewal_master(hostname):
ca.set_renewal_master(options.host)
# 7. And clean up the removed replica DNS entries if any.
try:
if bindinstance.dns_container_exists(api.env.basedn):
if bindinstance.dns_container_exists(options.host, api.env.basedn,
dm_password=options.dirman_passwd):
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=options.dirman_passwd)
bind = bindinstance.BindInstance()
bind.update_system_records()
except Exception as e:
print("Failed to cleanup %s DNS entries: %s" % (hostname, e))
print("You may need to manually remove them from the tree")
bind.remove_ipa_ca_dns_records(hostname, realm.lower())
except Exception, e:
print "Failed to cleanup %s DNS entries: %s" % (hostname, e)
print "You may need to manually remove them from the tree"
def add_link(realm, replica1, replica2, dirman_passwd, options):
try:
repl2 = replication.get_cs_replication_manager(realm, replica2,
dirman_passwd)
except Exception as e:
except Exception, e:
sys.exit(str(e))
try:
ldap_uri = ipaldap.get_ldap_uri(replica2, 636, cacert=paths.IPA_CA_CRT)
conn = ipaldap.LDAPClient(ldap_uri, cacert=paths.IPA_CA_CRT)
conn.simple_bind(bind_dn=ipaldap.DIRMAN_DN,
bind_password=dirman_passwd)
conn = ipaldap.IPAdmin(replica2, 636, cacert=CACERT)
conn.do_simple_bind(bindpw=dirman_passwd)
dn = DN(('cn', 'CA'), ('cn', replica2), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
ipautil.realm_to_suffix(realm))
conn.get_entries(dn, conn.SCOPE_BASE)
conn.get_entries(dn, conn.SCOPE_ONELEVEL)
conn.unbind()
except errors.NotFound:
sys.exit('%s does not have a CA configured.' % replica2)
except errors.NetworkError as e:
except errors.NetworkError, e:
sys.exit("Unable to connect to %s: %s" % (ipautil.format_netloc(replica2, 636), str(e)))
except Exception as e:
except Exception, e:
sys.exit("Failed to get data while trying to bind to '%s': %s" % (replica1, str(e)))
try:
@@ -324,9 +323,9 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
except errors.NotFound:
sys.exit("Cannot find replica '%s'" % replica1)
except errors.NetworkError as e:
except errors.NetworkError, e:
sys.exit("Unable to connect to %s: %s" % (replica1, e))
except Exception as e:
except Exception, e:
sys.exit(
"Failed to get data from '%s' while trying to get current "
"agreements: %s" % (replica1, e))
@@ -334,7 +333,7 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
repl1.setup_replication(
replica2, repl2.port, 0, DN(('cn', 'Directory Manager')),
dirman_passwd, is_cs_replica=True, local_port=repl1.port)
print("Connected '%s' to '%s'" % (replica1, replica2))
print "Connected '%s' to '%s'" % (replica1, replica2)
def re_initialize(realm, options):
@@ -348,7 +347,7 @@ def re_initialize(realm, options):
options.dirman_passwd)
thisrepl = replication.get_cs_replication_manager(realm, thishost,
options.dirman_passwd)
except Exception as e:
except Exception, e:
sys.exit(str(e))
filter = repl.get_agreement_filter(host=thishost)
@@ -356,12 +355,10 @@ def re_initialize(realm, options):
entry = repl.conn.get_entries(
DN(('cn', 'config')), repl.conn.SCOPE_SUBTREE, filter)
except errors.NotFound:
logger.error("Unable to find %s -> %s replication agreement",
options.fromhost, thishost)
root_logger.error("Unable to find %s -> %s replication agreement" % (options.fromhost, thishost))
sys.exit(1)
if len(entry) > 1:
logger.error("Found multiple agreements for %s. Only initializing the "
"first one returned: %s", thishost, entry[0].dn)
root_logger.error("Found multiple agreements for %s. Only initializing the first one returned: %s" % (thishost, entry[0].dn))
repl.hostnames = thisrepl.hostnames = [thishost, options.fromhost]
thisrepl.enable_agreement(options.fromhost)
@@ -376,57 +373,41 @@ def force_sync(realm, thishost, fromhost, dirman_passwd):
repl = replication.get_cs_replication_manager(realm, fromhost,
dirman_passwd)
repl.force_sync(repl.conn, thishost)
except Exception as e:
except Exception, e:
sys.exit(str(e))
def set_renewal_master(realm, replica):
if not replica:
replica = installutils.get_fqdn()
ca = cainstance.CAInstance(realm)
ca = cainstance.CAInstance(realm, certs.NSS_DIR)
if ca.is_renewal_master(replica):
sys.exit("%s is already the renewal master" % replica)
try:
ca.set_renewal_master(replica)
except Exception as e:
except Exception, e:
sys.exit("Failed to set renewal master to %s: %s" % (replica, e))
print("%s is now the renewal master" % replica)
def exit_on_managed_topology(what, hint="topologysegment"):
if hint == "topologysegment":
hinttext = ("Please use `ipa topologysegment-*` commands to manage "
"the topology.")
elif hint == "ipa-replica-manage-del":
hinttext = ("Please use the `ipa-replica-manage del` command.")
else:
assert False, "Unexpected value"
sys.exit("{0} is deprecated with managed IPA replication topology. {1}"
.format(what, hinttext))
print "%s is now the renewal master" % replica
def main():
options, args = parse_options()
# Just initialize the environment. This is so the installer can have
# access to the plugin environment
api_env = {}
api_env = {'in_server' : True,
'verbose' : options.verbose,
}
if os.getegid() != 0:
api_env['log'] = None # turn off logging for non-root
api.bootstrap(
context='cli',
in_server=True,
verbose=options.verbose,
confdir=paths.ETC_IPA,
**api_env
)
api.bootstrap(**api_env)
api.finalize()
dirman_passwd = None
realm = api.env.realm
realm = krbV.default_context().default_realm
if options.host:
host = options.host
@@ -445,18 +426,12 @@ def main():
options.dirman_passwd = dirman_passwd
api.Backend.ldap2.connect(bind_pw=options.dirman_passwd)
if args[0] == "list":
replica = None
if len(args) == 2:
replica = args[1]
list_replicas(realm, host, replica, dirman_passwd, options.verbose)
elif args[0] == "del":
if has_managed_topology(api):
exit_on_managed_topology(
"Removal of IPA CS replication agreement and replication data",
hint="ipa-replica-manage-del")
del_master(realm, args[1], options)
elif args[0] == "re-initialize":
re_initialize(realm, options)
@@ -465,8 +440,6 @@ def main():
sys.exit("force-sync requires the option --from <host name>")
force_sync(realm, host, options.fromhost, options.dirman_passwd)
elif args[0] == "connect":
if has_managed_topology(api):
exit_on_managed_topology("Creation of IPA CS replication agreement")
if len(args) == 3:
replica1 = args[1]
replica2 = args[2]
@@ -475,8 +448,6 @@ def main():
replica2 = args[1]
add_link(realm, replica1, replica2, dirman_passwd, options)
elif args[0] == "disconnect":
if has_managed_topology(api):
exit_on_managed_topology("Removal of IPA CS replication agreement")
if len(args) == 3:
replica1 = args[1]
replica2 = args[2]
@@ -490,13 +461,11 @@ def main():
replica = args[1]
set_renewal_master(realm, replica)
api.Backend.ldap2.disconnect()
try:
main()
except KeyboardInterrupt:
sys.exit(1)
except SystemExit as e:
except SystemExit, e:
sys.exit(e)
except Exception as e:
except Exception, e:
sys.exit("unexpected error: %s" % e)