mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add delete option to ipa-cacert-manage to remove CA certificates
Before removing a CA re-verify all the other CAs to ensure that the chain is not broken. Provide a force option to handle cases where the CA is expired or verification fails for some other reason, or you really just want them gone. https://pagure.io/freeipa/issue/8124 Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
This commit is contained in:
@@ -24,6 +24,8 @@ ipa\-cacert\-manage \- Manage CA certificates in IPA
|
||||
.br
|
||||
\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] install \fICERTFILE\fR...
|
||||
.br
|
||||
\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] delete \fINICKNAME\fR
|
||||
.br
|
||||
\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] list
|
||||
.SH "DESCRIPTION"
|
||||
\fBipa\-cacert\-manage\fR can be used to manage CA certificates in IPA.
|
||||
@@ -54,6 +56,16 @@ Please do not forget to run ipa-certupdate on the master, all the replicas and a
|
||||
.sp
|
||||
The supported formats for the certificate files are DER, PEM and PKCS#7 format.
|
||||
.RE
|
||||
.TP
|
||||
\fBdelete\fR
|
||||
\- Remove a CA certificate
|
||||
.sp
|
||||
.RS
|
||||
Remove a CA from IPA. The nickname of a CA to be removed can be found using the list command. The CA chain is validated before allowing a CA to be removed so leaf certificates in a chain need to be removed first.
|
||||
.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.
|
||||
.RE
|
||||
.TP
|
||||
\fBlist\fR
|
||||
\- List the stored CA certificates
|
||||
.sp
|
||||
@@ -130,6 +142,11 @@ T \- CA trusted to issue client certificates
|
||||
.IP
|
||||
p \- not trusted
|
||||
.RE
|
||||
.SH "DELETE OPTIONS"
|
||||
.TP
|
||||
\fB\-f\fR, \fB\-\-force\fR
|
||||
Force a CA certificate to be removed even if chain validation fails.
|
||||
.RE
|
||||
.SH "EXIT STATUS"
|
||||
0 if the command was successful
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ from ipapython import admintool, ipautil
|
||||
from ipapython.certdb import (EMPTY_TRUST_FLAGS,
|
||||
EXTERNAL_CA_TRUST_FLAGS,
|
||||
TrustFlags,
|
||||
parse_trust_flags)
|
||||
parse_trust_flags,
|
||||
get_ca_nickname)
|
||||
from ipapython.dn import DN
|
||||
from ipaplatform.paths import paths
|
||||
from ipalib import api, errors, x509
|
||||
@@ -42,7 +43,8 @@ logger = logging.getLogger(__name__)
|
||||
class CACertManage(admintool.AdminTool):
|
||||
command_name = 'ipa-cacert-manage'
|
||||
|
||||
usage = "%prog renew [options]\n%prog install [options] CERTFILE"
|
||||
usage = "%prog renew [options]\n%prog install [options] CERTFILE\n" \
|
||||
"%prog delete [options] NICKNAME\n%prog list"
|
||||
|
||||
description = "Manage CA certificates."
|
||||
|
||||
@@ -93,6 +95,12 @@ class CACertManage(admintool.AdminTool):
|
||||
help="Trust flags for the certificate in certutil format")
|
||||
parser.add_option_group(install_group)
|
||||
|
||||
delete_group = OptionGroup(parser, "Delete options")
|
||||
delete_group.add_option(
|
||||
"-f", "--force", action='store_true',
|
||||
help="Force removing the CA even if chain validation fails")
|
||||
parser.add_option_group(delete_group)
|
||||
|
||||
def validate_options(self):
|
||||
super(CACertManage, self).validate_options(needs_root=True)
|
||||
|
||||
@@ -112,6 +120,9 @@ class CACertManage(admintool.AdminTool):
|
||||
parser.error("certificate file name not provided")
|
||||
elif command == 'list':
|
||||
pass
|
||||
elif command == 'delete':
|
||||
if len(self.args) < 2:
|
||||
parser.error("nickname not provided")
|
||||
else:
|
||||
parser.error("unknown command \"%s\"" % command)
|
||||
|
||||
@@ -130,6 +141,8 @@ class CACertManage(admintool.AdminTool):
|
||||
return self.install()
|
||||
elif command == 'list':
|
||||
return self.list()
|
||||
elif command == 'delete':
|
||||
return self.delete()
|
||||
else:
|
||||
raise NotImplementedError
|
||||
finally:
|
||||
@@ -466,6 +479,71 @@ class CACertManage(admintool.AdminTool):
|
||||
for _ca_cert, ca_nickname, _ca_trust_flags in ca_certs:
|
||||
print(ca_nickname)
|
||||
|
||||
def delete(self):
|
||||
options = self.options
|
||||
nickname = self.args[1]
|
||||
conn = api.Backend.ldap2
|
||||
|
||||
ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2,
|
||||
api.env.basedn,
|
||||
api.env.realm,
|
||||
False)
|
||||
|
||||
ipa_ca_nickname = get_ca_nickname(api.env.realm)
|
||||
|
||||
found = False
|
||||
for _ca_cert, ca_nickname, _ca_trust_flags in ca_certs:
|
||||
if ca_nickname == nickname:
|
||||
if ca_nickname == ipa_ca_nickname:
|
||||
raise admintool.ScriptError(
|
||||
'The IPA CA cannot be removed with this tool'
|
||||
)
|
||||
else:
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
raise admintool.ScriptError(
|
||||
'Unknown CA \'{}\''.format(nickname)
|
||||
)
|
||||
|
||||
with certs.NSSDatabase() as tmpdb:
|
||||
tmpdb.create_db()
|
||||
for ca_cert, ca_nickname, ca_trust_flags in ca_certs:
|
||||
tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags)
|
||||
loaded = tmpdb.list_certs()
|
||||
logger.debug("loaded raw certs '%s'", loaded)
|
||||
|
||||
tmpdb.delete_cert(nickname)
|
||||
|
||||
for ca_nickname, _trust_flags in loaded:
|
||||
if ca_nickname == nickname:
|
||||
continue
|
||||
elif ipa_ca_nickname == nickname:
|
||||
raise admintool.ScriptError(
|
||||
"The IPA CA cannot be removed")
|
||||
logger.debug("Verifying %s", ca_nickname)
|
||||
try:
|
||||
tmpdb.verify_ca_cert_validity(ca_nickname)
|
||||
except ValueError as e:
|
||||
msg = "Verifying \'%s\' failed. Removing part of the " \
|
||||
"chain? %s" % (nickname, e)
|
||||
if options.force:
|
||||
print(msg)
|
||||
continue
|
||||
raise admintool.ScriptError(msg)
|
||||
else:
|
||||
logger.debug("Verified %s", ca_nickname)
|
||||
|
||||
for _ca_cert, ca_nickname, _ca_trust_flags in ca_certs:
|
||||
if ca_nickname == nickname:
|
||||
container_dn = DN(('cn', 'certificates'), ('cn', 'ipa'),
|
||||
('cn', 'etc'), api.env.basedn)
|
||||
dn = DN(('cn', nickname), container_dn)
|
||||
logger.debug("Deleting %s", ca_nickname)
|
||||
conn.delete_entry(dn)
|
||||
return
|
||||
|
||||
|
||||
def update_ipa_ca_entry(api, cert):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user