summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEndi S. Dewata <edewata@redhat.com>2016-02-19 08:42:30 +0100
committerEndi S. Dewata <edewata@redhat.com>2016-04-02 06:22:41 +0200
commit58406095925cd3d26ab8eab0c7c7e99cdddf21ea (patch)
tree2b07bdc6952c06b86b257cbb99b3f361172f5245
parent9667921a5a2489a3fccc6f4f7f7af88f60eadbd2 (diff)
downloadpki-58406095925cd3d26ab8eab0c7c7e99cdddf21ea.tar.gz
pki-58406095925cd3d26ab8eab0c7c7e99cdddf21ea.tar.xz
pki-58406095925cd3d26ab8eab0c7c7e99cdddf21ea.zip
Added mechanism to import system certs via PKCS #12 file.
The installation tool has been modified to provide an optional pki_server_pkcs12_path property to specify a PKCS #12 file containing certificate chain, system certificates, and third-party certificates needed by the subsystem being installed. If the pki_server_pkcs12_path is specified the installation tool will no longer download the certificate chain from the security domain directly, and it will no longer import the PKCS #12 containing the entire master NSS database specified in pki_clone_pkcs12_path. For backward compatibility, if the pki_server_pkcs12_path is not specified the installation tool will use the old mechanism to import the system certificates. The ConfigurationUtils.verifySystemCertificates() has been modified not to catch the exception to help troubleshooting. https://fedorahosted.org/pki/ticket/1742
-rw-r--r--base/common/python/pki/nssdb.py16
-rw-r--r--base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java32
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java76
-rw-r--r--base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java55
-rw-r--r--base/server/etc/default.cfg3
-rw-r--r--base/server/python/pki/server/deployment/pkihelper.py36
-rw-r--r--base/server/python/pki/server/deployment/pkiparser.py6
-rw-r--r--base/server/python/pki/server/deployment/scriptlets/security_databases.py27
8 files changed, 163 insertions, 88 deletions
diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py
index 219d824fd..3b34805b1 100644
--- a/base/common/python/pki/nssdb.py
+++ b/base/common/python/pki/nssdb.py
@@ -489,14 +489,20 @@ class NSSDatabase(object):
raise Exception('Missing PKCS #12 password')
cmd = [
- 'pk12util',
+ 'pki',
'-d', self.directory,
- '-h', self.token,
- '-k', self.password_file,
- '-i', pkcs12_file,
- '-w', password_file
+ '-C', self.password_file
]
+ if self.token and self.token != 'internal':
+ cmd.extend(['--token', self.token])
+
+ cmd.extend([
+ 'pkcs12-import',
+ '--pkcs12', pkcs12_file,
+ '--pkcs12-password-file', password_file
+ ])
+
subprocess.check_call(cmd)
finally:
diff --git a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java
index 8c9da6f37..890f7d01f 100644
--- a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java
+++ b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java
@@ -133,6 +133,9 @@ public class ConfigurationRequest {
protected String reindexData;
@XmlElement
+ protected Boolean systemCertsImported;
+
+ @XmlElement
protected List<SystemCertData> systemCerts;
@XmlElement
@@ -559,21 +562,37 @@ public class ConfigurationRequest {
/**
*
- * @return systemCerts
+ * @return systemCertsImported
*/
- public List<SystemCertData> getSystemCerts() {
- return systemCerts;
+ public Boolean getSystemCertsImported() {
+ return systemCertsImported;
}
/**
*
- * @param systemCerts
+ * @param systemCertsImported
*/
- public void setSystemCerts(List<SystemCertData> systemCerts) {
- this.systemCerts = systemCerts;
+ public void setSystemCertsImported(Boolean systemCertsImported) {
+ this.systemCertsImported = systemCertsImported;
}
/**
+ *
+ * @return systemCerts
+ */
+ public List<SystemCertData> getSystemCerts() {
+ return systemCerts;
+ }
+
+ /**
+ *
+ * @param systemCerts
+ */
+ public void setSystemCerts(List<SystemCertData> systemCerts) {
+ this.systemCerts = systemCerts;
+ }
+
+ /**
* @return the issuingCA
*/
public String getIssuingCA() {
@@ -940,6 +959,7 @@ public class ConfigurationRequest {
", masterReplicationPort=" + masterReplicationPort +
", cloneReplicationPort=" + cloneReplicationPort +
", replicationSecurity=" + replicationSecurity +
+ ", systemCertsImported=" + systemCertsImported +
", systemCerts=" + systemCerts +
", issuingCA=" + issuingCA +
", backupKeys=" + backupKeys +
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 32e10275f..ad2853d14 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
@@ -252,6 +252,8 @@ public class ConfigurationUtils {
public static void importCertChain(String host, int port, String serverPath, String tag)
throws Exception {
+ CMS.debug("ConfigurationUtils.importCertChain()");
+
IConfigStore cs = CMS.getConfigStore();
ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback();
String c = get(host, port, true, serverPath, null, certApprovalCallback);
@@ -950,44 +952,42 @@ public class ConfigurationUtils {
importKeyCert(pkeyinfo_collection, cert_collection);
}
- public static boolean isCertdbCloned() {
+ public static void verifySystemCertificates() throws Exception {
+
IConfigStore cs = CMS.getConfigStore();
- try {
- CryptoManager cm = CryptoManager.getInstance();
- String certList = cs.getString("preop.cert.list");
- String cstype = cs.getString("cs.type").toLowerCase();
- StringTokenizer st = new StringTokenizer(certList, ",");
- while (st.hasMoreTokens()) {
- String tag = st.nextToken();
- if (tag.equals("sslserver"))
- continue;
- String tokenname = cs.getString("preop.module.token", "");
- cm.getTokenByName(tokenname); // throw exception if token doesn't exist
- String name1 = "preop.master." + tag + ".nickname";
- String nickname = cs.getString(name1, "");
- if (!tokenname.equals("Internal Key Storage Token") &&
- !tokenname.equals("internal"))
- nickname = tokenname + ":" + nickname;
-
- CMS.debug("ConfigurationUtils.isCertdbCloned(): checking system certificate " + nickname);
-
- // TODO : remove this when we eliminate the extraneous nicknames
- // needed for self tests
- cs.putString(cstype + ".cert." + tag + ".nickname", nickname);
-
- X509Certificate cert = cm.findCertByNickname(nickname);
- if (cert == null) {
- CMS.debug("Missing system certificate: " + nickname);
- return false;
- }
- }
- } catch (Exception e) {
- CMS.debug(e);
- return false;
- }
+ CryptoManager cm = CryptoManager.getInstance();
+ String certList = cs.getString("preop.cert.list");
+ String cstype = cs.getString("cs.type").toLowerCase();
+ StringTokenizer st = new StringTokenizer(certList, ",");
- return true;
+ while (st.hasMoreTokens()) {
+ String tag = st.nextToken();
+ if (tag.equals("sslserver"))
+ continue;
+
+ String tokenname = cs.getString("preop.module.token", "");
+ cm.getTokenByName(tokenname); // throw exception if token doesn't exist
+
+ String name1 = "preop.master." + tag + ".nickname";
+ String nickname = cs.getString(name1, "");
+ if (!tokenname.equals("Internal Key Storage Token") &&
+ !tokenname.equals("internal"))
+ nickname = tokenname + ":" + nickname;
+
+ CMS.debug("ConfigurationUtils.verifySystemCertificates(): checking certificate " + nickname);
+
+ // TODO : remove this when we eliminate the extraneous nicknames
+ // needed for self tests
+ cs.putString(cstype + ".cert." + tag + ".nickname", nickname);
+
+ try {
+ cm.findCertByNickname(nickname);
+
+ } catch (ObjectNotFoundException e) {
+ throw new Exception("Missing system certificate: " + nickname);
+ }
+ }
}
public static void importKeyCert(
@@ -3684,10 +3684,12 @@ public class ConfigurationUtils {
String status = parser.getValue("Status");
CMS.debug("submitAdminXertRequest: status=" + status);
if (status.equals(AUTH_FAILURE)) {
- throw new EAuthException(AUTH_FAILURE);
+ throw new EAuthException("Unable to generate admin certificate: authentication failure");
+
} else if (!status.equals(SUCCESS)) {
String error = parser.getValue("Error");
- throw new IOException(error);
+ CMS.debug("Error: " + error);
+ throw new IOException("Unable to generate admin certificate: " + error);
}
IConfigStore cs = CMS.getConfigStore();
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 697196a6e..f7e5a6b05 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java
@@ -662,7 +662,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
response.setAdminCert(admincerts[0]);
} catch (Exception e) {
- e.printStackTrace();
+ CMS.debug(e);
throw new PKIException("Error in creating admin user: " + e);
}
}
@@ -818,7 +818,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
cs.putInteger("preop.ca.httpsport", port);
cs.putInteger("preop.ca.httpsadminport", admin_port);
- if (!data.isClone()) {
+ if (!data.isClone() && !data.getSystemCertsImported()) {
ConfigurationUtils.importCertChain(host, admin_port, "/ca/admin/ca/getCertChain", "ca");
}
@@ -855,7 +855,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
"Clone URI does not match available subsystems: " + url);
}
- if (csType.equals("CA")) {
+ if (csType.equals("CA") && !data.getSystemCertsImported()) {
CMS.debug("SystemConfigService: import certificate chain from master");
int masterAdminPort = ConfigurationUtils.getPortFromSecurityDomain(domainXML,
masterHost, masterPort, "CA", "SecurePort", "SecureAdminPort");
@@ -867,10 +867,12 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
ConfigurationUtils.getConfigEntriesFromMaster();
if (token.equals(ConfigurationRequest.TOKEN_DEFAULT)) {
- CMS.debug("SystemConfigService: restore certificates from P12 file");
- String p12File = data.getP12File();
- String p12Pass = data.getP12Password();
- ConfigurationUtils.restoreCertsFromP12(p12File, p12Pass);
+ if (!data.getSystemCertsImported()) {
+ CMS.debug("SystemConfigService: restore certificates from P12 file");
+ String p12File = data.getP12File();
+ String p12Pass = data.getP12Password();
+ ConfigurationUtils.restoreCertsFromP12(p12File, p12Pass);
+ }
} else {
CMS.debug("SystemConfigService: import certificates from HSM and set permission");
@@ -878,15 +880,10 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
}
CMS.debug("SystemConfigService: verify certificates");
- boolean cloneReady = ConfigurationUtils.isCertdbCloned();
-
- if (!cloneReady) {
- CMS.debug("SystemConfigService: clone does not have all the certificates.");
- throw new PKIException("Clone does not have all the required certificates");
- }
+ ConfigurationUtils.verifySystemCertificates();
}
- public String configureSecurityDomain(ConfigurationRequest data) {
+ public String configureSecurityDomain(ConfigurationRequest data) throws Exception {
String domainXML = null;
@@ -932,7 +929,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
cs.putString("preop.cert.subsystem.profile", "subsystemCert.profile");
}
- private String logIntoSecurityDomain(ConfigurationRequest data, String securityDomainURL) {
+ private String logIntoSecurityDomain(ConfigurationRequest data, String securityDomainURL) throws Exception {
URL secdomainURL;
String host;
int port;
@@ -948,7 +945,11 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
throw new PKIException("Failed to resolve security domain URL", e);
}
- getCertChainFromSecurityDomain(host, port);
+ if (!data.getSystemCertsImported()) {
+ CMS.debug("Getting security domain cert chain");
+ ConfigurationUtils.importCertChain(host, port, "/ca/admin/ca/getCertChain", "securitydomain");
+ }
+
getInstallToken(data, host, port);
return getDomainXML(host, port);
@@ -967,16 +968,6 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
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) {
- CMS.debug(e);
- throw new PKIException("Failed to import certificate chain from security domain master: " + e, e);
- }
- }
-
private void getInstallToken(ConfigurationRequest data, String host, int port) {
CMS.debug("Getting install token");
// log onto security domain and get token
@@ -1129,12 +1120,14 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
}
if (data.getToken().equals(ConfigurationRequest.TOKEN_DEFAULT)) {
- if (data.getP12File() == null) {
- throw new BadRequestException("P12 filename not provided");
- }
+ if (!data.getSystemCertsImported()) {
+ if (data.getP12File() == null) {
+ throw new BadRequestException("P12 filename not provided");
+ }
- if (data.getP12Password() == null) {
- throw new BadRequestException("P12 password not provided");
+ if (data.getP12Password() == null) {
+ throw new BadRequestException("P12 password not provided");
+ }
}
} else {
if (data.getP12File() != null) {
diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg
index 1c1ae92b3..c503e6345 100644
--- a/base/server/etc/default.cfg
+++ b/base/server/etc/default.cfg
@@ -27,6 +27,7 @@ sensitive_parameters=
pki_pin
pki_replication_password
pki_security_domain_password
+ pki_server_pkcs12_password
pki_token_password
# The spawn_scriplets contains a list of scriplets to be executed by pkispawn.
@@ -108,6 +109,8 @@ 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
+pki_server_pkcs12_path=
+pki_server_pkcs12_password=
#for supporting server cert SAN injection
pki_san_inject=False
pki_san_for_server_cert=
diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index e8591398d..ab6562ba0 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -619,10 +619,17 @@ class ConfigurationFile:
self.confirm_data_exists("pki_client_database_password")
# Verify existence of Client PKCS #12 Password for Admin Cert
self.confirm_data_exists("pki_client_pkcs12_password")
+
if self.clone:
+
# Verify existence of PKCS #12 Password (ONLY for non-HSM Clones)
if not config.str2bool(self.mdict['pki_hsm_enable']):
- self.confirm_data_exists("pki_clone_pkcs12_password")
+
+ # If system certificates are already provided via pki_server_pkcs12
+ # there's no need to provide pki_clone_pkcs12.
+ if not self.mdict['pki_server_pkcs12_path']:
+ self.confirm_data_exists("pki_clone_pkcs12_password")
+
# Verify absence of all PKCS #12 clone parameters for HSMs
elif (os.path.exists(self.mdict['pki_clone_pkcs12_path']) or
('pki_clone_pkcs12_password' in self.mdict and
@@ -632,6 +639,7 @@ class ConfigurationFile:
extra=config.PKI_INDENTATION_LEVEL_2)
raise Exception(
log.PKIHELPER_HSM_CLONES_MUST_SHARE_HSM_MASTER_PRIVATE_KEYS)
+
# Verify existence of Security Domain Password
# (ONLY for PKI KRA, PKI OCSP, PKI TKS, PKI TPS, Clones, or
# Subordinate CA that will be automatically configured and
@@ -736,11 +744,18 @@ class ConfigurationFile:
self.confirm_data_exists("pki_http_port")
self.confirm_data_exists("pki_https_port")
self.confirm_data_exists("pki_tomcat_server_port")
+
+ # Check clone parameters for non-HSM clone
if not config.str2bool(self.mdict['pki_hsm_enable']):
- # Check clone parameters for non-HSM clone
- self.confirm_data_exists("pki_clone_pkcs12_path")
- self.confirm_file_exists("pki_clone_pkcs12_path")
+
+ # If system certificates are already provided via pki_server_pkcs12
+ # there's no need to provide pki_clone_pkcs12.
+ if not self.mdict['pki_server_pkcs12_path']:
+ self.confirm_data_exists("pki_clone_pkcs12_path")
+ self.confirm_file_exists("pki_clone_pkcs12_path")
+
self.confirm_data_exists("pki_clone_replication_security")
+
elif self.external:
# External CA
if not self.external_step_two:
@@ -3996,6 +4011,8 @@ class ConfigClient:
# Issuing CA Information
self.set_issuing_ca_parameters(data)
+ data.systemCertsImported = self.mdict['pki_server_pkcs12_path'] != ''
+
# Create system certs
self.set_system_certs(data)
@@ -4268,10 +4285,15 @@ class ConfigClient:
def set_cloning_parameters(self, data):
data.isClone = "true"
data.cloneUri = self.mdict['pki_clone_uri']
+
+ # Set these clone parameters for non-HSM clones only
if not config.str2bool(self.mdict['pki_hsm_enable']):
- # Set these clone parameters for non-HSM clones only
- data.p12File = self.mdict['pki_clone_pkcs12_path']
- data.p12Password = self.mdict['pki_clone_pkcs12_password']
+ # If system certificates are already provided via pki_server_pkcs12
+ # there's no need to provide pki_clone_pkcs12.
+ if not self.mdict['pki_server_pkcs12_path']:
+ data.p12File = self.mdict['pki_clone_pkcs12_path']
+ data.p12Password = self.mdict['pki_clone_pkcs12_password']
+
if config.str2bool(self.mdict['pki_clone_replicate_schema']):
data.replicateSchema = "true"
else:
diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py
index e5e02a09e..755a5cdce 100644
--- a/base/server/python/pki/server/deployment/pkiparser.py
+++ b/base/server/python/pki/server/deployment/pkiparser.py
@@ -333,8 +333,10 @@ class PKIConfigParser:
'pki_client_pkcs12_password',
'pki_ds_password',
'pki_pin',
- 'pki_replicationdb_password',
- 'pki_security_domain_password')
+ 'pki_replication_password',
+ 'pki_security_domain_password',
+ 'pki_server_pkcs12_password',
+ 'pki_token_password')
print 'Loading deployment configuration from ' + \
config.user_deployment_cfg + '.'
diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
index c3d4d9e49..947c9a740 100644
--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py
+++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
@@ -19,6 +19,10 @@
# All rights reserved.
#
+from __future__ import absolute_import
+
+import pki.nssdb
+
# PKI Deployment Imports
from .. import pkiconfig as config
from .. import pkimessages as log
@@ -35,8 +39,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
config.pki_log.info(log.SKIP_SECURITY_DATABASES_SPAWN_1, __name__,
extra=config.PKI_INDENTATION_LEVEL_1)
return self.rv
+
config.pki_log.info(log.SECURITY_DATABASES_SPAWN_1, __name__,
extra=config.PKI_INDENTATION_LEVEL_1)
+
if config.str2bool(deployer.mdict['pki_hsm_enable']):
deployer.password.create_hsm_password_conf(
deployer.mdict['pki_shared_password_conf'],
@@ -46,6 +52,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
deployer.password.create_password_conf(
deployer.mdict['pki_shared_password_conf'],
deployer.mdict['pki_pin'])
+
# Since 'certutil' does NOT strip the 'token=' portion of
# the 'token=password' entries, create a temporary server 'pfile'
# which ONLY contains the 'password' for the purposes of
@@ -54,12 +61,14 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
deployer.mdict['pki_shared_pfile'],
deployer.mdict['pki_pin'], pin_sans_token=True)
deployer.file.modify(deployer.mdict['pki_shared_password_conf'])
+
deployer.certutil.create_security_databases(
deployer.mdict['pki_database_path'],
deployer.mdict['pki_cert_database'],
deployer.mdict['pki_key_database'],
deployer.mdict['pki_secmod_database'],
password_file=deployer.mdict['pki_shared_pfile'])
+
if config.str2bool(deployer.mdict['pki_hsm_enable']):
deployer.modutil.register_security_module(
deployer.mdict['pki_database_path'],
@@ -75,6 +84,24 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
deployer.mdict['pki_secmod_database'],
perms=config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS)
+ pki_server_pkcs12_path = deployer.mdict['pki_server_pkcs12_path']
+
+ if pki_server_pkcs12_path:
+
+ # importing system certificates
+
+ pki_server_pkcs12_password = deployer.mdict['pki_server_pkcs12_password']
+ if not pki_server_pkcs12_password:
+ raise Exception('Missing pki_server_pkcs12_password property.')
+
+ nssdb = pki.nssdb.NSSDatabase(
+ directory=deployer.mdict['pki_database_path'],
+ password_file=deployer.mdict['pki_shared_pfile'])
+
+ nssdb.import_pkcs12(
+ pkcs12_file=pki_server_pkcs12_path,
+ pkcs12_password=pki_server_pkcs12_password)
+
if len(deployer.instance.tomcat_instance_subsystems()) < 2:
# only create a self signed cert for a new instance
#