InfoMittenteFormatUtils.java

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

package org.openspcoop2.pdd.logger.info;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.openspcoop2.core.config.constants.TipoAutenticazione;
import org.openspcoop2.core.id.IDSoggetto;
import org.openspcoop2.pdd.core.autenticazione.ApiKeyUtilities;
import org.openspcoop2.protocol.engine.utils.NamingUtils;
import org.openspcoop2.utils.certificate.CertificateUtils;
import org.openspcoop2.utils.certificate.PrincipalType;

/**
 * InfoMittenteFormatUtils
 * 
 * @author Andrea Poli (apoli@link.it)
 * @author $Author$
 * @version $Rev$, $Date$
 *
 */
public class InfoMittenteFormatUtils {
	
	private InfoMittenteFormatUtils() {}

	public static String getRichiedente(DatiMittente infoDatiMittente) {
		
		/**
		 * Logica:
		 * - prevale l'utente descritto in forma umana (username);
		 * - altrimenti prevale un eventuale applicativo identificato (registrato su GovWay) dando precedenza ad un applicativo token rispetto ad un applicativo di trasporto;
		 * - altrimenti prevalgono le informazioni di un eventuale token presente rispetto al trasporto; se si tratta di client credentials (subject non presente o client_id=subject) prevale l'informazione sul client-id altrimenti quella sul subject.
		 */
		
		// 1) Username del Token
		String sTokenUsername = infoDatiMittente.getTokenUsername();
		if(StringUtils.isNotEmpty(sTokenUsername)) {
			return sTokenUsername;
		}
		
		// 2) Applicativo Token identificato tramite ClientID
		String sTokenClient = infoDatiMittente.getTokenClient();
		if(StringUtils.isNotEmpty(sTokenClient)) {
			return sTokenClient;
		}
		
		// 2b) Applicativo Token identificato tramite PDND
		String sTokenClientPdndOrganizationName = infoDatiMittente.getPdndOrganizationName();
		if(StringUtils.isNotEmpty(sTokenClientPdndOrganizationName)) {
			return sTokenClientPdndOrganizationName;
		}
		
		// 3) Applicativo Fruitore
		String sApplicativoFruitore = infoDatiMittente.getServizioApplicativoFruitore();
		if(StringUtils.isNotEmpty(sApplicativoFruitore)) {
			return sApplicativoFruitore;
		}
			
		// 4) ClientId/Subject/Issuer del Token
		String sTokenClientId = infoDatiMittente.getTokenClientId();
		String sTokenSubject = infoDatiMittente.getTokenSubject();
		boolean clientCredentialsFlow = false;
		if(StringUtils.isNotEmpty(sTokenClientId)) {
			clientCredentialsFlow = (sTokenSubject==null) || (StringUtils.isEmpty(sTokenSubject)) || (sTokenSubject.equals(sTokenClientId));
		}
				
		// 4a) Client ID, per il caso di ClientCredential
		if(clientCredentialsFlow &&
			StringUtils.isNotEmpty(sTokenClientId)) {
			return sTokenClientId;
		}
		
		// 4b) Subject/Issuer del Token
		if(StringUtils.isNotEmpty(sTokenSubject)) {
			
			String sTokenIssuer = infoDatiMittente.getTokenIssuer();
			if(StringUtils.isNotEmpty(sTokenIssuer)) {
				return sTokenSubject + NamingUtils.LABEL_DOMINIO + sTokenIssuer;
			}
			else {
				return sTokenSubject;
			}
		}
		
		// 4c) Client ID, per il caso diverso da ClientCredential
		if(!clientCredentialsFlow &&
			StringUtils.isNotEmpty(sTokenClientId)) {
			return sTokenClientId;
		}
		
		// 5) Credenziali dell'autenticazione di trasporto
		// volutamente uso l'id autenticato.
		// se l'api è pubblica non deve essere visualizzata questa informazione!
		String sTrasporto = getRichiedenteTrasporto(infoDatiMittente);
		if(sTrasporto!=null) {
			return sTrasporto;
		}
						
		return null;
		
	}
	
	private static String getRichiedenteTrasporto(DatiMittente infoDatiMittente) {
		String sTrasportoMittente = infoDatiMittente.getTrasportoMittente();
		String sTipoTrasportoMittente = infoDatiMittente.getTipoTrasportoMittente();
		if(StringUtils.isNotEmpty(sTrasportoMittente) && StringUtils.isNotEmpty(sTipoTrasportoMittente)) {
			if(sTipoTrasportoMittente.endsWith("_"+TipoAutenticazione.SSL.getValue())) {
				return getRichiedenteTrasportoSSLEngine(sTrasportoMittente);
			}
			else {
				return sTrasportoMittente;
			}
		}
		return null;
	}
	private static String getRichiedenteTrasportoSSLEngine(String sTrasportoMittente) {
		try {
			Map<String, List<String>> l = CertificateUtils.getPrincipalIntoMap(sTrasportoMittente, PrincipalType.SUBJECT);
			if(l!=null && !l.isEmpty()) {
				List<String> cnList = getCNList(l);
				if(cnList!=null && !cnList.isEmpty()) {
					StringBuilder bfList = new StringBuilder();
					for (String s : cnList) {
						if(bfList.length()>0) {
							bfList.append(", ");
						}
						bfList.append(s);
					}
					return bfList.toString();
				}
			}
			return sTrasportoMittente;
		}catch(Exception t) {	
			return sTrasportoMittente;
		}
	}
	private static List<String> getCNList(Map<String, List<String>> l){
		List<String> cnList = l.get("CN");
		if(cnList==null || cnList.isEmpty()) {
			cnList = l.get("cn");
		}
		if(cnList==null || cnList.isEmpty()) {
			cnList = l.get("Cn");
		}
		if(cnList==null || cnList.isEmpty()) {
			cnList = l.get("cN");
		}
		return cnList;
	}
	
	public static String getIpRichiedente(DatiMittente infoDatiMittente) {
		
		String t = infoDatiMittente.getTransportClientAddress();
		if(StringUtils.isNotEmpty(t)) {
			return t;
		}
		
		String s = infoDatiMittente.getSocketClientAddress();
		if(StringUtils.isNotEmpty(s)) {
			return s;
		}
		
		return null;
		
	}
	
	public static String getLabelRichiedenteConFruitore(DatiMittente infoDatiMittente) {
		StringBuilder bf = new StringBuilder();
		
		String richiedente = getRichiedente(infoDatiMittente);
		if(StringUtils.isNotEmpty(richiedente)) {
			bf.append(richiedente);	
		}
		
		String sTokenClient = infoDatiMittente.getTokenClient();
		if(StringUtils.isNotEmpty(sTokenClient)) {
			
			// dominio di un applicativo client
			processLabelRichiedenteConFruitoreTokenClient(infoDatiMittente, bf);
			
		}
		else {
			
			// dominio del soggetto fruitore
			processLabelRichiedenteConFruitore(infoDatiMittente, bf, richiedente);
			
		}
		
		return bf.toString();
	}
	
	private static void processLabelRichiedenteConFruitoreTokenClient(DatiMittente infoDatiMittente, StringBuilder bfParam) {
		if(infoDatiMittente.getTokenClientSoggettoFruitore()!=null &&
				infoDatiMittente.getTokenClientTipoSoggettoFruitore()!=null && infoDatiMittente.getTokenClientNomeSoggettoFruitore()!=null) {
			
			boolean addFruitore = true;
			
			IDSoggetto idSoggettoFruitore = new IDSoggetto(infoDatiMittente.getTokenClientTipoSoggettoFruitore(), infoDatiMittente.getTokenClientNomeSoggettoFruitore());
			
			if(org.openspcoop2.core.transazioni.constants.PddRuolo.DELEGATA.equals(infoDatiMittente.getPddRuolo())) {
				addFruitore = 
						/**(idSoggettoFruitore==null) ||*/ 
						(infoDatiMittente.getSoggettoOperativo()==null) || (!infoDatiMittente.getSoggettoOperativo().equals(idSoggettoFruitore.toString()));
			}
			
			if(addFruitore) {
				if(bfParam.length()>0) {
					bfParam.append(NamingUtils.LABEL_DOMINIO);
				}
				
				bfParam.append(infoDatiMittente.getTokenClientSoggettoFruitore());	
			}
		}
	}
	
	private static void processLabelRichiedenteConFruitore(DatiMittente infoDatiMittente, StringBuilder bfParam, String richiedente) {
		String sFruitore = infoDatiMittente.getSoggettoFruitore();
		if(StringUtils.isNotEmpty(sFruitore)) {

			boolean addFruitore = true;
						
			if(org.openspcoop2.core.transazioni.constants.PddRuolo.APPLICATIVA.equals(infoDatiMittente.getPddRuolo())) {
				
				processLabelRichiedenteConFruitorePortaApplicativa(infoDatiMittente, bfParam, richiedente);
				
			}
			else if(org.openspcoop2.core.transazioni.constants.PddRuolo.DELEGATA.equals(infoDatiMittente.getPddRuolo()) &&
					(infoDatiMittente.getSoggettoOperativo()!=null && StringUtils.isNotEmpty(infoDatiMittente.getTipoSoggettoFruitore()) && StringUtils.isNotEmpty(infoDatiMittente.getNomeSoggettoFruitore())) 
				) {
			
				IDSoggetto idSoggettoFruitore = new IDSoggetto(infoDatiMittente.getTipoSoggettoFruitore(), infoDatiMittente.getNomeSoggettoFruitore());
				addFruitore = !infoDatiMittente.getSoggettoOperativo().equals(idSoggettoFruitore.toString());
			
			}
			
			if(addFruitore) {
				if(bfParam.length()>0) {
					bfParam.append(NamingUtils.LABEL_DOMINIO);
				}
				
				bfParam.append(sFruitore);	
			}
		}
	}
	
	private static void processLabelRichiedenteConFruitorePortaApplicativa(DatiMittente infoDatiMittente, StringBuilder bfParam, String richiedente) {
		// L'AppId di un soggetto è già il soggetto. L'informazione sarebbe ridondante.
		String sTrasportoMittente = infoDatiMittente.getTrasportoMittente();
		if(richiedente!=null && sTrasportoMittente!=null && richiedente.equals(sTrasportoMittente)) { // se e' stato selezionato l'appId
			String sTipoTrasportoMittente = infoDatiMittente.getTipoTrasportoMittente();
			if(sTipoTrasportoMittente!=null && StringUtils.isNotEmpty(sTipoTrasportoMittente) && 
					sTipoTrasportoMittente.endsWith("_"+TipoAutenticazione.APIKEY.getValue()) &&
				// autenticazione api-key
				(!sTrasportoMittente.contains(ApiKeyUtilities.APPLICATIVO_SOGGETTO_SEPARATOR)) 
				&&
				bfParam.length()>0
				){
				// appId di un soggetto
				bfParam.setLength(0); // svuoto il buffer poichè aggiungo solo il soggetto
			}
		}
	}
	
}