Ensure IPA is running (ideally) before uninstalling the KRA

The KRA attempts to unregister itself from the security domain
which requires that IPA be running for this to succeed.

1. Move the KRA uninstall call prior to stopping all IPA
   services
2. Try to start IPA if it isn't running and a KRA is configured

It isn't mandatory that IPA be running for the KRA uninstall to
succeed but it will suppress a pretty scary backtrace and error
message.

https://pagure.io/freeipa/issue/8550

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
This commit is contained in:
Rob Crittenden 2021-01-25 11:40:22 -05:00 committed by Florence Blanc-Renaud
parent 928ab51be6
commit 1870c93354
3 changed files with 41 additions and 9 deletions

View File

@ -306,7 +306,12 @@ def get_config(dirsrv):
return deduplicate(ordered_list) return deduplicate(ordered_list)
def get_config_from_file(): def get_config_from_file(rval):
"""
Get the list of configured services from the cached file.
:param rval: The return value for any exception that is raised.
"""
svc_list = [] svc_list = []
@ -316,7 +321,8 @@ def get_config_from_file():
except Exception as e: except Exception as e:
raise IpactlError( raise IpactlError(
"Unknown error when retrieving list of services from file: %s" "Unknown error when retrieving list of services from file: %s"
% str(e) % str(e),
4
) )
# the framework can start/stop a number of related services we are not # the framework can start/stop a number of related services we are not
@ -427,7 +433,7 @@ def ipa_start(options):
def ipa_stop(options): def ipa_stop(options):
dirsrv = services.knownservices.dirsrv dirsrv = services.knownservices.dirsrv
try: try:
svc_list = get_config_from_file() svc_list = get_config_from_file(rval=4)
except Exception as e: except Exception as e:
# Issue reading the file ? Let's try to get data from LDAP as a # Issue reading the file ? Let's try to get data from LDAP as a
# fallback # fallback
@ -509,7 +515,7 @@ def ipa_restart(options):
old_svc_list = [] old_svc_list = []
try: try:
old_svc_list = get_config_from_file() old_svc_list = get_config_from_file(rval=4)
except Exception as e: except Exception as e:
emit_err("Failed to get service list from file: " + str(e)) emit_err("Failed to get service list from file: " + str(e))
# fallback to what's in LDAP # fallback to what's in LDAP
@ -629,13 +635,14 @@ def ipa_status(options):
We only really care about 0, 3 and 4. We only really care about 0, 3 and 4.
""" """
socket_activated = ('ipa-ods-exporter', 'ipa-otpd',)
try: try:
dirsrv = services.knownservices.dirsrv dirsrv = services.knownservices.dirsrv
if dirsrv.is_running(): if dirsrv.is_running():
svc_list = get_config(dirsrv) svc_list = get_config(dirsrv)
else: else:
svc_list = get_config_from_file() svc_list = get_config_from_file(rval=1)
except IpactlError as e: except IpactlError as e:
if os.path.exists(tasks.get_svc_list_file()): if os.path.exists(tasks.get_svc_list_file()):
raise e raise e
@ -647,12 +654,14 @@ def ipa_status(options):
4 4
) )
stopped = 0
dirsrv = services.knownservices.dirsrv dirsrv = services.knownservices.dirsrv
try: try:
if dirsrv.is_running(): if dirsrv.is_running():
print("Directory Service: RUNNING") print("Directory Service: RUNNING")
else: else:
print("Directory Service: STOPPED") print("Directory Service: STOPPED")
stopped = 1
except Exception as e: except Exception as e:
raise IpactlError("Failed to get Directory Service status", 4) raise IpactlError("Failed to get Directory Service status", 4)
@ -665,7 +674,6 @@ def ipa_status(options):
3, 3,
) )
stopped = 0
for svc in svc_list: for svc in svc_list:
svchandle = services.service(svc, api=api) svchandle = services.service(svc, api=api)
try: try:
@ -673,7 +681,8 @@ def ipa_status(options):
print("%s Service: RUNNING" % svc) print("%s Service: RUNNING" % svc)
else: else:
print("%s Service: STOPPED" % svc) print("%s Service: STOPPED" % svc)
stopped += 1 if svc not in socket_activated:
stopped += 1
except Exception: except Exception:
emit_err("Failed to get %s Service status" % svc) emit_err("Failed to get %s Service status" % svc)

View File

@ -8,6 +8,7 @@ KRA installer module
from __future__ import absolute_import from __future__ import absolute_import
import logging
import os import os
from ipalib import api from ipalib import api
@ -23,6 +24,8 @@ from ipaserver.install import service as _service
from . import dogtag from . import dogtag
logger = logging.getLogger(__name__)
def install_check(api, replica_config, options): def install_check(api, replica_config, options):
if replica_config is not None and not replica_config.setup_kra: if replica_config is not None and not replica_config.setup_kra:
@ -113,6 +116,22 @@ def install(api, replica_config, options, custodia):
named.restart(capture_output=True) named.restart(capture_output=True)
def uninstall_check(options):
"""IPA needs to be running so pkidestroy can unregister KRA"""
kra = krainstance.KRAInstance(api.env.realm)
if not kra.is_installed():
return
result = ipautil.run([paths.IPACTL, 'status'],
raiseonerr=False)
if result.returncode not in [0, 4]:
try:
ipautil.run([paths.IPACTL, 'start'])
except Exception:
logger.info("Re-starting IPA failed, continuing uninstall")
def uninstall(): def uninstall():
kra = krainstance.KRAInstance(api.env.realm) kra = krainstance.KRAInstance(api.env.realm)
kra.stop_tracking_certificates() kra.stop_tracking_certificates()

View File

@ -1098,6 +1098,8 @@ def uninstall_check(installer):
"uninstall procedure?", False): "uninstall procedure?", False):
raise ScriptError("Aborting uninstall operation.") raise ScriptError("Aborting uninstall operation.")
kra.uninstall_check(options)
try: try:
api.Backend.ldap2.connect(autobind=True) api.Backend.ldap2.connect(autobind=True)
@ -1165,6 +1167,10 @@ def uninstall(installer):
rv = 0 rv = 0
# Uninstall the KRA prior to shutting the services down so it
# can un-register with the CA.
kra.uninstall()
print("Shutting down all IPA services") print("Shutting down all IPA services")
try: try:
services.knownservices.ipa.stop() services.knownservices.ipa.stop()
@ -1177,8 +1183,6 @@ def uninstall(installer):
restore_time_sync(sstore, fstore) restore_time_sync(sstore, fstore)
kra.uninstall()
ca.uninstall() ca.uninstall()
dns.uninstall() dns.uninstall()