GestoreAutorizzazioneContenutiBuiltIn.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.core.autorizzazione;

  21. import java.util.List;
  22. import java.util.Map;

  23. import org.apache.commons.lang.StringUtils;
  24. import org.openspcoop2.core.config.Proprieta;
  25. import org.openspcoop2.core.config.utils.ConfigUtils;
  26. import org.openspcoop2.message.OpenSPCoop2Message;
  27. import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
  28. import org.openspcoop2.pdd.core.PdDContext;
  29. import org.openspcoop2.pdd.core.dynamic.DynamicUtils;
  30. import org.openspcoop2.pdd.logger.OpenSPCoop2Logger;
  31. import org.openspcoop2.utils.SortedMap;
  32. import org.openspcoop2.utils.regexp.RegularExpressionEngine;
  33. import org.slf4j.Logger;

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

  42.     private boolean autorizzato = true;
  43.     private String errorMessage = null;
  44.     public boolean isAutorizzato() {
  45.         return this.autorizzato;
  46.     }

  47.     public String getErrorMessage() {
  48.         return this.errorMessage;
  49.     }
  50.    
  51.     public void process(OpenSPCoop2Message msg, AbstractDatiInvocazione datiInvocazione, PdDContext pddContext,
  52.             List<Proprieta> regole) throws Exception {
  53.        
  54.         Logger log = OpenSPCoop2Logger.getLoggerOpenSPCoopCore();
  55.        
  56.         /* Costruisco dynamic Map */
  57.         boolean bufferMessage_readOnly =  OpenSPCoop2Properties.getInstance().isReadByPathBufferEnabled();
  58.         Map<String, Object> dynamicMap = DynamicUtils.buildDynamicMap(msg, pddContext, datiInvocazione.getBusta(), log, bufferMessage_readOnly);
  59.        
  60.        
  61.         /* Analisi regole di autorizzazione */
  62.        
  63.         if(regole==null || regole.size()<=0) {
  64.             throw new Exception("Non sono state definite regole di autorizzazione contenuto");
  65.         }
  66.        
  67.         SortedMap<List<String>> map = ConfigUtils.toSortedListMap(regole);
  68.         if(map==null || map.isEmpty()) {
  69.             throw new Exception("Non sono state definite regole di autorizzazione contenuto");
  70.         }
  71.        
  72.         //System.out.println("\n\n@ ===== AUTH CONTENUTI =====");
  73.        
  74.         List<String> keys = map.keys();
  75.         for (String risorsa : keys) {
  76.            
  77.             List<String> expectedValues = map.get(risorsa);
  78.            
  79.             if(expectedValues!=null && !expectedValues.isEmpty()) {
  80.                
  81.                 for (String expectedValue : expectedValues) {
  82.            
  83.                     //System.out.println("check '"+risorsa+"'='"+expectedValue+"'");
  84.                    
  85.                     if(risorsa==null) {
  86.                         throw new Exception("Trovata una regola di autorizzazione senza risorsa");
  87.                     }
  88.                     risorsa=risorsa.trim();
  89.                    
  90.                     if(risorsa.startsWith("#")) {
  91.                         // commento
  92.                         continue;
  93.                     }
  94.                    
  95.                     if(expectedValue==null) {
  96.                         throw new Exception("Trovata una regola di autorizzazione senza valore atteso");
  97.                     }  
  98.                     expectedValue = expectedValue.trim();
  99.                    
  100.                     // Risolvo valore della risorsa
  101.                     String valoreRisorsa = null;
  102.                     try {
  103.                         valoreRisorsa = DynamicUtils.convertDynamicPropertyValue(risorsa, risorsa, dynamicMap, pddContext);
  104.                     }catch(Exception e) {
  105.                         String msgError = "Conversione valore della risorsa '"+risorsa+"' non riuscita: "+e.getMessage();
  106.                         if(CostantiAutorizzazione.AUTHZ_UNDEFINED.equalsIgnoreCase(expectedValue)) {
  107.                             // NOP: se non l'ho risolto significa che non esiste.... sotto nel controllo undefined quindi autorizzo
  108.                             //if(!e.getMessage().contains("not exists as key in map")) {
  109.                             //  
  110.                             //}
  111.                         }
  112.                         else {
  113.                             log.error(msgError, e);
  114.                             this.autorizzato = false;
  115.                             this.errorMessage = "Resource '"+risorsa+"' not verifiable; unprocessable dynamic value '"+expectedValue+"': "+e.getMessage();
  116.                             break;
  117.                             //throw new Exception(msgError,e);
  118.                         }
  119.                     }
  120.                    
  121.        
  122.                    
  123.                     if(CostantiAutorizzazione.AUTHZ_ANY_VALUE.equalsIgnoreCase(expectedValue)) {
  124.                        
  125.                         /** ANY VALUE */
  126.                        
  127.                         log.debug("Verifico valore della risorsa '"+risorsa+"' non sia null e non sia vuoto ...");
  128.                        
  129.                         // basta che abbia un valore not null
  130.                         if(valoreRisorsa==null || "".equals(valoreRisorsa)) {
  131.                             this.autorizzato = false;
  132.                             this.errorMessage = "Resource '"+risorsa+"' with unexpected empty value";
  133.                             break;
  134.                         }
  135.                     }
  136.                     else if(CostantiAutorizzazione.AUTHZ_UNDEFINED.equalsIgnoreCase(expectedValue)) {
  137.                        
  138.                         /** NOT PRESENT */
  139.                        
  140.                         log.debug("Verifico valore della risorsa '"+risorsa+"' sia null o sia vuoto ...");
  141.                        
  142.                         // basta che abbia un valore
  143.                         if(valoreRisorsa!=null && !"".equals(valoreRisorsa)) {
  144.                             this.autorizzato = false;
  145.                             this.errorMessage = "Unexpected resource '"+risorsa+"'";
  146.                             break;
  147.                         }
  148.                        
  149.                     }
  150.                     else if(
  151.                             (
  152.                                     expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_MATCH_PREFIX.toLowerCase())
  153.                                     ||
  154.                                     expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_FIND_PREFIX.toLowerCase())
  155.                                     ||
  156.                                     expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_NOT_MATCH_PREFIX.toLowerCase())
  157.                                     ||
  158.                                     expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_NOT_FIND_PREFIX.toLowerCase())
  159.                             )
  160.                             &&
  161.                             expectedValue.toLowerCase().endsWith(CostantiAutorizzazione.AUTHZ_REGEXP_SUFFIX.toLowerCase())) {
  162.                        
  163.                         /** REGULAR EXPRESSION MATCH/FIND */
  164.                        
  165.                         boolean match = expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_MATCH_PREFIX.toLowerCase())
  166.                                 ||
  167.                                 expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_NOT_MATCH_PREFIX.toLowerCase());
  168.                         boolean not = expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_NOT_MATCH_PREFIX.toLowerCase())
  169.                                 ||
  170.                                 expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_NOT_FIND_PREFIX.toLowerCase());
  171.                         String regexpPattern = null;
  172.                         if(match) {
  173.                             int length = -1;
  174.                             if(expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_MATCH_PREFIX.toLowerCase())) {
  175.                                 length = CostantiAutorizzazione.AUTHZ_REGEXP_MATCH_PREFIX.length();
  176.                             }
  177.                             else {
  178.                                 length = CostantiAutorizzazione.AUTHZ_REGEXP_NOT_MATCH_PREFIX.length();
  179.                             }
  180.                             if(expectedValue.length()<= (length+CostantiAutorizzazione.AUTHZ_REGEXP_SUFFIX.length()) ) {
  181.                                 throw new Exception("Resource '"+risorsa+"' configuration without expected regexp match");
  182.                             }
  183.                             regexpPattern = expectedValue.substring(length, (expectedValue.length()-CostantiAutorizzazione.AUTHZ_REGEXP_SUFFIX.length()));
  184.                         }
  185.                         else {
  186.                             int length = -1;
  187.                             if(expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_REGEXP_FIND_PREFIX.toLowerCase())) {
  188.                                 length = CostantiAutorizzazione.AUTHZ_REGEXP_FIND_PREFIX.length();
  189.                             }
  190.                             else {
  191.                                 length = CostantiAutorizzazione.AUTHZ_REGEXP_NOT_FIND_PREFIX.length();
  192.                             }
  193.                             if(expectedValue.length()<= (length+CostantiAutorizzazione.AUTHZ_REGEXP_SUFFIX.length()) ) {
  194.                                 throw new Exception("Resource '"+risorsa+"' configuration without expected regexp find");
  195.                             }
  196.                             regexpPattern = expectedValue.substring(length, (expectedValue.length()-CostantiAutorizzazione.AUTHZ_REGEXP_SUFFIX.length()));
  197.                         }
  198.                         regexpPattern = regexpPattern.trim();
  199.                         log.debug("Verifico valore dela risorsa '"+risorsa+"' tramite espressione regolare (match:"+match+") '"+regexpPattern+"' ...");
  200.                        
  201.                         // basta che un valore abbia match
  202.                         if(valoreRisorsa==null || StringUtils.isEmpty(valoreRisorsa)) {
  203.                             // questo controllo serve per evitare che venga lanciata l'eccezione dentro RegularExpressionEngine del contenuto vuoto
  204.                             this.autorizzato = false;
  205.                             this.errorMessage = "Unable to locate the resource '"+risorsa+"' or the resource is empty.";
  206.                             break;
  207.                         }
  208.                         boolean ok = match ? RegularExpressionEngine.isMatch(valoreRisorsa, regexpPattern) : RegularExpressionEngine.isFind(valoreRisorsa, regexpPattern);
  209.                         if(not) {
  210.                             if(ok) {
  211.                                 String tipo = match ? "match" : "find";
  212.                                 this.autorizzato = false;
  213.                                 this.errorMessage = "Resource '"+risorsa+"' with unexpected value '"+valoreRisorsa+"' (regExpr not "+tipo+" failed)";
  214.                                 break;
  215.                             }
  216.                         }
  217.                         else {
  218.                             if(!ok) {
  219.                                 String tipo = match ? "match" : "find";
  220.                                 this.autorizzato = false;
  221.                                 this.errorMessage = "Resource '"+risorsa+"' with unexpected value '"+valoreRisorsa+"' (regExpr "+tipo+" failed)";
  222.                                 break;
  223.                             }
  224.                         }
  225.                        
  226.                     }
  227.                     else {
  228.                    
  229.                         /** VALUE (con PLACEHOLDERS) */
  230.                        
  231.                         boolean not = false;
  232.                         if(
  233.                                 expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_NOT_PREFIX.toLowerCase())
  234.                                 &&
  235.                                 expectedValue.toLowerCase().endsWith(CostantiAutorizzazione.AUTHZ_NOT_SUFFIX.toLowerCase())) {
  236.                             not = true;
  237.                             if(expectedValue.length()<= (CostantiAutorizzazione.AUTHZ_NOT_PREFIX.length()+CostantiAutorizzazione.AUTHZ_NOT_SUFFIX.length()) ) {
  238.                                 throw new Exception("Resource '"+risorsa+"' configuration without value in not condition");
  239.                             }
  240.                             expectedValue = expectedValue.substring(CostantiAutorizzazione.AUTHZ_NOT_PREFIX.length(), (expectedValue.length()-CostantiAutorizzazione.AUTHZ_NOT_SUFFIX.length()));
  241.                         }
  242.                        
  243.                         boolean ignoreCase = false;
  244.                         if(
  245.                                 expectedValue.toLowerCase().startsWith(CostantiAutorizzazione.AUTHZ_IGNORE_CASE_PREFIX.toLowerCase())
  246.                                 &&
  247.                                 expectedValue.toLowerCase().endsWith(CostantiAutorizzazione.AUTHZ_IGNORE_CASE_SUFFIX.toLowerCase())) {
  248.                             ignoreCase = true;
  249.                             if(expectedValue.length()<= (CostantiAutorizzazione.AUTHZ_IGNORE_CASE_PREFIX.length()+CostantiAutorizzazione.AUTHZ_IGNORE_CASE_SUFFIX.length()) ) {
  250.                                 throw new Exception("Resource '"+risorsa+"' configuration without value in ignore case condition");
  251.                             }
  252.                             expectedValue = expectedValue.substring(CostantiAutorizzazione.AUTHZ_IGNORE_CASE_PREFIX.length(), (expectedValue.length()-CostantiAutorizzazione.AUTHZ_IGNORE_CASE_SUFFIX.length()));
  253.                         }
  254.                        
  255.                         try {
  256.                             expectedValue = DynamicUtils.convertDynamicPropertyValue(risorsa, expectedValue, dynamicMap, pddContext);
  257.                         }catch(Exception e) {
  258.                             String msgErrore = "Conversione valore per risorsa '"+risorsa+"' non riuscita (valore: "+expectedValue+"): "+e.getMessage();
  259.                             //throw new Exception(msgErrore,e);
  260.                             log.error(msgErrore, e);
  261.                             this.autorizzato = false;
  262.                             this.errorMessage = "Resource '"+risorsa+"' not verifiable; unprocessable dynamic value '"+expectedValue+"': "+e.getMessage();
  263.                             break;
  264.                         }
  265.                        
  266.                         if(expectedValue!=null) {
  267.                             boolean ok = false;
  268.                             if(expectedValue.contains(",")) {
  269.                                 String [] values = expectedValue.split(",");
  270.                                 for (int i = 0; i < values.length; i++) {
  271.                                     String v = values[i].trim();
  272.                                     if(v!=null) {
  273.                                         if(ignoreCase) {
  274.                                             if(v.equalsIgnoreCase(valoreRisorsa)) {
  275.                                                 ok = true;
  276.                                                 break;
  277.                                             }
  278.                                         }
  279.                                         else {
  280.                                             if(v.equals(valoreRisorsa)) {
  281.                                                 ok = true;
  282.                                                 break;
  283.                                             }
  284.                                         }
  285.                                     }
  286.                                 }
  287.                             }
  288.                             else {
  289.                                 if(ignoreCase) {
  290.                                     ok = expectedValue.equalsIgnoreCase(valoreRisorsa);
  291.                                 }
  292.                                 else {
  293.                                     ok = expectedValue.equals(valoreRisorsa);
  294.                                 }
  295.                             }
  296.                            
  297.                             if(not) {
  298.                                 if(ok) {
  299.                                     this.autorizzato = false;
  300.                                     this.errorMessage = "Resource '"+risorsa+"' with unauthorized value '"+valoreRisorsa+"'";
  301.                                     break;
  302.                                 }
  303.                             }
  304.                             else {
  305.                                 if(!ok) {
  306.                                     this.autorizzato = false;
  307.                                     this.errorMessage = "Resource '"+risorsa+"' with unexpected value '"+valoreRisorsa+"'";
  308.                                     break;
  309.                                 }
  310.                             }
  311.                         }
  312.                         else {
  313.                             if(valoreRisorsa!=null) {
  314.                                 this.autorizzato = false;
  315.                                 this.errorMessage = "Resource '"+risorsa+"' with unexpected value; expected null value";
  316.                                 break;
  317.                             }
  318.                         }
  319.                     }
  320.                 }
  321.                
  322.             }
  323.            
  324.         }
  325.        
  326.     }

  327. }