Fix ipa-server-upgrade with server cert tracking

ipa-server-upgrade fails with Server-Cert not found, when trying to
track httpd/ldap server certificates. There are 2 issues in the upgrade:
- the certificates should be tracked only if they were issued by IPA CA
(it is possible to have CA configured but 3rd part certs)
- the certificate nickname can be different from Server-Cert

The fix provides methods to find the server crt nickname for http and ldap,
and a method to check if the server certs are issued by IPA and need to be
tracked by certmonger.

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

Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
This commit is contained in:
Florence Blanc-Renaud
2017-09-05 16:17:31 +02:00
committed by Stanislav Laznicka
parent 62e72c2a53
commit 87540fe1ef
4 changed files with 82 additions and 9 deletions

View File

@@ -1033,22 +1033,59 @@ class DsInstance(service.Service):
logger.error(
'Unable to restart DS instance %s: %s', ds_instance, e)
def get_server_cert_nickname(self, serverid=None):
"""
Retrieve the nickname of the server cert used by dirsrv.
The method directly reads the dse.ldif to find the attribute
nsSSLPersonalitySSL of cn=RSA,cn=encryption,cn=config because
LDAP is not always accessible when we need to get the nickname
(for instance during uninstall).
"""
if serverid is None:
serverid = self.get_state("serverid")
if serverid is not None:
dirname = config_dirname(serverid)
config_file = os.path.join(dirname, "dse.ldif")
rsa_dn = "cn=RSA,cn=encryption,cn=config"
with open(config_file, "r") as in_file:
parser = upgradeinstance.GetEntryFromLDIF(
in_file,
entries_dn=[rsa_dn])
parser.parse()
try:
config_entry = parser.get_results()[rsa_dn]
nickname = config_entry["nsSSLPersonalitySSL"][0]
return nickname.decode('utf-8')
except (KeyError, IndexError):
logger.error("Unable to find server cert nickname in %s",
config_file)
logger.debug("Falling back to nickname Server-Cert")
return 'Server-Cert'
def stop_tracking_certificates(self, serverid=None):
if serverid is None:
serverid = self.get_state("serverid")
if not serverid is None:
nickname = self.get_server_cert_nickname(serverid)
# drop the trailing / off the config_dirname so the directory
# will match what is in certmonger
dirname = config_dirname(serverid)[:-1]
dsdb = certs.CertDB(self.realm, nssdir=dirname)
dsdb.untrack_server_cert(self.nickname)
dsdb.untrack_server_cert(nickname)
def start_tracking_certificates(self, serverid):
nickname = self.get_server_cert_nickname(serverid)
dirname = config_dirname(serverid)[:-1]
dsdb = certs.CertDB(self.realm, nssdir=dirname)
dsdb.track_server_cert(self.nickname, self.principal,
dsdb.passwd_fname,
'restart_dirsrv %s' % serverid)
if dsdb.is_ipa_issued_cert(api, nickname):
dsdb.track_server_cert(nickname, self.principal,
dsdb.passwd_fname,
'restart_dirsrv %s' % serverid)
else:
logger.debug("Will not track DS server certificate %s as it is "
"not issued by IPA", nickname)
# we could probably move this function into the service.Service
# class - it's very generic - all we need is a way to get an