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.
.TP
\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
\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.

View File

@@ -60,6 +60,10 @@ class CACertManage(admintool.AdminTool):
"--self-signed", dest='self_signed',
action='store_true',
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)
renew_group.add_option(
"--external-ca-type", dest="external_ca_type",
@@ -67,9 +71,11 @@ class CACertManage(admintool.AdminTool):
metavar="{{{0}}}".format(",".join(ext_cas)),
help="Type of the external CA. Default: generic")
renew_group.add_option(
"--external-ca", dest='self_signed',
action='store_false',
help="Sign the renewed certificate by external CA")
"--external-ca-profile", dest="external_ca_profile",
type='constructor', constructor=cainstance.ExternalCAProfile,
default=None, metavar="PROFILE-SPEC",
help="Specify the certificate profile/template to use "
"at the external CA")
renew_group.add_option(
"--external-cert-file", dest="external_cert_files",
action="append", metavar="FILE",
@@ -179,6 +185,12 @@ class CACertManage(admintool.AdminTool):
def renew_self_signed(self, ca):
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:
ca.set_renewal_master()
except errors.NotFound:
@@ -191,13 +203,30 @@ class CACertManage(admintool.AdminTool):
def renew_external_step_1(self, ca):
print("Exporting CA certificate signing request, please wait")
if self.options.external_ca_type \
== cainstance.ExternalCAType.MS_CS.value:
profile = 'SubCA'
else:
profile = ''
options = self.options
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 "
"ipa-cacert-manage as:" % paths.IPA_CA_CSR))
@@ -299,12 +328,20 @@ class CACertManage(admintool.AdminTool):
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
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)
certmonger.resubmit_request(self.request_id, ca=ca, profile=profile,
is_ca=True)
certmonger.resubmit_request(self.request_id, ca=ca, profile=cm_profile,
template_v2=cm_template, is_ca=True)
try:
state = certmonger.wait_for_request(self.request_id, timeout)
except RuntimeError:
@@ -320,7 +357,7 @@ class CACertManage(admintool.AdminTool):
logger.debug("modifying certmonger request '%s'", self.request_id)
certmonger.modify(self.request_id,
ca='dogtag-ipa-ca-renew-agent',
profile='')
profile='', template_v2='')
def install(self):
print("Installing CA certificate, please wait")