PolicyDecisionPoint.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.utils.xacml;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.herasaf.xacml.core.SyntaxException;
import org.herasaf.xacml.core.api.PDP;
import org.herasaf.xacml.core.api.PolicyRetrievalPoint;
import org.herasaf.xacml.core.context.RequestMarshaller;
import org.herasaf.xacml.core.context.impl.RequestType;
import org.herasaf.xacml.core.context.impl.ResponseType;
import org.herasaf.xacml.core.context.impl.ResultType;
import org.herasaf.xacml.core.policy.Evaluatable;
import org.herasaf.xacml.core.policy.PolicyMarshaller;
import org.herasaf.xacml.core.policy.impl.EvaluatableIDImpl;
import org.herasaf.xacml.core.policy.impl.PolicyType;
import org.herasaf.xacml.core.simplePDP.MapBasedSimplePolicyRepository;
import org.herasaf.xacml.core.simplePDP.SimplePDPConfiguration;
import org.herasaf.xacml.core.simplePDP.SimplePDPFactory;
import org.herasaf.xacml.core.simplePDP.initializers.InitializerExecutor;
import org.openspcoop2.utils.LoggerWrapperFactory;
import org.slf4j.Logger;

/**
 * PolicyDecisionPoint
 *
 * @author Bussu Giovanni (bussu@link.it)
 * @author $Author$
 * @version $Rev$, $Date$
 */
public class PolicyDecisionPoint {

	private static final String SINGLE = "SINGLE";
	private Map<String, PDP> pdp;
	private boolean singlePDP;
	private Logger log;

	public static void runInitializers() {
		InitializerExecutor.runInitializers(); //Inizializza gli unmarshaller
	}
	
	public PolicyDecisionPoint() throws PolicyException {
		this(LoggerWrapperFactory.getLogger(PolicyDecisionPoint.class));
	}

	public PolicyDecisionPoint(Logger log) throws PolicyException {
		this(log, true);
	}

	public PolicyDecisionPoint(boolean singlePDP) throws PolicyException {
		this(LoggerWrapperFactory.getLogger(PolicyDecisionPoint.class), singlePDP);
	}

	public PolicyDecisionPoint(Logger log, boolean singlePDP) throws PolicyException {
		runInitializers();
		this.singlePDP=singlePDP;
		this.pdp = new HashMap<String, PDP>();
		this.log = log;
		if(singlePDP) {
			this.pdp.put(SINGLE, this.newPDP());
		}
	}
	
	private PDP newPDP() throws PolicyException {
		SimplePDPConfiguration configuration = new SimplePDPConfiguration();
		PolicyRetrievalPoint policyRetrievalPoint = new CachedMapBasedSimplePolicyRepository(this.log);
		configuration.setPolicyRetrievalPoint(policyRetrievalPoint);
		return SimplePDPFactory.getSimplePDP(configuration);
	}

	public List<ResultType> evaluate(String requestString) throws PolicyException {
		RequestType request;
		try {
			request = _unmarshalRequest(requestString);
		} catch (SyntaxException e) {
			throw new PolicyException(e);
		}
		return this._evaluate(request);
	}

	public List<ResultType> evaluate(XacmlRequest request) throws PolicyException {
		return this.evaluate(request.getXacmlRequest());
	}
	
	public List<ResultType> evaluate(RequestType request) throws PolicyException {
		return this._evaluate(request);
	}

	public static RequestType _unmarshalRequest(String requestString) throws PolicyException, SyntaxException {
		ByteArrayInputStream bais = null;
		try{
			InitializerExecutor.runInitializers(); //Inizializza gli unmarshaller
			bais = new ByteArrayInputStream(requestString.getBytes());
			return RequestMarshaller.unmarshal(bais);
		} finally {
			if(bais != null) {
				try {
					bais.close();
				} catch (IOException e) {}
			}
		}
	}

	public static boolean isValidRequest(String requestString) throws PolicyException {
		try{
			_unmarshalRequest(requestString);
		} catch(SyntaxException e) {
			return false;
		}
		return true;
	}

	public static Evaluatable _unmarshalPolicy(String policyString) throws PolicyException, SyntaxException {
		ByteArrayInputStream bais = null;
		try{
			bais = new ByteArrayInputStream(policyString.getBytes());
			InitializerExecutor.runInitializers(); //Inizializza gli unmarshaller
			return PolicyMarshaller.unmarshal(bais);
		} finally {
			if(bais != null) {
				try {
					bais.close();
				} catch (IOException e) {}
			}
		}
	}

	public void addPolicy(Evaluatable eval, String key) throws PolicyException {
		this._addPolicy(eval, key);
	}

	public void addPolicy(String policyString, String key) throws PolicyException {
		try {
			Evaluatable eval;
			eval = _unmarshalPolicy(policyString);
			((PolicyType)eval).setPolicyId(new EvaluatableIDImpl(key));
			this._addPolicy(eval, key);
		} catch (SyntaxException e) {
			throw new PolicyException(e);
		}
	}

	private void _addPolicy(Evaluatable eval, String key) throws PolicyException {
		
		EvaluatableIDImpl policyId = new EvaluatableIDImpl(key);
		((PolicyType)eval).setPolicyId(policyId);

		if(this.singlePDP) {
			PDP pdp = this.getPDP(SINGLE);
			MapBasedSimplePolicyRepository repo = (MapBasedSimplePolicyRepository)pdp.getPolicyRepository();
			repo.deploy(eval);
		} else {
			PDP newPDP = this.newPDP();
			MapBasedSimplePolicyRepository repo = (MapBasedSimplePolicyRepository)newPDP.getPolicyRepository();
			repo.deploy(eval);
			this.pdp.put(key, newPDP);
		}
	}

	private List<ResultType> _evaluate(RequestType request) throws PolicyException {
		PDP pdp = (this.singlePDP) ? this.getPDP(SINGLE): this.getPDP(request);
		ResponseType response = pdp.evaluate(request);
		return response.getResults();
	}

	private PDP getPDP(RequestType request) throws PolicyException {
		if(request == null) {
			throw new PolicyException("request non puo essere null");
		}
		
		if(request.getAction() == null) {
			throw new PolicyException("request.action non puo essere null");
		}
		
		if(request.getAction().getAttributes() == null || request.getAction().getAttributes().isEmpty()) {
			throw new PolicyException("request.action.attributes non puo essere null o vuoto");
		}
		
		if(request.getAction().getAttributes().get(0).getAttributeValues() == null || request.getAction().getAttributes().get(0).getAttributeValues().isEmpty()) {
			throw new PolicyException("request.action.attributes[0].attributeValues non puo essere null o vuoto");
		}
		
		if(request.getAction().getAttributes().get(0).getAttributeValues().get(0).getContent() == null || request.getAction().getAttributes().get(0).getAttributeValues().get(0).getContent().isEmpty()) {
			throw new PolicyException("request.action.attributes[0].attributeValues[0].content non puo essere null o vuoto");
		}
		
		String key = (String) request.getAction().getAttributes().get(0).getAttributeValues().get(0).getContent().get(0);
		return this.pdp.get(key);
	}
	
	private PDP getPDP(String key) {
		return this.pdp.get(key);
	}

}