PDNDResolver.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.pdd.config;

  21. import java.io.Serializable;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Map;

  25. import org.openspcoop2.core.commons.CoreException;
  26. import org.openspcoop2.core.constants.Costanti;
  27. import org.openspcoop2.core.id.IDSoggetto;
  28. import org.openspcoop2.core.transazioni.utils.CredenzialiMittente;
  29. import org.openspcoop2.pdd.core.autenticazione.GestoreAutenticazione;
  30. import org.openspcoop2.pdd.core.keystore.KeystoreException;
  31. import org.openspcoop2.pdd.core.keystore.RemoteStoreProvider;
  32. import org.openspcoop2.pdd.core.token.InformazioniToken;
  33. import org.openspcoop2.pdd.core.token.TokenUtilities;
  34. import org.openspcoop2.pdd.core.transazioni.Transaction;
  35. import org.openspcoop2.pdd.core.transazioni.TransactionContext;
  36. import org.openspcoop2.pdd.core.transazioni.TransactionDeletedException;
  37. import org.openspcoop2.pdd.core.transazioni.TransactionNotExistsException;
  38. import org.openspcoop2.protocol.engine.SecurityTokenUtilities;
  39. import org.openspcoop2.protocol.sdk.Context;
  40. import org.openspcoop2.protocol.sdk.PDNDTokenInfo;
  41. import org.openspcoop2.protocol.sdk.PDNDTokenInfoDetails;
  42. import org.openspcoop2.protocol.sdk.ProtocolException;
  43. import org.openspcoop2.protocol.sdk.SecurityToken;
  44. import org.openspcoop2.protocol.sdk.state.RequestInfo;
  45. import org.openspcoop2.security.SecurityException;
  46. import org.openspcoop2.security.keystore.cache.GestoreKeystoreCache;
  47. import org.openspcoop2.utils.UtilsException;
  48. import org.openspcoop2.utils.certificate.remote.RemoteKeyType;
  49. import org.openspcoop2.utils.certificate.remote.RemoteStoreClientInfo;
  50. import org.openspcoop2.utils.certificate.remote.RemoteStoreConfig;
  51. import org.openspcoop2.utils.json.JSONUtils;

  52. import com.fasterxml.jackson.databind.JsonNode;

  53. /**    
  54.  * PDNDResolver
  55.  *
  56.  * @author Poli Andrea (poli@link.it)
  57.  * @author $Author$
  58.  * @version $Rev$, $Date$
  59.  */
  60. public class PDNDResolver {
  61.    
  62.     private Context context;
  63.     private List<RemoteStoreConfig> remoteStores;
  64.    
  65.     public PDNDResolver(Context context, List<RemoteStoreConfig> remoteStores) {
  66.         this.context = context;
  67.         this.remoteStores = remoteStores;
  68.     }
  69.    
  70.    
  71.     public boolean isRemoteStore(String name) {
  72.         return isRemoteStore(name, this.remoteStores);
  73.     }
  74.     public static boolean isRemoteStore(String name, List<RemoteStoreConfig> remoteStores) {
  75.         for (RemoteStoreConfig rsc : remoteStores) {
  76.             if(name.equals(rsc.getStoreName())) {
  77.                 return true;
  78.             }
  79.         }
  80.         return false;
  81.     }
  82.    
  83.     public RemoteStoreConfig getRemoteStoreConfig(String name, IDSoggetto idDominio) throws ProtocolException {
  84.         return getRemoteStoreConfig(name, idDominio, this.remoteStores);
  85.     }
  86.     public static RemoteStoreConfig getRemoteStoreConfig(String name, IDSoggetto idDominio, List<RemoteStoreConfig> remoteStores) throws ProtocolException {
  87.         for (RemoteStoreConfig rsc : remoteStores) {
  88.             if(name.equals(rsc.getStoreName())) {
  89.                 if(rsc.isMultitenant() && idDominio!=null && idDominio.getNome()!=null) {
  90.                     try {
  91.                         return rsc.newInstanceMultitenant(idDominio.getNome());
  92.                     }catch(Exception e){
  93.                         throw new ProtocolException(e.getMessage(),e);
  94.                     }
  95.                 }
  96.                 return rsc;
  97.             }
  98.         }
  99.         return null;
  100.     }
  101.    
  102.     public RemoteStoreConfig getRemoteStoreConfigByTokenPolicy(String name, IDSoggetto idDominio) throws ProtocolException {
  103.         return getRemoteStoreConfigByTokenPolicy(name, idDominio, this.remoteStores);
  104.     }
  105.     public static RemoteStoreConfig getRemoteStoreConfigByTokenPolicy(String name, IDSoggetto idDominio, List<RemoteStoreConfig> remoteStores) throws ProtocolException {
  106.         for (RemoteStoreConfig rsc : remoteStores) {
  107.             if(name.equals(rsc.getTokenPolicy())) {
  108.                 if(rsc.isMultitenant() && idDominio!=null && idDominio.getNome()!=null) {
  109.                     try {
  110.                         return rsc.newInstanceMultitenant(idDominio.getNome());
  111.                     }catch(Exception e){
  112.                         throw new ProtocolException(e.getMessage(),e);
  113.                     }
  114.                 }
  115.                 return rsc;
  116.             }
  117.         }
  118.         return null;
  119.     }
  120.    
  121.     public RemoteStoreConfig enrichTokenInfo(RequestInfo requestInfo, IDSoggetto idSoggetto,
  122.             InformazioniToken informazioniToken, SecurityToken securityTokenForContext) throws ProtocolException {
  123.         return enrichTokenInfo(requestInfo, false, false, idSoggetto,
  124.                 informazioniToken, securityTokenForContext);
  125.     }
  126.     public RemoteStoreConfig enrichTokenInfo(RequestInfo requestInfo, boolean sicurezzaMessaggio, boolean sicurezzaAudit, IDSoggetto idSoggetto) throws ProtocolException {
  127.         Object oInformazioniTokenNormalizzate = null;
  128.         if(this.context!=null) {
  129.             oInformazioniTokenNormalizzate = this.context.getObject(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_INFORMAZIONI_NORMALIZZATE);
  130.         }
  131.         InformazioniToken informazioniTokenNormalizzate = null;
  132.         if(oInformazioniTokenNormalizzate instanceof InformazioniToken) {
  133.             informazioniTokenNormalizzate = (InformazioniToken) oInformazioniTokenNormalizzate;
  134.         }
  135.        
  136.         SecurityToken securityTokenForContext = SecurityTokenUtilities.readSecurityToken(this.context);
  137.        
  138.         return enrichTokenInfo(requestInfo, sicurezzaMessaggio, sicurezzaAudit, idSoggetto,
  139.                 informazioniTokenNormalizzate, securityTokenForContext);
  140.     }
  141.     private RemoteStoreConfig enrichTokenInfo(RequestInfo requestInfo, boolean sicurezzaMessaggio, boolean sicurezzaAudit, IDSoggetto idSoggetto,
  142.             InformazioniToken informazioniToken, SecurityToken securityTokenForContext) throws ProtocolException {
  143.        
  144.         OpenSPCoop2Properties op2Properties = OpenSPCoop2Properties.getInstance();
  145.         RemoteStoreConfig rsc = null;
  146.         try {
  147.             if(op2Properties.isGestoreChiaviPDNDclientInfoEnabled()) {
  148.            
  149.                 rsc = getRemoteStoreConfig(idSoggetto);
  150.                 if(rsc==null) {
  151.                     return rsc;
  152.                 }
  153.                
  154.                 String clientId = null;
  155.                 if(informazioniToken!=null) {
  156.                     clientId = informazioniToken.getClientId();
  157.                 }
  158.                 if(clientId==null) {
  159.                     return rsc;
  160.                 }
  161.                
  162.                 // NOTA: il kid DEVE essere preso dall'eventuale token di integrità, poichè il kid nell'access token è sempre uguale ed è quello della PDND
  163.                 String kid = readKid(sicurezzaMessaggio, sicurezzaAudit, securityTokenForContext, clientId);
  164.                
  165.                 enrichTokenInfo(requestInfo, idSoggetto,
  166.                         informazioniToken, securityTokenForContext,
  167.                         rsc, clientId, kid);
  168.             }
  169.         }catch(Exception e) {
  170.             throw new ProtocolException(e.getMessage(),e);
  171.         }
  172.        
  173.         return rsc;
  174.     }
  175.    
  176.     private void enrichTokenInfo(RequestInfo requestInfo, IDSoggetto idSoggetto,
  177.             InformazioniToken informazioniToken, SecurityToken securityTokenForContext,
  178.             RemoteStoreConfig rsc, String clientId, String kid) throws KeystoreException, SecurityException, UtilsException, TransactionNotExistsException, CoreException, TransactionDeletedException {
  179.         /**if(kid.startsWith(REMOTE_STORE_KEY_KID_STARTS_WITH_CLIENT_ID)) {*/
  180.         Object oInfoPDND = null;
  181.         if(this.context!=null) {
  182.             oInfoPDND = this.context.getObject(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_INFORMAZIONI_PDND_CLIENT_READ);
  183.         }
  184.         if(oInfoPDND instanceof String) {
  185.             String s = (String) oInfoPDND;
  186.             if("true".equals(s)) {
  187.                 // chiamata fatta dalla validazione semantica dopo che la raccolta delle informazioni sulla PDND è già stata chiamata in seguito alla validazione del token
  188.                 // poiche' il kid non e' presente, e' inutile ri-effettuare la medesima invocazione
  189.                 return;
  190.             }
  191.         }
  192.         /**}*/
  193.        
  194.         enrichTokenInfo(securityTokenForContext, informazioniToken, requestInfo, rsc,
  195.                 kid, clientId);
  196.        
  197.         if(kid.startsWith(REMOTE_STORE_KEY_KID_STARTS_WITH_CLIENT_ID)) {
  198.             this.context.put(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_INFORMAZIONI_PDND_CLIENT_READ, "true");
  199.         }
  200.        
  201.         updateCredenzialiTokenPDND(requestInfo, idSoggetto, informazioniToken);
  202.     }
  203.    
  204.     private void updateCredenzialiTokenPDND(RequestInfo requestInfo, IDSoggetto idSoggetto, InformazioniToken informazioniToken) throws TransactionNotExistsException, CoreException, TransactionDeletedException {
  205.         String idTransazione = null;
  206.         if(this.context!=null) {
  207.             idTransazione = (String) this.context.getObject(Costanti.ID_TRANSAZIONE);
  208.         }
  209.         Transaction transaction = TransactionContext.getTransaction(idTransazione);
  210.        
  211.         CredenzialiMittente credenzialiMittente = transaction.getCredenzialiMittente();
  212.         if(credenzialiMittente==null) {
  213.             credenzialiMittente = new CredenzialiMittente();
  214.             transaction.setCredenzialiMittente(credenzialiMittente);
  215.         }
  216.        
  217.         try {
  218.             GestoreAutenticazione.updateCredenzialiTokenPDND(idSoggetto, "ModIValidator", idTransazione,
  219.                 informazioniToken, credenzialiMittente,
  220.                 null, "ModIValidator.credenzialiPDND", requestInfo,
  221.                 this.context);
  222.         }catch(Exception e) {
  223.             throw new CoreException(e.getMessage(),e);
  224.         }
  225.     }
  226.    
  227.    
  228.     private RemoteStoreConfig getRemoteStoreConfig(IDSoggetto idSoggetto) throws ProtocolException {
  229.         Object oTokenPolicy = null;
  230.         if(this.context!=null) {
  231.             oTokenPolicy = this.context.getObject(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_POLICY);
  232.         }
  233.         String tokenPolicy = null;
  234.         if(oTokenPolicy instanceof String) {
  235.             tokenPolicy = (String) oTokenPolicy;
  236.         }
  237.         if(tokenPolicy==null) {
  238.             return null;
  239.         }
  240.        
  241.         return this.getRemoteStoreConfigByTokenPolicy(tokenPolicy, idSoggetto);
  242.     }
  243.    
  244.     public static final String REMOTE_STORE_KEY_KID_STARTS_WITH_CLIENT_ID = "ClientId--";
  245.     private String readKid(boolean sicurezzaMessaggio, boolean sicurezzaAudit, SecurityToken securityTokenForContext, String clientId) throws UtilsException {
  246.         // NOTA: il kid DEVE essere preso dall'eventuale token di integrità, poichè il kid nell'access token è sempre uguale ed è quello della PDND
  247.         String kid = null;
  248.         if(sicurezzaMessaggio) {
  249.             kid = readKidFromTokenIntegrity(securityTokenForContext);
  250.         }
  251.         if(kid==null && sicurezzaAudit) {
  252.             kid = readKidFromTokenAudit(securityTokenForContext);
  253.         }
  254.         if(kid==null) {
  255.             // Altrimenti utilizzo la struttura dati per ospitare le informazioni sul clientId
  256.             kid = REMOTE_STORE_KEY_KID_STARTS_WITH_CLIENT_ID+clientId;
  257.         }
  258.         return kid;
  259.     }
  260.    
  261.     private String readKidFromTokenIntegrity(SecurityToken securityTokenForContext) throws UtilsException {
  262.         String kid = null;
  263.         if(securityTokenForContext!=null && securityTokenForContext.getIntegrity()!=null) {
  264.             kid = securityTokenForContext.getIntegrity().getKid();
  265.             if(kid==null) {
  266.                 kid = securityTokenForContext.getIntegrity().getHeaderClaim("kid");
  267.             }
  268.         }
  269.         return kid;
  270.     }
  271.     private String readKidFromTokenAudit(SecurityToken securityTokenForContext) throws UtilsException {
  272.         String kid = null;
  273.         if(securityTokenForContext!=null && securityTokenForContext.getAudit()!=null) {
  274.             kid = securityTokenForContext.getAudit().getKid();
  275.             if(kid==null) {
  276.                 kid = securityTokenForContext.getAudit().getHeaderClaim("kid");
  277.             }
  278.         }
  279.         return kid;
  280.     }
  281.    
  282.    
  283.     private void enrichTokenInfo(SecurityToken securityTokenForContext, InformazioniToken informazioniTokenNormalizzate, RequestInfo requestInfo, RemoteStoreConfig rsc,
  284.             String kid, String clientId) throws KeystoreException, SecurityException, UtilsException {
  285.         RemoteKeyType keyType = RemoteKeyType.JWK; // ignored
  286.         RemoteStoreProvider remoteStoreProvider = new RemoteStoreProvider(requestInfo, keyType);
  287.         RemoteStoreClientInfo rsci = GestoreKeystoreCache.getRemoteStoreClientInfo(requestInfo, kid, clientId, rsc, remoteStoreProvider, this.context);
  288.         if(rsci!=null &&
  289.             (rsci.getClientDetails()!=null || rsci.getOrganizationId()!=null || rsci.getOrganizationDetails()!=null)
  290.             ){
  291.             if(informazioniTokenNormalizzate.getPdnd()==null) {
  292.                 informazioniTokenNormalizzate.setPdnd(new HashMap<>());
  293.             }
  294.             if(rsci.getClientDetails()!=null) {
  295.                 JSONUtils jsonUtils = JSONUtils.getInstance();
  296.                 if(jsonUtils.isJson(rsci.getClientDetails())) {
  297.                     JsonNode root = jsonUtils.getAsNode(rsci.getClientDetails());
  298.                     PDNDTokenInfoDetails info = new PDNDTokenInfoDetails();
  299.                     info.setId(rsci.getClientId());
  300.                     info.setDetails(rsci.getClientDetails());
  301.                     enrichTokenInfoAddInClaims(jsonUtils, securityTokenForContext, informazioniTokenNormalizzate, root, PDNDTokenInfo.CLIENT_INFO, info);
  302.                 }
  303.             }
  304.             if(rsci.getOrganizationDetails()!=null) {
  305.                 JSONUtils jsonUtils = JSONUtils.getInstance();
  306.                 if(jsonUtils.isJson(rsci.getOrganizationDetails())) {
  307.                     JsonNode root = jsonUtils.getAsNode(rsci.getOrganizationDetails());
  308.                     PDNDTokenInfoDetails info = new PDNDTokenInfoDetails();
  309.                     info.setId(rsci.getOrganizationId());
  310.                     info.setDetails(rsci.getOrganizationDetails());
  311.                     enrichTokenInfoAddInClaims(jsonUtils, securityTokenForContext, informazioniTokenNormalizzate, root, PDNDTokenInfo.ORGANIZATION_INFO, info);
  312.                 }
  313.             }
  314.         }
  315.     }
  316.     private void enrichTokenInfoAddInClaims(JSONUtils jsonUtils, SecurityToken securityTokenForContext, InformazioniToken informazioniTokenNormalizzate, JsonNode root, String type,
  317.             PDNDTokenInfoDetails info) {
  318.         Map<String, Serializable> readClaims = jsonUtils.convertToSimpleMap(root);
  319.         if(!readClaims.isEmpty()) {
  320.             enrichTokenInfoAddInClaims(securityTokenForContext, informazioniTokenNormalizzate,
  321.                     type, info,
  322.                     readClaims);
  323.         }
  324.     }

  325.     private void enrichTokenInfoAddInClaims(SecurityToken securityTokenForContext, InformazioniToken informazioniTokenNormalizzate,
  326.             String type, PDNDTokenInfoDetails info,
  327.             Map<String, Serializable> readClaims) {
  328.         informazioniTokenNormalizzate.getPdnd().put(type,TokenUtilities.toHashMapSerializable(readClaims));
  329.         String prefix = PDNDTokenInfo.TOKEN_INFO_PREFIX_PDND+type+".";
  330.         Map<String, Serializable> readClaimsSerializable = new HashMap<>();
  331.         if(informazioniTokenNormalizzate.getClaims()!=null) {
  332.             for (Map.Entry<String,Serializable> entry : readClaims.entrySet()) {
  333.                 String key = prefix+entry.getKey();
  334.                 if(!informazioniTokenNormalizzate.getClaims().containsKey(key)) {
  335.                     informazioniTokenNormalizzate.getClaims().put(key, entry.getValue());
  336.                 }
  337.                 if(entry.getValue() instanceof Serializable) {
  338.                     readClaimsSerializable.put(entry.getKey(), entry.getValue());
  339.                 }
  340.             }
  341.         }
  342.        
  343.         info.setClaims(readClaimsSerializable);
  344.         if(securityTokenForContext!=null) {
  345.             if(securityTokenForContext.getPdnd()==null) {
  346.                 securityTokenForContext.setPdnd(new PDNDTokenInfo());
  347.             }
  348.             securityTokenForContext.getPdnd().setInfo(type, info);
  349.         }
  350.     }
  351.    
  352. }