def import_certs_and_keys(self, deployer, nssdb): pkcs12_file = deployer.mdict.get('pki_external_pkcs12_path') if not pkcs12_file or not os.path.exists(pkcs12_file): return logger.info('Importing certificates and keys from %s', pkcs12_file) pkcs12_password = deployer.mdict['pki_external_pkcs12_password'] nssdb.import_pkcs12(pkcs12_file, pkcs12_password)
def import_certs_and_keys(self, deployer, nssdb): pkcs12_file = deployer.mdict.get('pki_external_pkcs12_path') if not pkcs12_file or not os.path.exists(pkcs12_file): return config.pki_log.info("importing certificates and keys from %s", pkcs12_file, extra=config.PKI_INDENTATION_LEVEL_2) pkcs12_password = deployer.mdict['pki_external_pkcs12_password'] nssdb.import_pkcs12(pkcs12_file, pkcs12_password)
def spawn(self, deployer): if config.str2bool(deployer.mdict['pki_skip_installation']): logger.info('Skipping NSS database creation') return logger.info('Creating NSS database') instance = pki.server.PKIInstance(deployer.mdict['pki_instance_name']) instance.load() subsystem = instance.get_subsystem( deployer.mdict['pki_subsystem'].lower()) if config.str2bool(deployer.mdict['pki_hsm_enable']): deployer.password.create_hsm_password_conf( deployer.mdict['pki_shared_password_conf'], deployer.mdict['pki_server_database_password'], deployer.mdict['pki_token_password']) else: deployer.password.create_password_conf( deployer.mdict['pki_shared_password_conf'], deployer.mdict['pki_server_database_password']) # 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 # allowing 'certutil' to generate the security databases deployer.password.create_password_conf( deployer.mdict['pki_shared_pfile'], deployer.mdict['pki_server_database_password'], pin_sans_token=True) deployer.file.modify(deployer.mdict['pki_shared_password_conf']) deployer.certutil.create_security_databases( deployer.mdict['pki_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) if config.str2bool(deployer.mdict['pki_hsm_enable']): deployer.modutil.register_security_module( deployer.mdict['pki_server_database_path'], deployer.mdict['pki_hsm_modulename'], deployer.mdict['pki_hsm_libfile']) pki.util.chown(deployer.mdict['pki_server_database_path'], deployer.mdict['pki_uid'], deployer.mdict['pki_uid']) pki.util.chmod( deployer.mdict['pki_server_database_path'], config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) os.chmod(deployer.mdict['pki_server_database_path'], config.PKI_DEPLOYMENT_DEFAULT_DIR_PERMISSIONS) # import system certificates before starting the server pki_server_pkcs12_path = deployer.mdict['pki_server_pkcs12_path'] if pki_server_pkcs12_path: 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_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) try: nssdb.import_pkcs12(pkcs12_file=pki_server_pkcs12_path, pkcs12_password=pki_server_pkcs12_password) finally: nssdb.close() # update external CA file (if needed) external_certs_path = deployer.mdict[ 'pki_server_external_certs_path'] if external_certs_path is not None: self.update_external_certs_conf(external_certs_path, deployer) # import CA certificates from PKCS #12 file for cloning pki_clone_pkcs12_path = deployer.mdict['pki_clone_pkcs12_path'] if pki_clone_pkcs12_path: pki_clone_pkcs12_password = deployer.mdict[ 'pki_clone_pkcs12_password'] if not pki_clone_pkcs12_password: raise Exception('Missing pki_clone_pkcs12_password property.') nssdb = pki.nssdb.NSSDatabase( directory=deployer.mdict['pki_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) try: print('Importing certificates from %s:' % pki_clone_pkcs12_path) # The PKCS12 class requires an NSS database to run. For simplicity # it uses the NSS database that has just been created. pkcs12 = pki.pkcs12.PKCS12(path=pki_clone_pkcs12_path, password=pki_clone_pkcs12_password, nssdb=nssdb) try: pkcs12.show_certs() finally: pkcs12.close() # Import certificates nssdb.import_pkcs12(pkcs12_file=pki_clone_pkcs12_path, pkcs12_password=pki_clone_pkcs12_password) # Set certificate trust flags if subsystem.type == 'CA': nssdb.modify_cert( nickname=deployer.mdict['pki_ca_signing_nickname'], trust_attributes='CTu,Cu,Cu') nssdb.modify_cert( nickname=deployer.mdict['pki_audit_signing_nickname'], trust_attributes='u,u,Pu') print('Imported certificates into %s:' % deployer.mdict['pki_server_database_path']) nssdb.show_certs() finally: nssdb.close() if len(deployer.instance.tomcat_instance_subsystems()) < 2: # Check to see if a secure connection is being used for the DS if config.str2bool(deployer.mdict['pki_ds_secure_connection']): # Check to see if a directory server CA certificate # using the same nickname already exists # # NOTE: ALWAYS use the software DB regardless of whether # the instance will utilize 'softokn' or an HSM # rv = deployer.certutil.verify_certificate_exists( path=deployer.mdict['pki_server_database_path'], token=deployer.mdict['pki_self_signed_token'], nickname=deployer. mdict['pki_ds_secure_connection_ca_nickname'], password_file=deployer.mdict['pki_shared_pfile']) if not rv: # Import the directory server CA certificate rv = deployer.certutil.import_cert( deployer.mdict['pki_ds_secure_connection_ca_nickname'], deployer. mdict['pki_ds_secure_connection_ca_trustargs'], deployer.mdict['pki_ds_secure_connection_ca_pem_file'], password_file=deployer.mdict['pki_shared_pfile'], path=deployer.mdict['pki_server_database_path'], token=deployer.mdict['pki_self_signed_token']) # Always delete the temporary 'pfile' deployer.file.delete(deployer.mdict['pki_shared_pfile']) # Store system cert parameters in installation step to guarantee the # parameters exist during configuration step and to allow customization. certs = subsystem.find_system_certs() for cert in certs: # get CS.cfg tag and pkispawn tag config_tag = cert['id'] deploy_tag = config_tag if config_tag == 'signing': # for CA and OCSP deploy_tag = subsystem.name + '_signing' # store nickname nickname = deployer.mdict['pki_%s_nickname' % deploy_tag] subsystem.config['%s.%s.nickname' % (subsystem.name, config_tag)] = nickname subsystem.config['preop.cert.%s.nickname' % config_tag] = nickname # store tokenname tokenname = deployer.mdict['pki_%s_token' % deploy_tag] subsystem.config['%s.%s.tokenname' % (subsystem.name, config_tag)] = tokenname # store subject DN subject_dn = deployer.mdict['pki_%s_subject_dn' % deploy_tag] subsystem.config['preop.cert.%s.dn' % config_tag] = subject_dn # TODO: move more system cert params here # If specified in the deployment parameter, add generic CA signing cert # extension parameters into the CS.cfg. Generic extension for other # system certs can be added directly into CS.cfg after before the # configuration step. if subsystem.type == 'CA': if deployer.configuration_file.add_req_ext: subsystem.config['preop.cert.signing.ext.oid'] = \ deployer.configuration_file.req_ext_oid subsystem.config['preop.cert.signing.ext.data'] = \ deployer.configuration_file.req_ext_data subsystem.config['preop.cert.signing.ext.critical'] = \ deployer.configuration_file.req_ext_critical.lower() subsystem.save() # Place 'slightly' less restrictive permissions on # the top-level client directory ONLY deployer.directory.create( deployer.mdict['pki_client_subsystem_dir'], uid=0, gid=0, perms=config.PKI_DEPLOYMENT_DEFAULT_CLIENT_DIR_PERMISSIONS) # Since 'certutil' does NOT strip the 'token=' portion of # the 'token=password' entries, create a client password file # which ONLY contains the 'password' for the purposes of # allowing 'certutil' to generate the security databases deployer.password.create_password_conf( deployer.mdict['pki_client_password_conf'], deployer.mdict['pki_client_database_password'], pin_sans_token=True) deployer.file.modify(deployer.mdict['pki_client_password_conf'], uid=0, gid=0) # Similarly, create a simple password file containing the # PKCS #12 password used when exporting the 'Admin Certificate' # into a PKCS #12 file deployer.password.create_client_pkcs12_password_conf( deployer.mdict['pki_client_pkcs12_password_conf']) deployer.file.modify(deployer.mdict['pki_client_pkcs12_password_conf']) deployer.directory.create(deployer.mdict['pki_client_database_dir'], uid=0, gid=0) deployer.certutil.create_security_databases( deployer.mdict['pki_client_database_dir'], password_file=deployer.mdict['pki_client_password_conf'])
def spawn(self, deployer): if config.str2bool(deployer.mdict['pki_skip_installation']): logger.info('Skipping NSS database creation') return instance = self.instance instance.load() usePSSForRSASigningAlg = \ deployer.mdict['pki_use_pss_rsa_signing_algorithm'] if usePSSForRSASigningAlg == "True": self.set_signing_algs_for_pss(deployer) subsystem = instance.get_subsystem(deployer.mdict['pki_subsystem'].lower()) if config.str2bool(deployer.mdict['pki_hsm_enable']): hsm_token = deployer.mdict['pki_token_name'] subsystem.config['preop.module.token'] = hsm_token # 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 # allowing 'certutil' to generate the security databases logger.info('Creating password file: %s', deployer.mdict['pki_shared_pfile']) deployer.password.create_password_conf( deployer.mdict['pki_shared_pfile'], deployer.mdict['pki_server_database_password'], pin_sans_token=True) deployer.file.modify(deployer.mdict['pki_shared_password_conf']) if not os.path.isdir(deployer.mdict['pki_server_database_path']): instance.makedirs(deployer.mdict['pki_server_database_path'], force=True) nssdb = pki.nssdb.NSSDatabase( directory=deployer.mdict['pki_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) try: if not nssdb.exists(): logger.info('Creating NSS database: %s', deployer.mdict['pki_server_database_path']) nssdb.create() finally: nssdb.close() if not os.path.islink(deployer.mdict['pki_instance_database_link']): instance.symlink( deployer.mdict['pki_server_database_path'], deployer.mdict['pki_instance_database_link'], force=True) instance.symlink( deployer.mdict['pki_instance_database_link'], deployer.mdict['pki_subsystem_database_link'], force=True) if config.str2bool(deployer.mdict['pki_hsm_enable']) and \ not nssdb.module_exists(deployer.mdict['pki_hsm_modulename']): nssdb.add_module( deployer.mdict['pki_hsm_modulename'], deployer.mdict['pki_hsm_libfile']) # Set the initial NSS database ownership and permissions. pki.util.chown( deployer.mdict['pki_server_database_path'], deployer.mdict['pki_uid'], deployer.mdict['pki_gid']) pki.util.chmod( deployer.mdict['pki_server_database_path'], config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) os.chmod( deployer.mdict['pki_server_database_path'], pki.server.DEFAULT_DIR_MODE) # import system certificates before starting the server pki_server_pkcs12_path = deployer.mdict['pki_server_pkcs12_path'] if pki_server_pkcs12_path: 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_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) try: nssdb.import_pkcs12( pkcs12_file=pki_server_pkcs12_path, pkcs12_password=pki_server_pkcs12_password) finally: nssdb.close() # update external CA file (if needed) external_certs_path = deployer.mdict['pki_server_external_certs_path'] if external_certs_path is not None: self.update_external_certs_conf(external_certs_path, deployer) # import CA certificates from PKCS #12 file for cloning pki_clone_pkcs12_path = deployer.mdict['pki_clone_pkcs12_path'] pki_server_database_path = deployer.mdict['pki_server_database_path'] if pki_clone_pkcs12_path: pki_clone_pkcs12_password = deployer.mdict[ 'pki_clone_pkcs12_password'] if not pki_clone_pkcs12_password: raise Exception('Missing pki_clone_pkcs12_password property.') nssdb = pki.nssdb.NSSDatabase( directory=pki_server_database_path, password_file=deployer.mdict['pki_shared_pfile']) try: print('Importing certificates from %s:' % pki_clone_pkcs12_path) # The PKCS12 class requires an NSS database to run. For simplicity # it uses the NSS database that has just been created. pkcs12 = pki.pkcs12.PKCS12( path=pki_clone_pkcs12_path, password=pki_clone_pkcs12_password, nssdb=nssdb) try: pkcs12.show_certs() finally: pkcs12.close() # Import certificates nssdb.import_pkcs12( pkcs12_file=pki_clone_pkcs12_path, pkcs12_password=pki_clone_pkcs12_password) print('Imported certificates into %s:' % pki_server_database_path) nssdb.show_certs() finally: nssdb.close() # Export CA certificate to PEM file; same command as in # PKIServer.setup_cert_authentication(). # openssl pkcs12 -in <p12_file_path> -out /tmp/auth.pem -nodes -nokeys pki_ca_crt_path = os.path.join(pki_server_database_path, 'ca.crt') cmd_export_ca = [ 'openssl', 'pkcs12', '-in', pki_clone_pkcs12_path, '-out', pki_ca_crt_path, '-nodes', '-nokeys', '-passin', 'pass:'******'utf-8') logger.debug('Result of CA certificate export: %s', res_ca) # At this point, we're running as root. However, the subsystem # will eventually start up as non-root and will attempt to do a # migration. If we don't fix the permissions now, migration will # fail and subsystem won't start up. pki.util.chmod(pki_ca_crt_path, 0o644) pki.util.chown(pki_ca_crt_path, deployer.mdict['pki_uid'], deployer.mdict['pki_gid']) ca_cert_path = deployer.mdict.get('pki_cert_chain_path') if ca_cert_path and os.path.exists(ca_cert_path): destination = os.path.join(instance.nssdb_dir, "ca.crt") if not os.path.exists(destination): # When we're passed a CA certificate file and we don't already # have a CA file for some reason, we need to copy the passed # file as the root CA certificate to establish trust in the # Python code. It doesn't import it into the NSS DB for Java # code, but so far we haven't had any issues with certificate # validation there. This is only usually necessary when # installing a non-CA subsystem on a fresh system. instance.copyfile(ca_cert_path, destination) if len(deployer.instance.tomcat_instance_subsystems()) < 2: # Check to see if a secure connection is being used for the DS if config.str2bool(deployer.mdict['pki_ds_secure_connection']): # Check to see if a directory server CA certificate # using the same nickname already exists # # NOTE: ALWAYS use the software DB regardless of whether # the instance will utilize 'softokn' or an HSM # rv = deployer.certutil.verify_certificate_exists( path=deployer.mdict['pki_server_database_path'], token=deployer.mdict['pki_self_signed_token'], nickname=deployer.mdict[ 'pki_ds_secure_connection_ca_nickname' ], password_file=deployer.mdict['pki_shared_pfile']) if not rv: # Import the directory server CA certificate rv = deployer.certutil.import_cert( deployer.mdict['pki_ds_secure_connection_ca_nickname'], deployer.mdict[ 'pki_ds_secure_connection_ca_trustargs'], deployer.mdict['pki_ds_secure_connection_ca_pem_file'], password_file=deployer.mdict['pki_shared_pfile'], path=deployer.mdict['pki_server_database_path'], token=deployer.mdict['pki_self_signed_token']) # Always delete the temporary 'pfile' deployer.file.delete(deployer.mdict['pki_shared_pfile']) # Store system cert parameters in installation step to guarantee the # parameters exist during configuration step and to allow customization. certs = subsystem.find_system_certs() for cert in certs: # get CS.cfg tag and pkispawn tag config_tag = cert['id'] deploy_tag = config_tag if config_tag == 'signing': # for CA and OCSP deploy_tag = subsystem.name + '_signing' # store nickname nickname = deployer.mdict['pki_%s_nickname' % deploy_tag] subsystem.config['%s.%s.nickname' % (subsystem.name, config_tag)] = nickname subsystem.config['preop.cert.%s.nickname' % config_tag] = nickname # store tokenname tokenname = deployer.mdict['pki_%s_token' % deploy_tag] subsystem.config['%s.%s.tokenname' % (subsystem.name, config_tag)] = tokenname fullname = nickname if pki.nssdb.normalize_token(tokenname): fullname = tokenname + ':' + nickname subsystem.config['%s.cert.%s.nickname' % (subsystem.name, config_tag)] = fullname # store subject DN subject_dn = deployer.mdict['pki_%s_subject_dn' % deploy_tag] subsystem.config['preop.cert.%s.dn' % config_tag] = subject_dn keyalgorithm = deployer.mdict['pki_%s_key_algorithm' % deploy_tag] subsystem.config['preop.cert.%s.keyalgorithm' % config_tag] = keyalgorithm signingalgorithm = deployer.mdict.get( 'pki_%s_signing_algorithm' % deploy_tag, keyalgorithm) subsystem.config['preop.cert.%s.signingalgorithm' % config_tag] = signingalgorithm if subsystem.name == 'ca': if config_tag == 'signing': subsystem.config['ca.signing.defaultSigningAlgorithm'] = signingalgorithm subsystem.config['ca.crl.MasterCRL.signingAlgorithm'] = signingalgorithm elif config_tag == 'ocsp_signing': subsystem.config['ca.ocsp_signing.defaultSigningAlgorithm'] = signingalgorithm elif subsystem.name == 'ocsp': if config_tag == 'signing': subsystem.config['ocsp.signing.defaultSigningAlgorithm'] = signingalgorithm elif subsystem.name == 'kra': if config_tag == 'transport': subsystem.config['kra.transportUnit.signingAlgorithm'] = signingalgorithm # TODO: move more system cert params here admin_dn = deployer.mdict['pki_admin_subject_dn'] subsystem.config['preop.cert.admin.dn'] = admin_dn # If specified in the deployment parameter, add generic CA signing cert # extension parameters into the CS.cfg. Generic extension for other # system certs can be added directly into CS.cfg after before the # configuration step. if subsystem.type == 'CA': signing_nickname = subsystem.config['ca.signing.nickname'] subsystem.config['ca.signing.certnickname'] = signing_nickname subsystem.config['ca.signing.cacertnickname'] = signing_nickname ocsp_signing_nickname = subsystem.config['ca.ocsp_signing.nickname'] subsystem.config['ca.ocsp_signing.certnickname'] = ocsp_signing_nickname subsystem.config['ca.ocsp_signing.cacertnickname'] = ocsp_signing_nickname if deployer.configuration_file.add_req_ext: subsystem.config['preop.cert.signing.ext.oid'] = \ deployer.configuration_file.req_ext_oid subsystem.config['preop.cert.signing.ext.data'] = \ deployer.configuration_file.req_ext_data subsystem.config['preop.cert.signing.ext.critical'] = \ deployer.configuration_file.req_ext_critical.lower() if deployer.configuration_file.req_ski: subsystem.config['preop.cert.signing.subject_key_id'] = \ deployer.configuration_file.req_ski if subsystem.type == 'KRA': storage_nickname = subsystem.config['kra.storage.nickname'] storage_token = subsystem.config['kra.storage.tokenname'] if pki.nssdb.normalize_token(storage_token): subsystem.config['kra.storageUnit.hardware'] = storage_token subsystem.config['kra.storageUnit.nickName'] = \ storage_token + ':' + storage_nickname else: subsystem.config['kra.storageUnit.nickName'] = \ storage_nickname transport_nickname = subsystem.config['kra.transport.nickname'] transport_token = subsystem.config['kra.transport.tokenname'] if pki.nssdb.normalize_token(transport_token): subsystem.config['kra.transportUnit.nickName'] = \ transport_token + ':' + transport_nickname else: subsystem.config['kra.transportUnit.nickName'] = \ transport_nickname if subsystem.type == 'OCSP': signing_nickname = subsystem.config['ocsp.signing.nickname'] subsystem.config['ocsp.signing.certnickname'] = signing_nickname subsystem.config['ocsp.signing.cacertnickname'] = signing_nickname audit_nickname = subsystem.config['%s.audit_signing.nickname' % subsystem.name] audit_token = subsystem.config['%s.audit_signing.tokenname' % subsystem.name] if pki.nssdb.normalize_token(audit_token): audit_nickname = audit_token + ':' + audit_nickname subsystem.config['log.instance.SignedAudit.signedAuditCertNickname'] = audit_nickname san_inject = config.str2bool(deployer.mdict['pki_san_inject']) logger.info('Injecting SAN: %s', san_inject) san_for_server_cert = deployer.mdict.get('pki_san_for_server_cert') logger.info('SSL server cert SAN: %s', san_for_server_cert) if san_inject and san_for_server_cert: subsystem.config['service.injectSAN'] = 'true' subsystem.config['service.sslserver.san'] = san_for_server_cert subsystem.save() # Place 'slightly' less restrictive permissions on # the top-level client directory ONLY deployer.directory.create( deployer.mdict['pki_client_subsystem_dir'], uid=0, gid=0, perms=config.PKI_DEPLOYMENT_DEFAULT_CLIENT_DIR_PERMISSIONS) # Since 'certutil' does NOT strip the 'token=' portion of # the 'token=password' entries, create a client password file # which ONLY contains the 'password' for the purposes of # allowing 'certutil' to generate the security databases logger.info('Creating password file: %s', deployer.mdict['pki_client_password_conf']) deployer.password.create_password_conf( deployer.mdict['pki_client_password_conf'], deployer.mdict['pki_client_database_password'], pin_sans_token=True) deployer.file.modify( deployer.mdict['pki_client_password_conf'], uid=0, gid=0) # Similarly, create a simple password file containing the # PKCS #12 password used when exporting the 'Admin Certificate' # into a PKCS #12 file deployer.password.create_client_pkcs12_password_conf( deployer.mdict['pki_client_pkcs12_password_conf']) deployer.file.modify(deployer.mdict['pki_client_pkcs12_password_conf']) pki.util.makedirs(deployer.mdict['pki_client_database_dir'], force=True) nssdb = pki.nssdb.NSSDatabase( directory=deployer.mdict['pki_client_database_dir'], password_file=deployer.mdict['pki_client_password_conf']) try: if not nssdb.exists(): nssdb.create() finally: nssdb.close()
def spawn(self, deployer): if config.str2bool(deployer.mdict['pki_skip_installation']): logger.info('Skipping NSS database creation') return logger.info('Creating NSS database') instance = pki.server.PKIInstance(deployer.mdict['pki_instance_name']) instance.load() subsystem = instance.get_subsystem( deployer.mdict['pki_subsystem'].lower()) if config.str2bool(deployer.mdict['pki_hsm_enable']): deployer.password.create_hsm_password_conf( deployer.mdict['pki_shared_password_conf'], deployer.mdict['pki_server_database_password'], deployer.mdict['pki_token_password']) else: deployer.password.create_password_conf( deployer.mdict['pki_shared_password_conf'], deployer.mdict['pki_server_database_password']) # 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 # allowing 'certutil' to generate the security databases deployer.password.create_password_conf( deployer.mdict['pki_shared_pfile'], deployer.mdict['pki_server_database_password'], pin_sans_token=True) deployer.file.modify(deployer.mdict['pki_shared_password_conf']) deployer.certutil.create_security_databases( deployer.mdict['pki_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) if config.str2bool(deployer.mdict['pki_hsm_enable']): deployer.modutil.register_security_module( deployer.mdict['pki_server_database_path'], deployer.mdict['pki_hsm_modulename'], deployer.mdict['pki_hsm_libfile']) pki.util.chown( deployer.mdict['pki_server_database_path'], deployer.mdict['pki_uid'], deployer.mdict['pki_uid']) pki.util.chmod( deployer.mdict['pki_server_database_path'], config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) os.chmod( deployer.mdict['pki_server_database_path'], config.PKI_DEPLOYMENT_DEFAULT_DIR_PERMISSIONS) # import system certificates before starting the server pki_server_pkcs12_path = deployer.mdict['pki_server_pkcs12_path'] if pki_server_pkcs12_path: 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_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) try: nssdb.import_pkcs12( pkcs12_file=pki_server_pkcs12_path, pkcs12_password=pki_server_pkcs12_password) finally: nssdb.close() # update external CA file (if needed) external_certs_path = deployer.mdict['pki_server_external_certs_path'] if external_certs_path is not None: self.update_external_certs_conf(external_certs_path, deployer) # import CA certificates from PKCS #12 file for cloning pki_clone_pkcs12_path = deployer.mdict['pki_clone_pkcs12_path'] if pki_clone_pkcs12_path: pki_clone_pkcs12_password = deployer.mdict[ 'pki_clone_pkcs12_password'] if not pki_clone_pkcs12_password: raise Exception('Missing pki_clone_pkcs12_password property.') nssdb = pki.nssdb.NSSDatabase( directory=deployer.mdict['pki_server_database_path'], password_file=deployer.mdict['pki_shared_pfile']) try: print('Importing certificates from %s:' % pki_clone_pkcs12_path) # The PKCS12 class requires an NSS database to run. For simplicity # it uses the NSS database that has just been created. pkcs12 = pki.pkcs12.PKCS12( path=pki_clone_pkcs12_path, password=pki_clone_pkcs12_password, nssdb=nssdb) try: pkcs12.show_certs() finally: pkcs12.close() # Import certificates nssdb.import_pkcs12( pkcs12_file=pki_clone_pkcs12_path, pkcs12_password=pki_clone_pkcs12_password) # Set certificate trust flags if subsystem.type == 'CA': nssdb.modify_cert( nickname=deployer.mdict['pki_ca_signing_nickname'], trust_attributes='CTu,Cu,Cu') nssdb.modify_cert( nickname=deployer.mdict['pki_audit_signing_nickname'], trust_attributes='u,u,Pu') print('Imported certificates into %s:' % deployer.mdict['pki_server_database_path']) nssdb.show_certs() finally: nssdb.close() if len(deployer.instance.tomcat_instance_subsystems()) < 2: # Check to see if a secure connection is being used for the DS if config.str2bool(deployer.mdict['pki_ds_secure_connection']): # Check to see if a directory server CA certificate # using the same nickname already exists # # NOTE: ALWAYS use the software DB regardless of whether # the instance will utilize 'softokn' or an HSM # rv = deployer.certutil.verify_certificate_exists( path=deployer.mdict['pki_server_database_path'], token=deployer.mdict['pki_self_signed_token'], nickname=deployer.mdict[ 'pki_ds_secure_connection_ca_nickname' ], password_file=deployer.mdict['pki_shared_pfile']) if not rv: # Import the directory server CA certificate rv = deployer.certutil.import_cert( deployer.mdict['pki_ds_secure_connection_ca_nickname'], deployer.mdict[ 'pki_ds_secure_connection_ca_trustargs'], deployer.mdict['pki_ds_secure_connection_ca_pem_file'], password_file=deployer.mdict['pki_shared_pfile'], path=deployer.mdict['pki_server_database_path'], token=deployer.mdict['pki_self_signed_token']) # Always delete the temporary 'pfile' deployer.file.delete(deployer.mdict['pki_shared_pfile']) # Store system cert parameters in installation step to guarantee the # parameters exist during configuration step and to allow customization. certs = subsystem.find_system_certs() for cert in certs: # get CS.cfg tag and pkispawn tag config_tag = cert['id'] deploy_tag = config_tag if config_tag == 'signing': # for CA and OCSP deploy_tag = subsystem.name + '_signing' # store nickname nickname = deployer.mdict['pki_%s_nickname' % deploy_tag] subsystem.config['%s.%s.nickname' % (subsystem.name, config_tag)] = nickname subsystem.config['preop.cert.%s.nickname' % config_tag] = nickname # store tokenname tokenname = deployer.mdict['pki_%s_token' % deploy_tag] subsystem.config['%s.%s.tokenname' % (subsystem.name, config_tag)] = tokenname # store subject DN subject_dn = deployer.mdict['pki_%s_subject_dn' % deploy_tag] subsystem.config['preop.cert.%s.dn' % config_tag] = subject_dn # TODO: move more system cert params here # If specified in the deployment parameter, add generic CA signing cert # extension parameters into the CS.cfg. Generic extension for other # system certs can be added directly into CS.cfg after before the # configuration step. if subsystem.type == 'CA': if deployer.configuration_file.add_req_ext: subsystem.config['preop.cert.signing.ext.oid'] = \ deployer.configuration_file.req_ext_oid subsystem.config['preop.cert.signing.ext.data'] = \ deployer.configuration_file.req_ext_data subsystem.config['preop.cert.signing.ext.critical'] = \ deployer.configuration_file.req_ext_critical.lower() subsystem.save() # Place 'slightly' less restrictive permissions on # the top-level client directory ONLY deployer.directory.create( deployer.mdict['pki_client_subsystem_dir'], uid=0, gid=0, perms=config.PKI_DEPLOYMENT_DEFAULT_CLIENT_DIR_PERMISSIONS) # Since 'certutil' does NOT strip the 'token=' portion of # the 'token=password' entries, create a client password file # which ONLY contains the 'password' for the purposes of # allowing 'certutil' to generate the security databases deployer.password.create_password_conf( deployer.mdict['pki_client_password_conf'], deployer.mdict['pki_client_database_password'], pin_sans_token=True) deployer.file.modify( deployer.mdict['pki_client_password_conf'], uid=0, gid=0) # Similarly, create a simple password file containing the # PKCS #12 password used when exporting the 'Admin Certificate' # into a PKCS #12 file deployer.password.create_client_pkcs12_password_conf( deployer.mdict['pki_client_pkcs12_password_conf']) deployer.file.modify(deployer.mdict['pki_client_pkcs12_password_conf']) deployer.directory.create( deployer.mdict['pki_client_database_dir'], uid=0, gid=0) deployer.certutil.create_security_databases( deployer.mdict['pki_client_database_dir'], password_file=deployer.mdict['pki_client_password_conf'])
def spawn(self, deployer): if config.str2bool(deployer.mdict['pki_skip_configuration']): config.pki_log.info(log.SKIP_CONFIGURATION_SPAWN_1, __name__, extra=config.PKI_INDENTATION_LEVEL_1) return config.pki_log.info(log.CONFIGURATION_SPAWN_1, __name__, extra=config.PKI_INDENTATION_LEVEL_1) # Place "slightly" less restrictive permissions on # the top-level client directory ONLY deployer.directory.create( deployer.mdict['pki_client_subsystem_dir'], uid=0, gid=0, perms=config.PKI_DEPLOYMENT_DEFAULT_CLIENT_DIR_PERMISSIONS) # Since 'certutil' does NOT strip the 'token=' portion of # the 'token=password' entries, create a client password file # which ONLY contains the 'password' for the purposes of # allowing 'certutil' to generate the security databases deployer.password.create_password_conf( deployer.mdict['pki_client_password_conf'], deployer.mdict['pki_client_database_password'], pin_sans_token=True) deployer.file.modify(deployer.mdict['pki_client_password_conf'], uid=0, gid=0) # Similarly, create a simple password file containing the # PKCS #12 password used when exporting the "Admin Certificate" # into a PKCS #12 file deployer.password.create_client_pkcs12_password_conf( deployer.mdict['pki_client_pkcs12_password_conf']) deployer.file.modify(deployer.mdict['pki_client_pkcs12_password_conf']) deployer.directory.create(deployer.mdict['pki_client_database_dir'], uid=0, gid=0) deployer.certutil.create_security_databases( deployer.mdict['pki_client_database_dir'], deployer.mdict['pki_client_cert_database'], deployer.mdict['pki_client_key_database'], deployer.mdict['pki_client_secmod_database'], password_file=deployer.mdict['pki_client_password_conf']) instance = pki.server.PKIInstance(deployer.mdict['pki_instance_name']) instance.load() subsystem = instance.get_subsystem( deployer.mdict['pki_subsystem'].lower()) ocsp_uri = deployer.mdict.get('pki_default_ocsp_uri') if ocsp_uri: subsystem.config['ca.defaultOcspUri'] = ocsp_uri subsystem.save() token = deployer.mdict['pki_token_name'] nssdb = instance.open_nssdb(token) existing = deployer.configuration_file.existing external = deployer.configuration_file.external standalone = deployer.configuration_file.standalone step_one = deployer.configuration_file.external_step_one step_two = deployer.configuration_file.external_step_two clone = deployer.configuration_file.clone try: if external and step_one: # external CA step 1 only subject_dn = subsystem.config['preop.cert.signing.dn'] # Determine CA signing key type and algorithm key_type = deployer.mdict['pki_ca_signing_key_type'] key_alg = deployer.mdict['pki_ca_signing_key_algorithm'] if key_type == 'rsa': key_size = int(deployer.mdict['pki_ca_signing_key_size']) curve = None m = re.match(r'(.*)withRSA', key_alg) if not m: raise Exception('Invalid key algorithm: %s' % key_alg) hash_alg = m.group(1) elif key_type == 'ec' or key_type == 'ecc': key_type = 'ec' key_size = None curve = deployer.mdict['pki_ca_signing_key_size'] m = re.match(r'(.*)withEC', key_alg) if not m: raise Exception('Invalid key algorithm: %s' % key_alg) hash_alg = m.group(1) else: raise Exception('Invalid key type: %s' % key_type) # If filename specified, generate CA cert request and # import it into CS.cfg. external_csr_path = deployer.mdict['pki_external_csr_path'] if external_csr_path: config.pki_log.info( "generating CA signing certificate request in %s", external_csr_path, extra=config.PKI_INDENTATION_LEVEL_2) basic_constraints_ext = { 'ca': True, 'path_length': None, 'critical': True } key_usage_ext = { 'digitalSignature': True, 'nonRepudiation': True, 'certSigning': True, 'crlSigning': True, 'critical': True } # if specified, add generic CSR extension generic_exts = None if 'preop.cert.signing.ext.oid' in subsystem.config and \ 'preop.cert.signing.ext.data' in subsystem.config: data = subsystem.config['preop.cert.signing.ext.data'] critical = subsystem.config[ 'preop.cert.signing.ext.critical'] generic_ext = { 'oid': subsystem.config['preop.cert.signing.ext.oid'], 'data': binascii.unhexlify(data), 'critical': config.str2bool(critical) } generic_exts = [generic_ext] nssdb.create_request( subject_dn=subject_dn, request_file=external_csr_path, key_type=key_type, key_size=key_size, curve=curve, hash_alg=hash_alg, basic_constraints_ext=basic_constraints_ext, key_usage_ext=key_usage_ext, generic_exts=generic_exts) with open(external_csr_path) as f: signing_csr = f.read() signing_csr = pki.nssdb.convert_csr( signing_csr, 'pem', 'base64') subsystem.config['ca.signing.certreq'] = signing_csr # This is needed by IPA to detect step 1 completion. # See is_step_one_done() in ipaserver/install/cainstance.py. subsystem.config['preop.ca.type'] = 'otherca' subsystem.save() if existing or external and step_two: # existing CA or external CA step 2 # If specified, import CA signing CSR into CS.cfg. signing_csr_path = deployer.mdict['pki_external_csr_path'] if signing_csr_path: config.pki_log.info("importing CA signing CSR from %s", signing_csr_path, extra=config.PKI_INDENTATION_LEVEL_2) with open(signing_csr_path) as f: signing_csr = f.read() signing_csr = pki.nssdb.convert_csr( signing_csr, 'pem', 'base64') subsystem.config['ca.signing.certreq'] = signing_csr # If specified, import CA signing cert into NSS database. signing_nickname = deployer.mdict['pki_ca_signing_nickname'] signing_cert_file = deployer.mdict['pki_external_ca_cert_path'] if signing_cert_file: config.pki_log.info("importing %s from %s", signing_nickname, signing_cert_file, extra=config.PKI_INDENTATION_LEVEL_2) nssdb.add_cert(nickname=signing_nickname, cert_file=signing_cert_file, trust_attributes='CT,C,C') # If specified, import certs and keys from PKCS #12 file # into NSS database. pkcs12_file = deployer.mdict['pki_external_pkcs12_path'] if pkcs12_file: config.pki_log.info( "importing certificates and keys from %s", pkcs12_file, extra=config.PKI_INDENTATION_LEVEL_2) pkcs12_password = deployer.mdict[ 'pki_external_pkcs12_password'] nssdb.import_pkcs12(pkcs12_file, pkcs12_password) # If specified, import cert chain into NSS database. # Note: Cert chain must be imported after the system certs # to ensure that the system certs are imported with # the correct nicknames. external_ca_cert_chain_nickname = \ deployer.mdict['pki_external_ca_cert_chain_nickname'] external_ca_cert_chain_file = deployer.mdict[ 'pki_external_ca_cert_chain_path'] if external_ca_cert_chain_file: config.pki_log.info( "importing certificate chain %s from %s", external_ca_cert_chain_nickname, external_ca_cert_chain_file, extra=config.PKI_INDENTATION_LEVEL_2) cert_chain, _nicks = nssdb.import_cert_chain( nickname=external_ca_cert_chain_nickname, cert_chain_file=external_ca_cert_chain_file, trust_attributes='CT,C,C') subsystem.config['ca.external_ca_chain.cert'] = cert_chain # Export CA signing cert from NSS database and import # it into CS.cfg. signing_cert_data = nssdb.get_cert(nickname=signing_nickname, output_format='base64') subsystem.config['ca.signing.nickname'] = signing_nickname subsystem.config['ca.signing.tokenname'] = ( deployer.mdict['pki_ca_signing_token']) subsystem.config['ca.signing.cert'] = signing_cert_data subsystem.config[ 'ca.signing.cacertnickname'] = signing_nickname subsystem.config['ca.signing.defaultSigningAlgorithm'] = ( deployer.mdict['pki_ca_signing_signing_algorithm']) subsystem.save() # verify the signing certificate # raises exception on failure config.pki_log.info("validating the signing certificate", extra=config.PKI_INDENTATION_LEVEL_2) verifier = pki.server.deployment.PKIDeployer.create_system_cert_verifier( instance, 'ca') verifier.verify_certificate('signing') else: # self-signed CA # To be implemented in ticket #1692. # Generate CA cert request. # Self sign CA cert. # Import self-signed CA cert into NSS database. pass finally: nssdb.close() if external and step_one: return if len(deployer.instance.tomcat_instance_subsystems()) < 2: deployer.password.create_password_conf( deployer.mdict['pki_shared_pfile'], deployer.mdict['pki_pin'], pin_sans_token=True) # only create a self signed cert for a new instance # # NOTE: ALWAYS create the temporary sslserver certificate # in the software DB regardless of whether the # instance will utilize 'softokn' or an HSM # rv = deployer.certutil.verify_certificate_exists( deployer.mdict['pki_database_path'], deployer.mdict['pki_cert_database'], deployer.mdict['pki_key_database'], deployer.mdict['pki_secmod_database'], deployer.mdict['pki_self_signed_token'], deployer.mdict['pki_self_signed_nickname'], password_file=deployer.mdict['pki_shared_pfile']) if not rv: # note: in the function below, certutil is used to generate # the request for the self signed cert. The keys are generated # by NSS, which does not actually use the data in the noise # file, so it does not matter what is in this file. Certutil # still requires it though, otherwise it waits for keyboard # input with open(deployer.mdict['pki_self_signed_noise_file'], 'w') as f: f.write("not_so_random_data") deployer.certutil.generate_self_signed_certificate( deployer.mdict['pki_database_path'], deployer.mdict['pki_cert_database'], deployer.mdict['pki_key_database'], deployer.mdict['pki_secmod_database'], deployer.mdict['pki_self_signed_token'], deployer.mdict['pki_self_signed_nickname'], deployer.mdict['pki_self_signed_subject'], deployer.mdict['pki_self_signed_serial_number'], deployer.mdict['pki_self_signed_validity_period'], deployer.mdict['pki_self_signed_issuer_name'], deployer.mdict['pki_self_signed_trustargs'], deployer.mdict['pki_self_signed_noise_file'], password_file=deployer.mdict['pki_shared_pfile']) # Delete the temporary 'noise' file deployer.file.delete( deployer.mdict['pki_self_signed_noise_file']) # Always delete the temporary 'pfile' deployer.file.delete(deployer.mdict['pki_shared_pfile']) # Start/Restart this Tomcat PKI Process # Optionally prepare to enable a java debugger # (e. g. - 'eclipse'): if config.str2bool(deployer.mdict['pki_enable_java_debugger']): config.prepare_for_an_external_java_debugger( deployer.mdict['pki_target_tomcat_conf_instance_id']) tomcat_instance_subsystems = \ len(deployer.instance.tomcat_instance_subsystems()) if tomcat_instance_subsystems == 1: deployer.systemd.start() elif tomcat_instance_subsystems > 1: deployer.systemd.restart() # wait for startup status = deployer.instance.wait_for_startup(60) if status is None: config.pki_log.error("server failed to restart", extra=config.PKI_INDENTATION_LEVEL_2) raise Exception("server failed to restart") # Optionally wait for debugger to attach (e. g. - 'eclipse'): if config.str2bool(deployer.mdict['pki_enable_java_debugger']): config.wait_to_attach_an_external_java_debugger() # Construct PKI Subsystem Configuration Data data = None if deployer.mdict['pki_instance_type'] == "Tomcat": # CA, KRA, OCSP, TKS, or TPS data = deployer.config_client.construct_pki_configuration_data() # Configure the subsystem response = deployer.config_client.configure_pki_data( json.dumps(data, cls=pki.encoder.CustomTypeEncoder)) config.pki_log.debug(log.PKI_CONFIG_RESPONSE_STATUS + " " + str(response['status']), extra=config.PKI_INDENTATION_LEVEL_2) try: certs = response['systemCerts'] except KeyError: # no system certs created config.pki_log.debug("No new system certificates generated.", extra=config.PKI_INDENTATION_LEVEL_2) certs = [] if not isinstance(certs, list): certs = [certs] for cdata in certs: if standalone and not step_two: # Stand-alone PKI (Step 1) if cdata['tag'].lower() == "audit_signing": # Save Stand-alone PKI 'Audit Signing Certificate' CSR # (Step 1) deployer.config_client.save_system_csr( cdata['request'], log.PKI_CONFIG_EXTERNAL_CSR_SAVE_PKI_AUDIT_SIGNING_1, deployer.mdict['pki_external_audit_signing_csr_path'], subsystem.name) elif cdata['tag'].lower() == "signing": # Save Stand-alone PKI OCSP 'OCSP Signing Certificate' # CSR (Step 1) deployer.config_client.save_system_csr( cdata['request'], log.PKI_CONFIG_EXTERNAL_CSR_SAVE_OCSP_SIGNING, deployer.mdict['pki_external_signing_csr_path']) elif cdata['tag'].lower() == "sslserver": # Save Stand-alone PKI 'SSL Server Certificate' CSR # (Step 1) deployer.config_client.save_system_csr( cdata['request'], log.PKI_CONFIG_EXTERNAL_CSR_SAVE_PKI_SSLSERVER_1, deployer.mdict['pki_external_sslserver_csr_path'], subsystem.name) elif cdata['tag'].lower() == "storage": # Save Stand-alone PKI KRA 'Storage Certificate' CSR # (Step 1) deployer.config_client.save_system_csr( cdata['request'], log.PKI_CONFIG_EXTERNAL_CSR_SAVE_KRA_STORAGE, deployer.mdict['pki_external_storage_csr_path']) elif cdata['tag'].lower() == "subsystem": # Save Stand-alone PKI 'Subsystem Certificate' CSR # (Step 1) deployer.config_client.save_system_csr( cdata['request'], log.PKI_CONFIG_EXTERNAL_CSR_SAVE_PKI_SUBSYSTEM_1, deployer.mdict['pki_external_subsystem_csr_path'], subsystem.name) elif cdata['tag'].lower() == "transport": # Save Stand-alone PKI KRA 'Transport Certificate' CSR # (Step 1) deployer.config_client.save_system_csr( cdata['request'], log.PKI_CONFIG_EXTERNAL_CSR_SAVE_KRA_TRANSPORT, deployer.mdict['pki_external_transport_csr_path']) else: config.pki_log.debug(log.PKI_CONFIG_CDATA_TAG + " " + cdata['tag'], extra=config.PKI_INDENTATION_LEVEL_2) config.pki_log.debug(log.PKI_CONFIG_CDATA_CERT + "\n" + cdata['cert'], extra=config.PKI_INDENTATION_LEVEL_2) config.pki_log.debug(log.PKI_CONFIG_CDATA_REQUEST + "\n" + cdata['request'], extra=config.PKI_INDENTATION_LEVEL_2) # Cloned PKI subsystems do not return an Admin Certificate if not clone: if standalone: if not step_two: # NOTE: Do nothing for Stand-alone PKI (Step 1) # as this has already been addressed # in 'set_admin_parameters()' pass else: admin_cert = response['adminCert']['cert'] deployer.config_client.process_admin_cert(admin_cert) elif not config.str2bool(deployer.mdict['pki_import_admin_cert']): admin_cert = response['adminCert']['cert'] deployer.config_client.process_admin_cert(admin_cert) if len(deployer.instance.tomcat_instance_subsystems()) == 1: # Modify contents of 'serverCertNick.conf' (if necessary) deployer.servercertnick_conf.modify() # Optionally, programmatically 'restart' the configured PKI instance if not config.str2bool( deployer.mdict['pki_restart_configured_instance']): return deployer.systemd.restart() # wait for startup status = None if deployer.fips.is_fips_enabled(): # must use 'http' protocol when FIPS mode is enabled status = deployer.instance.wait_for_startup( 60, secure_connection=False) else: status = deployer.instance.wait_for_startup(60, secure_connection=True) if not status: config.pki_log.error("server failed to restart", extra=config.PKI_INDENTATION_LEVEL_1) raise RuntimeError("server failed to restart")