diff options
author | Ade Lee <alee@redhat.com> | 2014-09-09 15:06:31 -0400 |
---|---|---|
committer | Ade Lee <alee@redhat.com> | 2014-10-01 12:43:59 -0400 |
commit | b644429de7d9649e98737113182d9fcd6912e92a (patch) | |
tree | 6448bc5712d3f28430870ab9c7b971eded8b7fbc /base/server | |
parent | 67f8c07d29a329f091a6c527f8d0dc9d52439cbd (diff) | |
download | pki-b644429de7d9649e98737113182d9fcd6912e92a.tar.gz pki-b644429de7d9649e98737113182d9fcd6912e92a.tar.xz pki-b644429de7d9649e98737113182d9fcd6912e92a.zip |
Fix sub-CA installation with own security domain
Installation code failed to anticipate installation of a subordinate
CA that would host its own security domain. This patch includes changes
to python installation code, java configuration servlet and
changes to man pages.
Ticket 1132
Diffstat (limited to 'base/server')
-rw-r--r-- | base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java | 224 | ||||
-rw-r--r-- | base/server/etc/default.cfg | 2 | ||||
-rw-r--r-- | base/server/man/man5/pki_default.cfg.5 | 11 | ||||
-rw-r--r-- | base/server/man/man8/pkispawn.8 | 28 | ||||
-rw-r--r-- | base/server/python/pki/server/deployment/pkihelper.py | 21 | ||||
-rw-r--r-- | base/server/python/pki/server/deployment/pkiparser.py | 11 | ||||
-rwxr-xr-x | base/server/sbin/pkispawn | 9 |
7 files changed, 201 insertions, 105 deletions
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 fa762774a..7ba345d8d 100644 --- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java +++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java @@ -222,28 +222,8 @@ public class SystemConfigService extends PKIService implements SystemConfigResou // Done Panel // Create or update security domain CMS.debug("=== Done Panel ==="); - try { - String securityDomainType = data.getSecurityDomainType(); - if (securityDomainType.equals(ConfigurationRequest.NEW_DOMAIN)) { - ConfigurationUtils.createSecurityDomain(); - } else { - ConfigurationUtils.updateSecurityDomain(); - } - cs.putString("service.securityDomainPort", CMS.getAgentPort()); - cs.putString("securitydomain.store", "ldap"); - cs.commit(false); - } catch (Exception e) { - e.printStackTrace(); - throw new PKIException("Error while updating security domain: " + e); - } - - try { - if (!data.getSharedDB()) ConfigurationUtils.setupDBUser(); - } catch (Exception e) { - CMS.debug(e); - throw new PKIException("Errors in creating or updating dbuser: " + e); - } - + setupSecurityDomain(data); + setupDBUser(data); finalizeConfiguration(data); cs.putInteger("cs.state", 1); @@ -268,6 +248,46 @@ public class SystemConfigService extends PKIService implements SystemConfigResou response.setStatus(SUCCESS); } + private void setupDBUser(ConfigurationRequest data) { + try { + if (!data.getSharedDB()) ConfigurationUtils.setupDBUser(); + } catch (Exception e) { + CMS.debug(e); + throw new PKIException("Errors in creating or updating dbuser: " + e); + } + } + + private void setupSecurityDomain(ConfigurationRequest data) { + try { + String securityDomainType = data.getSecurityDomainType(); + if (securityDomainType.equals(ConfigurationRequest.NEW_DOMAIN)) { + CMS.debug("Creating new security domain"); + ConfigurationUtils.createSecurityDomain(); + } else if (securityDomainType.equals(ConfigurationRequest.NEW_SUBDOMAIN)) { + CMS.debug("Creating subordinate CA security domain"); + + // switch out security domain parameters from issuing CA security domain + // to subordinate CA hosted security domain + cs.putString("securitydomain.name", data.getSubordinateSecurityDomainName()); + cs.putString("securitydomain.host", CMS.getEENonSSLHost()); + cs.putString("securitydomain.httpport", CMS.getEENonSSLPort()); + cs.putString("securitydomain.httpsagentport", CMS.getAgentPort()); + cs.putString("securitydomain.httpseeport", CMS.getEESSLPort()); + cs.putString("securitydomain.httpsadminport", CMS.getAdminPort()); + ConfigurationUtils.createSecurityDomain(); + } else { + CMS.debug("Updating existing security domain"); + ConfigurationUtils.updateSecurityDomain(); + } + cs.putString("service.securityDomainPort", CMS.getAgentPort()); + cs.putString("securitydomain.store", "ldap"); + cs.commit(false); + } catch (Exception e) { + e.printStackTrace(); + throw new PKIException("Error while updating security domain: " + e); + } + } + public Collection<String> getCertList(ConfigurationRequest request) { Collection<String> certList = new ArrayList<String>(); @@ -737,10 +757,10 @@ public class SystemConfigService extends PKIService implements SystemConfigResou CMS.debug("local CA selected"); url = url.substring(url.indexOf("https")); cs.putString("preop.ca.url", url); - URL urlx = new URL(url); String host = urlx.getHost(); int port = urlx.getPort(); + int admin_port = ConfigurationUtils.getPortFromSecurityDomain(domainXML, host, port, "CA", "SecurePort", "SecureAdminPort"); @@ -841,81 +861,111 @@ public class SystemConfigService extends PKIService implements SystemConfigResou String securityDomainType = data.getSecurityDomainType(); String securityDomainName = data.getSecurityDomainName(); - String securityDomainURL = data.getSecurityDomainUri(); if (securityDomainType.equals(ConfigurationRequest.NEW_DOMAIN)) { - CMS.debug("Creating new security domain"); - cs.putString("preop.securitydomain.select", "new"); - cs.putString("securitydomain.select", "new"); - cs.putString("preop.securitydomain.name", securityDomainName); - cs.putString("securitydomain.name", securityDomainName); - cs.putString("securitydomain.host", CMS.getEENonSSLHost()); - cs.putString("securitydomain.httpport", CMS.getEENonSSLPort()); - cs.putString("securitydomain.httpsagentport", CMS.getAgentPort()); - cs.putString("securitydomain.httpseeport", CMS.getEESSLPort()); - cs.putString("securitydomain.httpsadminport", CMS.getAdminPort()); - // Stand-alone PKI (Step 1) - if (data.getStandAlone()) { - cs.putString("preop.cert.subsystem.type", "remote"); - } else { - cs.putString("preop.cert.subsystem.type", "local"); - } - cs.putString("preop.cert.subsystem.profile", "subsystemCert.profile"); - + configureNewSecurityDomain(data, securityDomainName); + } else if (securityDomainType.equals(ConfigurationRequest.NEW_SUBDOMAIN)){ + CMS.debug("Configuring new subordinate root CA"); + configureNewSecurityDomain(data, data.getSubordinateSecurityDomainName()); + String securityDomainURL = data.getSecurityDomainUri(); + domainXML = logIntoSecurityDomain(data, securityDomainURL); } else { CMS.debug("Joining existing security domain"); cs.putString("preop.securitydomain.select", "existing"); cs.putString("securitydomain.select", "existing"); cs.putString("preop.cert.subsystem.type", "remote"); cs.putString("preop.cert.subsystem.profile", "caInternalAuthSubsystemCert"); + String securityDomainURL = data.getSecurityDomainUri(); + domainXML = logIntoSecurityDomain(data, securityDomainURL); + } + return domainXML; + } - CMS.debug("Getting certificate chain"); - // contact and log onto security domain - URL secdomainURL; - String host; - int port; - try { - secdomainURL = new URL(securityDomainURL); - host = secdomainURL.getHost(); - port = secdomainURL.getPort(); - cs.putString("securitydomain.host", host); - cs.putInteger("securitydomain.httpsadminport",port); - ConfigurationUtils.importCertChain(host, port, "/ca/admin/ca/getCertChain", "securitydomain"); - } catch (Exception e) { - e.printStackTrace(); - throw new PKIException("Failed to import certificate chain from security domain master: " + e); - } + private void configureNewSecurityDomain(ConfigurationRequest data, String securityDomainName) { + CMS.debug("Creating new security domain"); + cs.putString("preop.securitydomain.select", "new"); + cs.putString("securitydomain.select", "new"); + cs.putString("preop.securitydomain.name", securityDomainName); + cs.putString("securitydomain.name", securityDomainName); + cs.putString("securitydomain.host", CMS.getEENonSSLHost()); + cs.putString("securitydomain.httpport", CMS.getEENonSSLPort()); + cs.putString("securitydomain.httpsagentport", CMS.getAgentPort()); + cs.putString("securitydomain.httpseeport", CMS.getEESSLPort()); + cs.putString("securitydomain.httpsadminport", CMS.getAdminPort()); + // Stand-alone PKI (Step 1) + if (data.getStandAlone()) { + cs.putString("preop.cert.subsystem.type", "remote"); + } else { + cs.putString("preop.cert.subsystem.type", "local"); + } + cs.putString("preop.cert.subsystem.profile", "subsystemCert.profile"); + } - CMS.debug("Getting install token"); - // log onto security domain and get token - String user = data.getSecurityDomainUser(); - String pass = data.getSecurityDomainPassword(); - String installToken; - try { - installToken = ConfigurationUtils.getInstallToken(host, port, user, pass); - } catch (Exception e) { - e.printStackTrace(); - throw new PKIException("Failed to obtain installation token from security domain: " + e); - } + private String logIntoSecurityDomain(ConfigurationRequest data, String securityDomainURL) { + URL secdomainURL; + String host; + int port; + try { + CMS.debug("Resolving security domain URL" + securityDomainURL); + secdomainURL = new URL(securityDomainURL); + host = secdomainURL.getHost(); + port = secdomainURL.getPort(); + cs.putString("securitydomain.host", host); + cs.putInteger("securitydomain.httpsadminport",port); + } catch (Exception e) { + e.printStackTrace(); + throw new PKIException("Failed to resolve security domain URL"); + } - if (installToken == null) { - CMS.debug("Install token is null"); - throw new PKIException("Failed to obtain installation token from security domain"); - } - CMS.setConfigSDSessionId(installToken); + getCertChainFromSecurityDomain(host, port); + getInstallToken(data, host, port); - CMS.debug("Getting domain XML"); - try { - domainXML = ConfigurationUtils.getDomainXML(host, port, true); - ConfigurationUtils.getSecurityDomainPorts(domainXML, host, port); - } catch (Exception e) { - e.printStackTrace(); - throw new PKIException("Failed to obtain security domain decriptor from security domain master: " + e); - } + return getDomainXML(host, port); + } + + private String getDomainXML(String host, int port) { + CMS.debug("Getting domain XML"); + String domainXML = null; + try { + domainXML = ConfigurationUtils.getDomainXML(host, port, true); + ConfigurationUtils.getSecurityDomainPorts(domainXML, host, port); + } catch (Exception e) { + e.printStackTrace(); + throw new PKIException("Failed to obtain security domain decriptor from security domain master: " + e); } return domainXML; } + private void getCertChainFromSecurityDomain(String host, int port) { + CMS.debug("Getting security domain cert chain"); + try { + ConfigurationUtils.importCertChain(host, port, "/ca/admin/ca/getCertChain", "securitydomain"); + } catch (Exception e) { + e.printStackTrace(); + throw new PKIException("Failed to import certificate chain from security domain master: " + e); + } + } + + private void getInstallToken(ConfigurationRequest data, String host, int port) { + CMS.debug("Getting install token"); + // log onto security domain and get token + String user = data.getSecurityDomainUser(); + String pass = data.getSecurityDomainPassword(); + String installToken; + try { + installToken = ConfigurationUtils.getInstallToken(host, port, user, pass); + } catch (Exception e) { + e.printStackTrace(); + throw new PKIException("Failed to obtain installation token from security domain: " + e); + } + + if (installToken == null) { + CMS.debug("Install token is null"); + throw new PKIException("Failed to obtain installation token from security domain"); + } + CMS.setConfigSDSessionId(installToken); + } + public void configureSubsystem(ConfigurationRequest request, Collection<String> certList, String token, String domainXML) { @@ -1002,7 +1052,8 @@ public class SystemConfigService extends PKIService implements SystemConfigResou if (data.getSecurityDomainName() == null) { throw new BadRequestException("Security Domain Name is not provided"); } - } else if (domainType.equals(ConfigurationRequest.EXISTING_DOMAIN)) { + } else if (domainType.equals(ConfigurationRequest.EXISTING_DOMAIN) || + domainType.equals(ConfigurationRequest.NEW_SUBDOMAIN)) { if (data.getStandAlone()) { throw new BadRequestException("Existing security domains are not valid for stand-alone PKI subsytems"); } @@ -1026,6 +1077,13 @@ public class SystemConfigService extends PKIService implements SystemConfigResou throw new BadRequestException("Invalid security domain URI provided"); } + // validate subordinate CA security domain settings + if (domainType.equals(ConfigurationRequest.NEW_SUBDOMAIN)) { + if (StringUtils.isEmpty(data.getSubordinateSecurityDomainName())) { + throw new BadRequestException("Subordinate CA security domain name not provided"); + } + } + if ((data.getSubsystemName() == null) || (data.getSubsystemName().length() ==0)) { throw new BadRequestException("Invalid or no subsystem name provided"); } diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index 686cc59f9..ecf436d9f 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -366,6 +366,8 @@ pki_ocsp_signing_subject_dn=cn=CA OCSP Signing Certificate,o=%(pki_security_doma pki_ocsp_signing_token=Internal Key Storage Token pki_random_serial_numbers_enable=False pki_subordinate=False +pki_subordinate_create_new_security_domain=False +pki_subordinate_security_domain_name=%(pki_dns_domainname)s Subordinate Security Domain pki_admin_email=%(pki_admin_name)s@%(pki_dns_domainname)s pki_admin_name=%(pki_admin_uid)s pki_admin_nickname=PKI Administrator for %(pki_dns_domainname)s diff --git a/base/server/man/man5/pki_default.cfg.5 b/base/server/man/man5/pki_default.cfg.5 index 1522cc6f3..a7706656b 100644 --- a/base/server/man/man5/pki_default.cfg.5 +++ b/base/server/man/man5/pki_default.cfg.5 @@ -184,7 +184,7 @@ Name of the back-end database. It is advised that the Certificate Server have i \x'-1'\fBpki_issuing_ca_hostname, pki_issuing_ca_https_port, pki_issuing_ca_uri\fR .IP Hostname and port, or URI of the issuing CA. Required for installations of subordinate CA and non-CA subsystems. This should point to the CA that will issue the relevant system certificates for the subsystem. In a default install, this defaults to the CA subsystem within the same instance. The URI has the format https://<ca_hostname>:<ca_https_port>. - +.PP .SS MISCELLANEOUS PARAMETERS \x'-1'\fBpki_restart_configured_instance\fR .IP @@ -263,6 +263,15 @@ Required for the second step of the external CA signing process. This is the lo \x'-1'\fBpki_subordinate\fR .IP Specifies whether the new CA which will be a subordinate of another CA. The master CA is specified by \fBpki_issuing_ca\fP. Defaults to False. +.TP +.B pki_subordinate_create_new_security_domain +.IP +Set to \fBTrue\fP if the subordinate CA will host its own security domain. Defaults to \fBFalse\fP. +.TP +.B pki_subordinate_security_domain_name +.IP +Used when \fBpki_subordinate_create_security_domain\fP is set to \fBTrue\fP. Specifies the name of the security domain to be hosted on the subordinate CA. + .SS STANDALONE PKI PARAMETERS A stand-alone PKI subsystem is defined as a non-CA PKI subsystem that does not contain a CA as a part of its deployment, and functions as its own security domain. Currently, only stand-alone DRMs are supported. .TP diff --git a/base/server/man/man8/pkispawn.8 b/base/server/man/man8/pkispawn.8 index 1b8f49e4b..fc50fd380 100644 --- a/base/server/man/man8/pkispawn.8 +++ b/base/server/man/man8/pkispawn.8 @@ -304,12 +304,38 @@ pki_security_domain_user=caadmin [CA] pki_subordinate=True pki_issuing_ca=https://<master_ca_hostname>:<master_ca_https_port> -pki_ca_signing_subject_dn=cn=CA Subordinate Signing ,o=example.com +pki_ca_signing_subject_dn=cn=CA Subordinate Signing,o=example.com .fi .PP A sub-CA derives its certificate configuration -- such as allowed extensions and validity periods -- from a superior or root CA. Otherwise, the configuration of the CA is independent of the root CA, so it is its own instance rather than a clone. A sub-CA is configured using the pki_subordinate parameter and a pointer to the CA which issues the sub-CA's certificates. .PP \fBNote:\fP The value of \fBpki_ca_signing_subject_dn\fP of a subordinate CA should be different from the root CA's signing subject DN. +.SS Installing a subordinate CA which hosts its own security domain +\x'-1'\fBpkispawn \-s CA \-f myconfig.txt\fR +.PP +where \fImyconfig.txt\fP contains the following text: +.IP +.nf +[DEFAULT] +pki_admin_password=\fIpassword123\fP +pki_client_pkcs12_password=\fIpassword123\fP +pki_ds_password=\fIpassword123\fP +pki_security_domain_password=\fIpassword123\fP +pki_security_domain_hostname=<master CA security domain hostname> +pki_security_domain_https_port=<master CA security domain https port> +pki_security_domain_user=caadmin + +[CA] +pki_subordinate=True +pki_issuing_ca=https://<master ca hostname>:<master ca https port> +pki_ca_signing_subject_dn=cn=CA Subordinate Signing,o=example.com +pki_subordinate_create_new_security_domain=True +pki_subordinate_security_domain_name=Subordinate CA Security Domain +.fi +.PP +In this section, the subordinate CA logs onto and registers with the security domain CA (using parameters \fBpki_security_domain_hostname\fP, \fBpki_security_domain_https_port\fP, \fBpki_security_domain_user\fP and \fBpki_security_domain_password\fP) as in the previous section, but also creates and hosts a new security domain. To do this, \fBpki_subordinate_create_new_security_domain\fP must be set to \fBTrue\fP. The subordinate CA security domain name can also be specified by specifying a value for \fBpki_subordinate_security_domain_name\fP. +.PP +\fBNote:\fP The value of \fBpki_ca_signing_subject_dn\fP of a subordinate CA should be different from the root CA's signing subject DN. .SS Installing an externally signed CA \x'-1'\fBpkispawn \-s CA \-f myconfig.txt\fR .PP diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py index b4c728a87..96048bdec 100644 --- a/base/server/python/pki/server/deployment/pkihelper.py +++ b/base/server/python/pki/server/deployment/pkihelper.py @@ -52,7 +52,6 @@ from .pkiconfig import pki_selinux_config_ports as ports from . import pkimanifest as manifest from . import pkimessages as log from .pkiparser import PKIConfigParser -import pki.account import pki.client import pki.system @@ -503,6 +502,9 @@ class ConfigurationFile: extra=config.PKI_INDENTATION_LEVEL_2) raise Exception(log.PKI_SUBORDINATE_UNSUPPORTED_1, self.subsystem) + if config.str2bool( + self.mdict['pki_subordinate_create_new_security_domain']): + self.confirm_data_exists('pki_subordinate_security_domain_name') def confirm_external_step_two(self): # ALWAYS defined via 'pkiparser.py' @@ -3414,6 +3416,7 @@ class ConfigClient: # generic extension support in CSR - for external CA self.add_req_ext = config.str2bool( self.mdict['pki_req_ext_add']) + self.security_domain_type = self.mdict['pki_security_domain_type'] def configure_pki_data(self, data): config.pki_log.info( @@ -3626,16 +3629,15 @@ class ConfigClient: self.set_hierarchy_parameters(data) # Security Domain - if ((self.subsystem != "CA" or self.clone or self.subordinate) and - not self.standalone): - # PKI KRA, PKI OCSP, PKI RA, PKI TKS, PKI TPS, - # CA Clone, KRA Clone, OCSP Clone, TKS Clone, TPS Clone, or - # Subordinate CA + if self.security_domain_type != "new": self.set_existing_security_domain(data) else: # PKI CA, External CA, or Stand-alone PKI self.set_new_security_domain(data) + if self.subordinate: + self.set_subca_security_domain(data) + # database if self.subsystem != "RA": self.set_database_parameters(data) @@ -3943,6 +3945,13 @@ class ConfigClient: data.securityDomainType = "newdomain" data.securityDomainName = self.mdict['pki_security_domain_name'] + def set_subca_security_domain(self, data): + if config.str2bool( + self.mdict['pki_subordinate_create_new_security_domain']): + data.securityDomainType = "newsubdomain" + data.subordinateSecurityDomainName = ( + self.mdict['pki_subordinate_security_domain_name']) + def set_database_parameters(self, data): data.dsHost = self.mdict['pki_ds_hostname'] data.dsPort = self.mdict['pki_ds_ldap_port'] diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py index de224eb9a..ea6bbffab 100644 --- a/base/server/python/pki/server/deployment/pkiparser.py +++ b/base/server/python/pki/server/deployment/pkiparser.py @@ -1078,24 +1078,23 @@ class PKIConfigParser: # Stand-alone PKI self.mdict['pki_security_domain_type'] = "new" self.mdict['pki_issuing_ca'] = "External CA" - elif config.pki_subsystem != "CA" or\ - config.str2bool(self.mdict['pki_clone']) or\ - config.str2bool(self.mdict['pki_subordinate']): + elif (config.pki_subsystem != "CA" or + config.str2bool(self.mdict['pki_clone']) or + config.str2bool(self.mdict['pki_subordinate'])): # PKI KRA, PKI OCSP, PKI RA, PKI TKS, PKI TPS, - # CA Clone, KRA Clone, OCSP Clone, TKS Clone, TPS Clone, or + # CA Clone, KRA Clone, OCSP Clone, TKS Clone, TPS Clone # Subordinate CA self.mdict['pki_security_domain_type'] = "existing" self.mdict['pki_security_domain_uri'] = \ "https" + "://" + \ self.mdict['pki_security_domain_hostname'] + ":" + \ self.mdict['pki_security_domain_https_port'] - elif config.str2bool(self.mdict['pki_external']): # External CA self.mdict['pki_security_domain_type'] = "new" self.mdict['pki_issuing_ca'] = "External CA" else: - # PKI CA + # PKI CA (master) self.mdict['pki_security_domain_type'] = "new" # 'External CA' Configuration name/value pairs diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn index 4b939743a..04eec6ab9 100755 --- a/base/server/sbin/pkispawn +++ b/base/server/sbin/pkispawn @@ -464,14 +464,7 @@ def main(argv): e.message['desc'] sys.exit(1) - if ((config.pki_subsystem == "KRA" or - config.pki_subsystem == "OCSP") and - not config.str2bool(parser.mdict['pki_standalone'])) or\ - config.pki_subsystem == "TKS" or\ - config.pki_subsystem == "TPS" or\ - config.str2bool(parser.mdict['pki_clone']) or\ - (config.pki_subsystem == "CA" and - config.str2bool(parser.mdict['pki_subordinate'])): + if parser.mdict['pki_security_domain_type'] != "new": try: # Verify existence of Security Domain Password if not 'pki_security_domain_password' in parser.mdict or\ |