ipa-cacert-manage: support MS V2 template extension

Update ipa-cacert-manage to support the MS V2 certificate template
extension.

Part of: https://pagure.io/freeipa/issue/6858

Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
This commit is contained in:
Fraser Tweedale
2017-08-22 15:40:00 +10:00
committed by Pavel Vomacka
parent 560ee3c0b5
commit 29f4ec865b
2 changed files with 70 additions and 14 deletions

View File

@@ -79,7 +79,26 @@ Sign the renewed certificate by itself.
Sign the renewed certificate by external CA. Sign the renewed certificate by external CA.
.TP .TP
\fB\-\-external\-ca\-type\fR=\fITYPE\fR \fB\-\-external\-ca\-type\fR=\fITYPE\fR
Type of the external CA. Possible values are "generic", "ms-cs". Default value is "generic". Use "ms-cs" to include template name required by Microsoft Certificate Services (MS CS) in the generated CSR. Type of the external CA. Possible values are "generic", "ms-cs". Default value is "generic". Use "ms-cs" to include the template name required by Microsoft Certificate Services (MS CS) in the generated CSR (see \fB\-\-external\-ca\-profile\fR for full details).
.TP
\fB\-\-external\-ca\-profile\fR=\fIPROFILE_SPEC\fR
Specify the certificate profile or template to use at the external CA.
When \fB\-\-external\-ca\-type\fR is "ms-cs" the following specifiers may be used:
.RS
.TP
\fB<oid>:<majorVersion>[:<minorVersion>]\fR
Specify a certificate template by OID and major version, optionally also specifying minor version.
.TP
\fB<name>\fR
Specify a certificate template by name. The name cannot contain any \fI:\fR characters and cannot be an OID (otherwise the OID-based template specifier syntax takes precedence).
.TP
\fBdefault\fR
If no template is specified, the template name "SubCA" is used.
.RE
.TP .TP
\fB\-\-external\-cert\-file\fR=\fIFILE\fR \fB\-\-external\-cert\-file\fR=\fIFILE\fR
File containing the IPA CA certificate and the external CA certificate chain. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times. File containing the IPA CA certificate and the external CA certificate chain. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times.

View File

@@ -60,6 +60,10 @@ class CACertManage(admintool.AdminTool):
"--self-signed", dest='self_signed', "--self-signed", dest='self_signed',
action='store_true', action='store_true',
help="Sign the renewed certificate by itself") help="Sign the renewed certificate by itself")
renew_group.add_option(
"--external-ca", dest='self_signed',
action='store_false',
help="Sign the renewed certificate by external CA")
ext_cas = tuple(x.value for x in cainstance.ExternalCAType) ext_cas = tuple(x.value for x in cainstance.ExternalCAType)
renew_group.add_option( renew_group.add_option(
"--external-ca-type", dest="external_ca_type", "--external-ca-type", dest="external_ca_type",
@@ -67,9 +71,11 @@ class CACertManage(admintool.AdminTool):
metavar="{{{0}}}".format(",".join(ext_cas)), metavar="{{{0}}}".format(",".join(ext_cas)),
help="Type of the external CA. Default: generic") help="Type of the external CA. Default: generic")
renew_group.add_option( renew_group.add_option(
"--external-ca", dest='self_signed', "--external-ca-profile", dest="external_ca_profile",
action='store_false', type='constructor', constructor=cainstance.ExternalCAProfile,
help="Sign the renewed certificate by external CA") default=None, metavar="PROFILE-SPEC",
help="Specify the certificate profile/template to use "
"at the external CA")
renew_group.add_option( renew_group.add_option(
"--external-cert-file", dest="external_cert_files", "--external-cert-file", dest="external_cert_files",
action="append", metavar="FILE", action="append", metavar="FILE",
@@ -179,6 +185,12 @@ class CACertManage(admintool.AdminTool):
def renew_self_signed(self, ca): def renew_self_signed(self, ca):
print("Renewing CA certificate, please wait") print("Renewing CA certificate, please wait")
msg = "You cannot specify {} when renewing a self-signed CA"
if self.options.external_ca_type:
raise admintool.ScriptError(msg.format("--external-ca-type"))
if self.options.external_ca_profile:
raise admintool.ScriptError(msg.format("--external-ca-profile"))
try: try:
ca.set_renewal_master() ca.set_renewal_master()
except errors.NotFound: except errors.NotFound:
@@ -191,13 +203,30 @@ class CACertManage(admintool.AdminTool):
def renew_external_step_1(self, ca): def renew_external_step_1(self, ca):
print("Exporting CA certificate signing request, please wait") print("Exporting CA certificate signing request, please wait")
if self.options.external_ca_type \ options = self.options
== cainstance.ExternalCAType.MS_CS.value:
profile = 'SubCA'
else:
profile = ''
self.resubmit_request('dogtag-ipa-ca-renew-agent-reuse', profile) if not options.external_ca_type:
options.external_ca_type = cainstance.ExternalCAType.GENERIC.value
if options.external_ca_type == cainstance.ExternalCAType.MS_CS.value \
and options.external_ca_profile is None:
options.external_ca_profile = cainstance.MSCSTemplateV1(u"SubCA")
if options.external_ca_profile is not None:
# check that profile is valid for the external ca type
if options.external_ca_type \
not in options.external_ca_profile.valid_for:
raise admintool.ScriptError(
"External CA profile specification '{}' "
"cannot be used with external CA type '{}'."
.format(
options.external_ca_profile.unparsed_input,
options.external_ca_type)
)
self.resubmit_request(
'dogtag-ipa-ca-renew-agent-reuse',
profile=options.external_ca_profile)
print(("The next step is to get %s signed by your CA and re-run " print(("The next step is to get %s signed by your CA and re-run "
"ipa-cacert-manage as:" % paths.IPA_CA_CSR)) "ipa-cacert-manage as:" % paths.IPA_CA_CSR))
@@ -299,12 +328,20 @@ class CACertManage(admintool.AdminTool):
print("CA certificate successfully renewed") print("CA certificate successfully renewed")
def resubmit_request(self, ca='dogtag-ipa-ca-renew-agent', profile=''): def resubmit_request(self, ca='dogtag-ipa-ca-renew-agent', profile=None):
timeout = api.env.startup_timeout + 60 timeout = api.env.startup_timeout + 60
cm_profile = None
if isinstance(profile, cainstance.MSCSTemplateV1):
cm_profile = profile.unparsed_input
cm_template = None
if isinstance(profile, cainstance.MSCSTemplateV2):
cm_template = profile.unparsed_input
logger.debug("resubmitting certmonger request '%s'", self.request_id) logger.debug("resubmitting certmonger request '%s'", self.request_id)
certmonger.resubmit_request(self.request_id, ca=ca, profile=profile, certmonger.resubmit_request(self.request_id, ca=ca, profile=cm_profile,
is_ca=True) template_v2=cm_template, is_ca=True)
try: try:
state = certmonger.wait_for_request(self.request_id, timeout) state = certmonger.wait_for_request(self.request_id, timeout)
except RuntimeError: except RuntimeError:
@@ -320,7 +357,7 @@ class CACertManage(admintool.AdminTool):
logger.debug("modifying certmonger request '%s'", self.request_id) logger.debug("modifying certmonger request '%s'", self.request_id)
certmonger.modify(self.request_id, certmonger.modify(self.request_id,
ca='dogtag-ipa-ca-renew-agent', ca='dogtag-ipa-ca-renew-agent',
profile='') profile='', template_v2='')
def install(self): def install(self):
print("Installing CA certificate, please wait") print("Installing CA certificate, please wait")