diff options
author | Christina Fu <cfu@redhat.com> | 2015-04-15 10:58:08 -0700 |
---|---|---|
committer | Christina Fu <cfu@redhat.com> | 2015-04-21 18:24:32 -0700 |
commit | e2683d6a8f6211ac58a5674aaa626814f26ebbf2 (patch) | |
tree | cb6e9fae0990b334ee1acd6333f8ef46594994e8 /base | |
parent | 79c5627ae28840756d99928fd33701552cc93322 (diff) | |
download | pki-e2683d6a8f6211ac58a5674aaa626814f26ebbf2.tar.gz pki-e2683d6a8f6211ac58a5674aaa626814f26ebbf2.tar.xz pki-e2683d6a8f6211ac58a5674aaa626814f26ebbf2.zip |
Ticket 1316 Allow adding SAN to server cert during the install process
Usage:
* under /usr/share/pki/ca/conf, you will find a new file called
serverCert.profile.exampleWithSANpattern
* copy existing serverCert.profile away and replace with
serverCert.profile.exampleWithSANpattern
* edit serverCert.profile.exampleWithSANpattern
- follow the instruction right above 8.default.
- save and quit
* cd /usr/share/pki/ca/profiles/ca , edit caInternalAuthServerCert.cfg
- follow the instruction right above policyset.serverCertSet.9
- save and quit
* save away and edit the ca config file for pkispawn: (note: you can
add multiple SAN's delimited by ',' for pki_san_server_cert
- add the following lines, e.g.
pki_san_inject=True
pki_san_server_cert=host1.Example.com
- do the same pkispawn cfg changes for kra or any other instances
that you plan on creating
* create your instance(s)
check the sl sever cert, it should contain something like the
following:
Identifier: Subject Alternative Name - 2.5.29.17
Critical: no
Value:
DNSName: host1.Example.com
Diffstat (limited to 'base')
10 files changed, 239 insertions, 10 deletions
diff --git a/base/ca/shared/conf/serverCert.profile.exampleWithSANpattern b/base/ca/shared/conf/serverCert.profile.exampleWithSANpattern new file mode 100644 index 000000000..5ca44270e --- /dev/null +++ b/base/ca/shared/conf/serverCert.profile.exampleWithSANpattern @@ -0,0 +1,68 @@ +# +# Server Certificate +# +id=serverCert.profile +name=All Purpose SSL server cert Profile +description=This profile creates an SSL server certificate that is valid for SSL servers +profileIDMapping=caServerCert +profileSetIDMapping=serverCertSet +list=2,4,5,6,7,8 +2.default.class=com.netscape.cms.profile.def.ValidityDefault +2.default.name=Validity Default +2.default.params.range=720 +2.default.params.startTime=0 +4.default.class=com.netscape.cms.profile.def.AuthorityKeyIdentifierExtDefault +4.default.name=Authority Key Identifier Default +5.default.class=com.netscape.cms.profile.def.AuthInfoAccessExtDefault +5.default.name=AIA Extension Default +5.default.params.authInfoAccessADEnable_0=true +5.default.params.authInfoAccessADLocationType_0=URIName +5.default.params.authInfoAccessADLocation_0= +5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 +5.default.params.authInfoAccessCritical=false +5.default.params.authInfoAccessNumADs=1 +6.default.class=com.netscape.cms.profile.def.KeyUsageExtDefault +6.default.name=Key Usage Default +6.default.params.keyUsageCritical=true +6.default.params.keyUsageDigitalSignature=true +6.default.params.keyUsageNonRepudiation=true +6.default.params.keyUsageDataEncipherment=true +6.default.params.keyUsageKeyEncipherment=true +6.default.params.keyUsageKeyAgreement=false +6.default.params.keyUsageKeyCertSign=false +6.default.params.keyUsageCrlSign=false +6.default.params.keyUsageEncipherOnly=false +6.default.params.keyUsageDecipherOnly=false +7.default.class=com.netscape.cms.profile.def.ExtendedKeyUsageExtDefault +7.default.name=Extended Key Usage Extension Default +7.default.params.exKeyUsageCritical=false +7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.1 +# allows SAN to be specified from client side +# need to: +# 1. add 8 to list above +# 2. change below to reflect the number of general names, and +# turn each corresponding subjAltExtPattern_<num> to true +# 8.default.params.subjAltNameNumGNs +8.default.class=com.netscape.cms.profile.def.SubjectAltNameExtDefault +8.default.name=Subject Alternative Name Extension Default +8.default.params.subjAltExtGNEnable_0=true +8.default.params.subjAltExtPattern_0=$request.req_san_pattern_0$ +8.default.params.subjAltExtType_0=DNSName +8.default.params.subjAltExtGNEnable_1=true +8.default.params.subjAltExtPattern_1=$request.req_san_pattern_1$ +8.default.params.subjAltExtType_1=DNSName +8.default.params.subjAltExtGNEnable_2=true +8.default.params.subjAltExtPattern_2=$request.req_san_pattern_2$ +8.default.params.subjAltExtType_2=DNSName +8.default.params.subjAltExtGNEnable_3=true +8.default.params.subjAltExtPattern_3=$request.req_san_pattern_3$ +8.default.params.subjAltExtType_3=DNSName +8.default.params.subjAltExtType_4=OtherName +8.default.params.subjAltExtSource_4=UUID4 +8.default.params.subjAltExtPattern_4=(IA5String)1.2.3.4,$server.source$ +8.default.params.subjAltExtGNEnable_4=true +8.default.params.subjAltExtType_5=DNSName +8.default.params.subjAltExtPattern_5=myhost.example.com +8.default.params.subjAltExtGNEnable_5=true +8.default.params.subjAltNameExtCritical=false +8.default.params.subjAltNameNumGNs=6 diff --git a/base/ca/shared/profiles/ca/caInternalAuthServerCert.cfg b/base/ca/shared/profiles/ca/caInternalAuthServerCert.cfg index 719351080..f145325f0 100644 --- a/base/ca/shared/profiles/ca/caInternalAuthServerCert.cfg +++ b/base/ca/shared/profiles/ca/caInternalAuthServerCert.cfg @@ -8,6 +8,7 @@ name=Security Domain Server Certificate Enrollment input.list=i1,i2 input.i1.class_id=certReqInputImpl input.i2.class_id=submitterInfoInputImpl +input.i3.class_id=subjectAltNameExtInputImpl output.list=o1 output.o1.class_id=certOutputImpl policyset.list=serverCertSet @@ -84,3 +85,25 @@ policyset.serverCertSet.8.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA25 policyset.serverCertSet.8.default.class_id=signingAlgDefaultImpl policyset.serverCertSet.8.default.name=Signing Alg policyset.serverCertSet.8.default.params.signingAlg=- +# allows SAN to be specified from client side +# need to: +# 1. add i3 to input.list above +# 2. add 9 to policyset.serverCertSet.list above +# 3. change below to reflect the number of general names, and +# turn each corresponding subjAltExtPattern_<num> to true +# policyset.serverCertSet.9.default.params.subjAltNameNumGNs +policyset.serverCertSet.9.constraint.class_id=noConstraintImpl +policyset.serverCertSet.9.constraint.name=No Constraint +policyset.serverCertSet.9.default.class_id=subjectAltNameExtDefaultImpl +policyset.serverCertSet.9.default.name=Subject Alternative Name Extension Default +policyset.serverCertSet.9.default.params.subjAltExtGNEnable_0=true +policyset.serverCertSet.9.default.params.subjAltExtPattern_0=$request.req_san_pattern_0$ +policyset.serverCertSet.9.default.params.subjAltExtType_0=DNSName +policyset.serverCertSet.9.default.params.subjAltExtGNEnable_1=false +policyset.serverCertSet.9.default.params.subjAltExtPattern_1=$request.req_san_pattern_1$ +policyset.serverCertSet.9.default.params.subjAltExtType_1=DNSName +policyset.serverCertSet.9.default.params.subjAltExtGNEnable_2=false +policyset.serverCertSet.9.default.params.subjAltExtPattern_2=$request.req_san_pattern_2$ +policyset.serverCertSet.9.default.params.subjAltExtType_2=DNSName +policyset.serverCertSet.9.default.params.subjAltNameExtCritical=false +policyset.serverCertSet.9.default.params.subjAltNameNumGNs=1 diff --git a/base/common/src/com/netscape/certsrv/system/SystemCertData.java b/base/common/src/com/netscape/certsrv/system/SystemCertData.java index 064d8e190..89fb8cb8f 100644 --- a/base/common/src/com/netscape/certsrv/system/SystemCertData.java +++ b/base/common/src/com/netscape/certsrv/system/SystemCertData.java @@ -46,6 +46,7 @@ public class SystemCertData { public static final String REQUEST_EXT_OID = "req_ext_oid"; public static final String REQUEST_EXT_CRITICAL = "req_ext_critial"; public static final String REQUEST_EXT_DATA = "req_ext_data"; + public static final String SERVER_CERT_SAN = "san_for_server_cert"; @XmlElement protected String tag; @@ -92,6 +93,9 @@ public class SystemCertData { @XmlElement protected String req_ext_data; + @XmlElement + protected String san_for_server_cert; + public SystemCertData() { // required for JAXB } @@ -113,6 +117,8 @@ public class SystemCertData { req_ext_oid = form.getFirst(REQUEST_EXT_OID); req_ext_critical = form.getFirst(REQUEST_EXT_CRITICAL); req_ext_data = form.getFirst(REQUEST_EXT_DATA); + //support SAN in server cert + san_for_server_cert = form.getFirst(SERVER_CERT_SAN); } /** @@ -307,4 +313,11 @@ public class SystemCertData { return false; } + /** + * @return the server cert SAN + */ + public String getServerCertSAN() { + return san_for_server_cert; + } + } diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java index 240f86a13..ca3d05f25 100644 --- a/base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java +++ b/base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java @@ -450,6 +450,7 @@ public class SubjectAltNameExtDefault extends EnrollExtDefault { if (!pattern.equals("")) { CMS.debug("SubjectAltNameExtDefault: createExtension() pattern="+ pattern); String gname = ""; + String gtype = ""; // cfu - see if this is server-generated (e.g. UUID4) // to use this feature, use $server.source$ in pattern @@ -479,16 +480,18 @@ public class SubjectAltNameExtDefault extends EnrollExtDefault { } else { if (request != null) { gname = mapPattern(request, pattern); + gtype = mapPattern(request, type); } } - if (gname.equals("") || gname.contains("$")) { - CMS.debug("ubjectAltNameExtDefault: mapPattern()failed. Not added. gname="+ gname); + if (gname.equals("") || + gname.startsWith(CONFIG_SAN_REQ_PATTERN_PREFIX)) { + CMS.debug("SubjectAltNameExtDefault: gname is empty,not added."); continue; } - CMS.debug("SubjectAltNameExtDefault: createExtension got gname=" + gname); + CMS.debug("SubjectAltNameExtDefault: createExtension got gname=" +gname + " with type=" + gtype); - GeneralNameInterface n = parseGeneralName(type + ":" + gname); + GeneralNameInterface n = parseGeneralName(gtype + ":" + gname); CMS.debug("adding gname: " + gname); if (n != null) { diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java index 22f092973..36b0e4d0d 100644 --- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java +++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java @@ -206,6 +206,85 @@ public class CertUtil { } } + + // Dynamically inject the SubjectAlternativeName extension to a + // local/self-signed master CA's request for its SSL Server Certificate. + // + // Since this information may vary from instance to + // instance, obtain the necessary information from the + // 'service.sslserver.san' value(s) in the instance's + // CS.cfg, process these values converting each item into + // its individual SubjectAlternativeName components, and + // inject these values into the local request. + // + public static void injectSANextensionIntoRequest(IConfigStore config, + IRequest req) throws Exception { + CMS.debug("CertUtil::injectSANextensionIntoRequest() - injecting SAN " + + "entries into request . . ."); + int i = 0; + if (config == null || req == null) { + throw new EBaseException("injectSANextensionIntoRequest: parameters config and req cannot be null"); + } + String sanHostnames = config.getString("service.sslserver.san"); + String sans[] = StringUtils.split(sanHostnames, ","); + for (String san : sans) { + CMS.debug("CertUtil: injectSANextensionIntoRequest() injecting " + + "SAN hostname: " + san); + req.setExtData("req_san_pattern_" + i, san); + i++; + } + CMS.debug("CertUtil: injectSANextensionIntoRequest() " + "injected " + + i + " SAN entries into request."); + } + + // Dynamically apply the SubjectAlternativeName extension to a + // remote PKI instance's request for its SSL Server Certificate. + // + // Since this information may vary from instance to + // instance, obtain the necessary information from the + // 'service.sslserver.san' value(s) in the instance's + // CS.cfg, process these values converting each item into + // its individual SubjectAlternativeName components, and + // build an SSL Server Certificate URL extension consisting + // of this information. + // + // 03/27/2013 - Should consider removing this + // "buildSANSSLserverURLExtension()" + // method if it becomes possible to + // embed a certificate extension into + // a PKCS #10 certificate request. + // + public static String buildSANSSLserverURLExtension(IConfigStore config) + throws Exception { + String url = ""; + String entries = ""; + + CMS.debug("CertUtil: buildSANSSLserverURLExtension() " + + "building SAN SSL Server Certificate URL extension . . ."); + int i = 0; + if (config == null) { + throw new EBaseException("injectSANextensionIntoRequest: parameter config cannot be null"); + } + String sanHostnames = config.getString("service.sslserver.san"); + String sans[] = StringUtils.split(sanHostnames, ","); + for (String san : sans) { + CMS.debug("CertUtil: buildSANSSLserverURLExtension() processing " + + "SAN hostname: " + san); + // Add the DNSName for all SANs + entries = entries + + "&req_san_pattern_" + i + "=" + san; + i++; + } + + url = "&req_san_entries=" + i + entries; + + CMS.debug("CertUtil: buildSANSSLserverURLExtension() " + "placed " + + i + " SAN entries into SSL Server Certificate URL."); + + return url; + } + + /* * create requests so renewal can work on these initial certs */ @@ -375,6 +454,9 @@ public class CertUtil { IRequest req = null; try { + Boolean injectSAN = config.getBoolean( + "service.injectSAN", false); + CMS.debug("createLocalCert: injectSAN=" + injectSAN); String dn = config.getString(prefix + certTag + ".dn"); String keyAlgorithm = null; Date date = new Date(); @@ -426,6 +508,10 @@ public class CertUtil { queue = ca.getRequestQueue(); if (queue != null) { req = createLocalRequest(queue, serialNo.toString(), info); + if (certTag.equals("sslserver") && + injectSAN == true) { + injectSANextensionIntoRequest(config, req); + } CMS.debug("CertUtil profile name= " + profile); req.setExtData("req_key", x509key.toString()); @@ -498,7 +584,7 @@ public class CertUtil { } } catch (Exception e) { CMS.debug(e); - CMS.debug("NamePanel configCert() exception caught:" + e.toString()); + CMS.debug("CertUtil createLocalCert() exception caught:" + e.toString()); } if (cr == null) { @@ -520,22 +606,22 @@ public class CertUtil { cert.getSerialNumber(), cert, meta); } catch (Exception e) { CMS.debug( - "NamePanel configCert: failed to add metainfo. Exception: " + e.toString()); + "CertUtil createLocalCert: failed to add metainfo. Exception: " + e.toString()); } try { cr.addCertificateRecord(record); CMS.debug( - "NamePanel configCert: finished adding certificate record."); + "CertUtil createLocalCert: finished adding certificate record."); } catch (Exception e) { CMS.debug( - "NamePanel configCert: failed to add certificate record. Exception: " + "CertUtil createLocalCert: failed to add certificate record. Exception: " + e.toString()); try { cr.deleteCertificateRecord(record.getSerialNumber()); cr.addCertificateRecord(record); } catch (Exception ee) { - CMS.debug("NamePanel update: Exception: " + ee.toString()); + CMS.debug("CertUtil createLocalCert: Exception: " + ee.toString()); } } diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java index 21aaf203b..1765ba7a6 100644 --- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java @@ -2492,11 +2492,22 @@ public class ConfigurationUtils { } catch (Exception ee) { } + String sslserver_extension = ""; + Boolean injectSAN = config.getBoolean( + "service.injectSAN", false); + CMS.debug("ConfigurationUtils: injectSAN="+injectSAN); + if (certTag.equals("sslserver") && + injectSAN == true) { + sslserver_extension = + CertUtil.buildSANSSLserverURLExtension(config); + } + String content = "requestor_name=" + sysType + "-" + machineName + "-" + securePort + "&profileId=" + profileId + "&cert_request_type=pkcs10&cert_request=" + URLEncoder.encode(pkcs10, "UTF-8") - + "&xmlOutput=true&sessionID=" + session_id; + + "&xmlOutput=true&sessionID=" + session_id + + sslserver_extension; cert = CertUtil.createRemoteCert(ca_hostname, ca_port, content, response, panel); if (cert == null) { diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java index 7067c24ec..12dd54dac 100644 --- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java +++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java @@ -410,6 +410,16 @@ public class SystemConfigService extends PKIService implements SystemConfigResou cs.putString("preop.cert." + tag + ".signingalgorithm", signingalgorithm); cs.putString("preop.cert." + tag + ".nickname", nickname); cs.putString("preop.cert." + tag + ".dn", dn); + + // support injecting SAN into server cert + if ( tag.equals("sslserver") && certData.getServerCertSAN() != null) { + CMS.debug("updateConfiguration(): san_server_cert found"); + cs.putString("service.injectSAN", "true"); + cs.putString("service.sslserver.san", certData.getServerCertSAN()); + } else { + if ( tag.equals("sslserver")) + CMS.debug("SystemConfigService:processCerts(): san_server_cert not found for tag sslserver"); + } cs.commit(false); if (!request.getStepTwo()) { diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index 50117a20e..3f7af5ebd 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -104,6 +104,9 @@ pki_security_domain_https_port=8443 pki_security_domain_name=%(pki_dns_domainname)s Security Domain pki_security_domain_password= pki_security_domain_user=caadmin +#for supporting server cert SAN injection +pki_san_inject=False +pki_san_for_server_cert= pki_skip_configuration=False pki_skip_installation=False pki_ssl_server_key_algorithm=SHA256withRSA diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py index 7f46c1f8b..884215e85 100644 --- a/base/server/python/pki/server/deployment/pkihelper.py +++ b/base/server/python/pki/server/deployment/pkihelper.py @@ -463,6 +463,11 @@ class ConfigurationFile: self.mdict['pki_skip_configuration']) self.standalone = config.str2bool(self.mdict['pki_standalone']) self.subordinate = config.str2bool(self.mdict['pki_subordinate']) + # server cert san injection support + self.san_inject = config.str2bool(self.mdict['pki_san_inject']) + if self.san_inject: + self.confirm_data_exists('pki_san_for_server_cert') + self.san_for_server_cert = self.mdict['pki_san_for_server_cert'] # set useful 'string' object variables for this class self.subsystem = self.mdict['pki_subsystem'] @@ -3637,6 +3642,7 @@ class ConfigClient: self.add_req_ext = config.str2bool( self.mdict['pki_req_ext_add']) self.security_domain_type = self.mdict['pki_security_domain_type'] + self.san_inject = config.str2bool(self.mdict['pki_san_inject']) def configure_pki_data(self, data): config.pki_log.info( @@ -4335,6 +4341,9 @@ class ConfigClient: cert.nickname = self.mdict["pki_%s_nickname" % tag] cert.subjectDN = self.mdict["pki_%s_subject_dn" % tag] cert.token = self.mdict["pki_%s_token" % tag] + if tag == 'ssl_server' and self.san_inject: + cert.san_for_server_cert = \ + self.mdict['pki_san_for_server_cert'] return cert def retrieve_existing_server_cert(self, cfg_file): diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py index e37b0e4a5..e93f1717e 100644 --- a/base/server/python/pki/server/deployment/pkiparser.py +++ b/base/server/python/pki/server/deployment/pkiparser.py @@ -588,6 +588,9 @@ class PKIConfigParser: if not 'pki_subordinate' in self.mdict or\ not len(self.mdict['pki_subordinate']): self.mdict['pki_subordinate'] = "false" + if not 'pki_san_inject' in self.mdict or\ + not len(self.mdict['pki_san_inject']): + self.mdict['pki_san_inject'] = "false" # PKI Target (slot substitution) name/value pairs self.mdict['pki_target_cs_cfg'] = \ |