mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add support for multiple certificates/formats to ipa-cacert-manage
Only a single cert in DER or PEM format would be loaded from the provided file. Extend this to include PKCS#7 format and load all certificates found in the file. Signed-off-by: Rob Crittenden <rcritten@redhat.com> https://pagure.io/freeipa/issue/7579 Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
This commit is contained in:
committed by
Christian Heimes
parent
3e8f550c29
commit
35d1d345c1
@@ -22,7 +22,9 @@ ipa\-cacert\-manage \- Manage CA certificates in IPA
|
||||
.SH "SYNOPSIS"
|
||||
\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] renew
|
||||
.RE
|
||||
\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] install \fICERTFILE\fR
|
||||
\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] install \fICERTFILE\fR...
|
||||
.RE
|
||||
\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] list
|
||||
.SH "DESCRIPTION"
|
||||
\fBipa\-cacert\-manage\fR can be used to manage CA certificates in IPA.
|
||||
.SH "COMMANDS"
|
||||
@@ -41,14 +43,22 @@ When the IPA CA is not configured, this command is not available.
|
||||
.RE
|
||||
.TP
|
||||
\fBinstall\fR
|
||||
\- Install a CA certificate
|
||||
\- Install one or more CA certificates
|
||||
.sp
|
||||
.RS
|
||||
This command can be used to install the certificate contained in \fICERTFILE\fR as an additional CA certificate to IPA.
|
||||
This command can be used to install the certificates contained in \fICERTFILE\fR as additional CA certificates to IPA.
|
||||
.sp
|
||||
Important: this does not replace IPA CA but adds the provided certificate as a known CA. This is useful for instance when using ipa-server-certinstall to replace HTTP/LDAP certificates with third-party certificates signed by this additional CA.
|
||||
.sp
|
||||
Please do not forget to run ipa-certupdate on the master, all the replicas and all the clients after this command in order to update IPA certificates databases.
|
||||
.sp
|
||||
The supported formats for the certificate files are DER, PEM and PKCS#7 format.
|
||||
.RE
|
||||
\fBlist\fR
|
||||
\- List the stored CA certificates
|
||||
.sp
|
||||
.RS
|
||||
Display a list of the nicknames or subjects of the CA certificates that have been installed.
|
||||
.RE
|
||||
.SH "COMMON OPTIONS"
|
||||
.TP
|
||||
@@ -106,7 +116,7 @@ File containing the IPA CA certificate and the external CA certificate chain. Th
|
||||
.SH "INSTALL OPTIONS"
|
||||
.TP
|
||||
\fB\-n\fR \fINICKNAME\fR, \fB\-\-nickname\fR=\fINICKNAME\fR
|
||||
Nickname for the certificate.
|
||||
Nickname for the certificate. Applicable only when a single certificate is being installed.
|
||||
.TP
|
||||
\fB\-t\fR \fITRUST_FLAGS\fR, \fB\-\-trust\-flags\fR=\fITRUST_FLAGS\fR
|
||||
Trust flags for the certificate in certutil format. Trust flags are of the form "A,B,C" or "A,B,C,D" where A is for SSL, B is for S/MIME, C is for code signing, and D is for PKINIT. Use ",," for no explicit trust.
|
||||
|
||||
@@ -110,6 +110,8 @@ class CACertManage(admintool.AdminTool):
|
||||
elif command == 'install':
|
||||
if len(self.args) < 2:
|
||||
parser.error("certificate file name not provided")
|
||||
elif command == 'list':
|
||||
pass
|
||||
else:
|
||||
parser.error("unknown command \"%s\"" % command)
|
||||
|
||||
@@ -126,6 +128,8 @@ class CACertManage(admintool.AdminTool):
|
||||
return self.renew()
|
||||
elif command == 'install':
|
||||
return self.install()
|
||||
elif command == 'list':
|
||||
return self.list()
|
||||
else:
|
||||
raise NotImplementedError
|
||||
finally:
|
||||
@@ -379,17 +383,6 @@ class CACertManage(admintool.AdminTool):
|
||||
print("Installing CA certificate, please wait")
|
||||
|
||||
options = self.options
|
||||
cert_filename = self.args[1]
|
||||
|
||||
try:
|
||||
cert = x509.load_certificate_from_file(cert_filename)
|
||||
except IOError as e:
|
||||
raise admintool.ScriptError(
|
||||
"Can't open \"%s\": %s" % (cert_filename, e))
|
||||
except (TypeError, ValueError) as e:
|
||||
raise admintool.ScriptError("Not a valid certificate: %s" % e)
|
||||
|
||||
nickname = options.nickname or str(DN(cert.subject))
|
||||
|
||||
ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2,
|
||||
api.env.basedn,
|
||||
@@ -398,46 +391,81 @@ class CACertManage(admintool.AdminTool):
|
||||
|
||||
with certs.NSSDatabase() as tmpdb:
|
||||
tmpdb.create_db()
|
||||
tmpdb.add_cert(cert, nickname, EXTERNAL_CA_TRUST_FLAGS)
|
||||
tmpdb.import_files(self.args[1:])
|
||||
imported = tmpdb.list_certs()
|
||||
logger.debug("loaded raw certs '%s'", imported)
|
||||
|
||||
if len(imported) > 1 and options.nickname:
|
||||
raise admintool.ScriptError(
|
||||
"Nickname can only be used if only a single "
|
||||
"certificate is loaded")
|
||||
|
||||
# If a nickname was provided re-import the cert
|
||||
if options.nickname:
|
||||
(nickname, trust_flags) = imported[0]
|
||||
cert = tmpdb.get_cert(nickname)
|
||||
tmpdb.delete_cert(nickname)
|
||||
tmpdb.add_cert(cert, options.nickname, EXTERNAL_CA_TRUST_FLAGS)
|
||||
imported = tmpdb.list_certs()
|
||||
|
||||
for ca_cert, ca_nickname, ca_trust_flags in ca_certs:
|
||||
tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags)
|
||||
|
||||
try:
|
||||
tmpdb.verify_ca_cert_validity(nickname)
|
||||
except ValueError as e:
|
||||
raise admintool.ScriptError(
|
||||
"Not a valid CA certificate: %s (visit "
|
||||
"http://www.freeipa.org/page/Troubleshooting for "
|
||||
"troubleshooting guide)" % e)
|
||||
for nickname, trust_flags in imported:
|
||||
if trust_flags.has_key:
|
||||
continue
|
||||
tmpdb.trust_root_cert(nickname, EXTERNAL_CA_TRUST_FLAGS)
|
||||
|
||||
trust_flags = options.trust_flags.split(',')
|
||||
if (set(options.trust_flags) - set(',CPTcgpuw') or
|
||||
len(trust_flags) not in [3, 4]):
|
||||
raise admintool.ScriptError("Invalid trust flags")
|
||||
for nickname, trust_flags in imported:
|
||||
try:
|
||||
tmpdb.verify_ca_cert_validity(nickname)
|
||||
except ValueError as e:
|
||||
raise admintool.ScriptError(
|
||||
"Not a valid CA certificate: %s (visit "
|
||||
"http://www.freeipa.org/page/Troubleshooting for "
|
||||
"troubleshooting guide)" % e)
|
||||
else:
|
||||
print("Verified %s" % nickname)
|
||||
|
||||
extra_flags = trust_flags[3:]
|
||||
extra_usages = set()
|
||||
if extra_flags:
|
||||
if 'C' in extra_flags[0]:
|
||||
extra_usages.add(x509.EKU_PKINIT_KDC)
|
||||
if 'T' in extra_flags[0]:
|
||||
extra_usages.add(x509.EKU_PKINIT_CLIENT_AUTH)
|
||||
trust_flags = options.trust_flags.split(',')
|
||||
if (set(options.trust_flags) - set(',CPTcgpuw') or
|
||||
len(trust_flags) not in [3, 4]):
|
||||
raise admintool.ScriptError("Invalid trust flags")
|
||||
|
||||
trust_flags = parse_trust_flags(','.join(trust_flags[:3]))
|
||||
trust_flags = TrustFlags(trust_flags.has_key,
|
||||
trust_flags.trusted,
|
||||
trust_flags.ca,
|
||||
trust_flags.usages | extra_usages)
|
||||
extra_flags = trust_flags[3:]
|
||||
extra_usages = set()
|
||||
if extra_flags:
|
||||
if 'C' in extra_flags[0]:
|
||||
extra_usages.add(x509.EKU_PKINIT_KDC)
|
||||
if 'T' in extra_flags[0]:
|
||||
extra_usages.add(x509.EKU_PKINIT_CLIENT_AUTH)
|
||||
|
||||
try:
|
||||
certstore.put_ca_cert_nss(
|
||||
api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags)
|
||||
except ValueError as e:
|
||||
raise admintool.ScriptError(
|
||||
"Failed to install the certificate: %s" % e)
|
||||
trust_flags = parse_trust_flags(','.join(trust_flags[:3]))
|
||||
trust_flags = TrustFlags(trust_flags.has_key,
|
||||
trust_flags.trusted,
|
||||
trust_flags.ca,
|
||||
trust_flags.usages | extra_usages)
|
||||
|
||||
for nickname, _trust_flags in imported:
|
||||
try:
|
||||
cert = tmpdb.get_cert(nickname)
|
||||
certstore.put_ca_cert_nss(
|
||||
api.Backend.ldap2, api.env.basedn, cert, nickname,
|
||||
trust_flags)
|
||||
except ValueError as e:
|
||||
raise admintool.ScriptError(
|
||||
"Failed to install the certificate: %s" % e)
|
||||
|
||||
print("CA certificate successfully installed")
|
||||
|
||||
def list(self):
|
||||
ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2,
|
||||
api.env.basedn,
|
||||
api.env.realm,
|
||||
False)
|
||||
for _ca_cert, ca_nickname, _ca_trust_flags in ca_certs:
|
||||
print(ca_nickname)
|
||||
|
||||
|
||||
def update_ipa_ca_entry(api, cert):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user