HSMManager.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.utils.certificate.hsm;

  21. import java.io.File;
  22. import java.io.FileInputStream;
  23. import java.util.ArrayList;
  24. import java.util.Enumeration;
  25. import java.util.HashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Properties;

  29. import org.openspcoop2.utils.UtilsException;
  30. import org.openspcoop2.utils.certificate.KeyStore;
  31. import org.openspcoop2.utils.properties.PropertiesReader;
  32. import org.slf4j.Logger;

  33. /**
  34.  * HSMManager
  35.  *
  36.  * @author Poli Andrea (apoli@link.it)
  37.  * @author $Author$
  38.  * @version $Rev$, $Date$
  39.  */
  40. public class HSMManager {

  41.     private static HSMManager staticInstance;
  42.     public static synchronized void init(File f, boolean throwNotExists, Logger log, boolean accessKeystore) throws UtilsException {
  43.         if(staticInstance==null) {
  44.             staticInstance = new HSMManager(f, throwNotExists, log, accessKeystore);
  45.         }
  46.     }
  47.     public static HSMManager getInstance() {
  48.         // spotbugs warning 'SING_SINGLETON_GETTER_NOT_SYNCHRONIZED': l'istanza viene creata allo startup
  49.         if (staticInstance == null) {
  50.             synchronized (HSMManager.class) {
  51.                 if (staticInstance == null) {
  52.                     return null;
  53.                 }
  54.             }
  55.         }
  56.         return staticInstance;
  57.     }
  58.    
  59.     /*
  60.      * Consente di inizializzare una serie di keystore hardware
  61.      *
  62.      * La configurazione di ogni keystore deve essere definita nel file hsm.properties fornito come argomento dove la sintassi utilizzabile è la seguente
  63.      *
  64.      * hsm.<idKeystore>.provider: [required su nodo run] classe del provider che deve essere stata registrata in JVM/conf/security/java.security o andrà aggiunta dinamicamente tramite opzione successiva
  65.      * hsm.<idKeystore>.provider.add: [optional, default false] indica se il provider fornito deve essere aggiunto (se non già presente)
  66.      * hsm.<idKeystore>.provider.configFile: [optional] se fornito verrà utilizzato per configurare il provider tramite l'istruzione 'configure(configFile)'
  67.      * hsm.<idKeystore>.provider.config: [optional] se fornito verrà utilizzato per configurare il provider tramite l'istruzione 'configure(config)'
  68.      * hsm.<idKeystore>.pin: [required su nodo run] pin per accedere al keystore
  69.      * hsm.<idKeystore>.keystoreType.label: [required su nodo run] label associata al keystore e visualizzata nelle console
  70.      * hsm.<idKeystore>.keystoreType: [required su nodo run] tipo associato al keystore ed utilizzato per istanziarlo tramite l'istruzione 'KeyStore.getInstance(keystoreType, provider)'
  71.      * hsm.<idKeystore>.usableAsTrustStore: [optional, default false] indica se il keystore è utilizzabile anche come truststore di certificati
  72.      * hsm.<idKeystore>.usableAsSecretKeyStore: [optional, default false] indica se il keystore è utilizzabile anche come repository di chiavi segrete
  73.      *
  74.      * Un disponibile in HSM.example
  75.      *
  76.      **/
  77.    
  78.     private HashMap<String, HSMKeystore> hsmKeystoreMapIDtoConfig = new HashMap<>();
  79.    
  80.     private HashMap<String, String> hsmKeystoreMapKeystoreTypeLabelToID = new HashMap<>();
  81.    
  82.     private HSMManager(File f, boolean throwNotExists, Logger log, boolean accessKeystore) throws UtilsException {
  83.         String prefixFile = "File '"+f.getAbsolutePath()+"'";
  84.         if(!f.exists()) {
  85.             if(throwNotExists) {
  86.                 throw new UtilsException(prefixFile+" not exists");
  87.             }
  88.         }
  89.         else {
  90.             if(!f.canRead()) {
  91.                 throw new UtilsException(prefixFile+" cannot read");
  92.             }
  93.             Properties p = new Properties();
  94.             try {
  95.                 try(FileInputStream fin = new FileInputStream(f)){
  96.                     p.load(fin);
  97.                 }
  98.             }catch(Exception t) {
  99.                 throw new UtilsException(prefixFile+"; initialize error: "+t.getMessage(),t);
  100.             }
  101.             init(p, log, accessKeystore);
  102.         }
  103.     }
  104.     /**private HSMManager(Properties p, Logger log, boolean accessKeystore) throws UtilsException {
  105.         init(p, log, accessKeystore);
  106.     }*/
  107.     private void init(Properties p, Logger log, boolean accessKeystore) throws UtilsException {
  108.        
  109.         List<String> idKeystore = new ArrayList<>();
  110.        
  111.         if(p!=null && !p.isEmpty()) {
  112.             init(p, idKeystore);
  113.         }
  114.        
  115.         if(!idKeystore.isEmpty()) {
  116.             for (String idK : idKeystore) {
  117.                 init(p, log, accessKeystore, idK);      
  118.             }
  119.         }
  120.         else {
  121.             log.warn("La configurazione fornita per HSM non contiene alcun keystore");
  122.         }
  123.     }
  124.     private void init(Properties p, List<String> idKeystore) {
  125.         Enumeration<?> enKeys = p.keys();
  126.         while (enKeys.hasMoreElements()) {
  127.             Object object = enKeys.nextElement();
  128.             if(object instanceof String) {
  129.                 String key = (String) object;
  130.                 init(key, idKeystore);  
  131.             }
  132.         }
  133.     }
  134.     private void init(String key, List<String> idKeystore) {
  135.         if(key.startsWith(HSMCostanti.PROPERTY_PREFIX) && key.length()>(HSMCostanti.PROPERTY_PREFIX.length())) {
  136.             String tmp = key.substring(HSMCostanti.PROPERTY_PREFIX.length());
  137.             if(tmp!=null && tmp.contains(".")) {
  138.                 int indeoOf = tmp.indexOf(".");
  139.                 if(indeoOf>0) {
  140.                     String idK = tmp.substring(0,indeoOf);
  141.                     if(!idKeystore.contains(idK)) {
  142.                         idKeystore.add(idK);
  143.                     }
  144.                 }
  145.             }
  146.         }
  147.     }
  148.     private void init(Properties p, Logger log, boolean accessKeystore, String idK) throws UtilsException {
  149.         String prefix = HSMCostanti.PROPERTY_PREFIX + idK + ".";
  150.         PropertiesReader pReader = new PropertiesReader(p, true);
  151.         Properties pKeystore = pReader.readProperties_convertEnvProperties(prefix);
  152.         HSMKeystore hsmKeystore = new HSMKeystore(idK, pKeystore, log, accessKeystore);
  153.        
  154.         boolean alreadyExists = false;
  155.         for (String type : this.hsmKeystoreMapKeystoreTypeLabelToID.keySet()) {
  156.             if(hsmKeystore.getKeystoreTypeLabel().equalsIgnoreCase(type)) {
  157.                 alreadyExists = true;
  158.             }
  159.         }
  160.         if(alreadyExists) {
  161.             throw new UtilsException("Same keystore type label found for keystore '"+this.hsmKeystoreMapKeystoreTypeLabelToID.get(hsmKeystore.getKeystoreTypeLabel())+"' e '"+idK+"'");
  162.         }
  163.         this.hsmKeystoreMapKeystoreTypeLabelToID.put(hsmKeystore.getKeystoreTypeLabel(), idK);
  164.        
  165.         this.hsmKeystoreMapIDtoConfig.put(idK, hsmKeystore);
  166.         String d = "HSMKeystore "+idK+" registrato (keystoreType:"+hsmKeystore.getKeystoreTypeLabel()+")";
  167.         log.info(d);    
  168.     }
  169.    
  170.     public void providerInit(Logger log, boolean uniqueProviderInstance) throws UtilsException {
  171.         if(this.hsmKeystoreMapIDtoConfig!=null && !this.hsmKeystoreMapIDtoConfig.isEmpty()) {
  172.             for (Map.Entry<String,HSMKeystore> entry : this.hsmKeystoreMapIDtoConfig.entrySet()) {
  173.                 String idK = entry.getKey();
  174.                 HSMKeystore hsmKeystore = this.hsmKeystoreMapIDtoConfig.get(idK);
  175.                 hsmKeystore.init(log, uniqueProviderInstance);
  176.             }
  177.         }
  178.     }
  179.    
  180.     private HSMKeystore getHSMKeystore(String keystoreTypeLabel) throws UtilsException {
  181.         if(!this.hsmKeystoreMapKeystoreTypeLabelToID.containsKey(keystoreTypeLabel)) {
  182.             throw new UtilsException("Keystore type '"+keystoreTypeLabel+"' unknown");
  183.         }
  184.         String idK = this.hsmKeystoreMapKeystoreTypeLabelToID.get(keystoreTypeLabel);
  185.         if(!this.hsmKeystoreMapIDtoConfig.containsKey(idK)) {
  186.             throw new UtilsException("Keystore config for type '"+keystoreTypeLabel+"' unknown ? (id:"+idK+")");
  187.         }
  188.         return this.hsmKeystoreMapIDtoConfig.get(idK);
  189.     }
  190.    
  191.     public KeyStore getKeystore(String keystoreTypeLabel) throws UtilsException {
  192.         HSMKeystore hsmKeystore = getHSMKeystore(keystoreTypeLabel);
  193.         return hsmKeystore.getInstance();
  194.     }
  195.    
  196.     public boolean isUsableAsTrustStore(String keystoreTypeLabel) throws UtilsException {
  197.         HSMKeystore hsmKeystore = getHSMKeystore(keystoreTypeLabel);
  198.         return hsmKeystore.isUsableAsTrustStore();
  199.     }
  200.    
  201.     public boolean isUsableAsSecretKeyStore(String keystoreTypeLabel) throws UtilsException {
  202.         HSMKeystore hsmKeystore = getHSMKeystore(keystoreTypeLabel);
  203.         return hsmKeystore.isUsableAsSecretKeyStore();
  204.     }
  205.    
  206.     public List<String> getKeystoreTypes() {
  207.         List<String> l = new ArrayList<>();
  208.         if(!this.hsmKeystoreMapKeystoreTypeLabelToID.isEmpty()) {
  209.             for (String type : this.hsmKeystoreMapKeystoreTypeLabelToID.keySet()) {
  210.                 l.add(type);
  211.             }
  212.         }
  213.         return l;
  214.     }
  215.    
  216.     public boolean existsKeystoreType(String keystoreTypeLabel) {
  217.         if(keystoreTypeLabel==null) {
  218.             return false;
  219.         }
  220.         for (String type : this.hsmKeystoreMapKeystoreTypeLabelToID.keySet()) {
  221.             if(keystoreTypeLabel.equalsIgnoreCase(type)) {
  222.                 return true;
  223.             }
  224.         }
  225.         return false;
  226.     }
  227. }