/* Copyright 2012-2015 SAP SE * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package eu.aniketos.securebpmn.xacml.pdpstate; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import eu.aniketos.securebpmn.xacml.api.SecurityError; import eu.aniketos.securebpmn.xacml.api.ErrorType; import eu.aniketos.securebpmn.xacml.api.ReasonType; import eu.aniketos.securebpmn.xacml.api.autho.AttributeIdentifier; import eu.aniketos.securebpmn.xacml.api.autho.IPDPStateManagement; import eu.aniketos.securebpmn.xacml.api.log.AccessControlRequest; import eu.aniketos.securebpmn.xacml.pdpstate.db.AttributeDBIdentifier; import eu.aniketos.securebpmn.xacml.pdpstate.db.HibernateUtil; public class PDPStateManagement implements IPDPStateManagement { private static PDPStateManagement instance; private PDPState pdpState; private HibernateUtil dbUtil; //private IPDP pdp; private Map<String, AttributeDBIdentifier> attributes = new HashMap<String, AttributeDBIdentifier>(); private Map<String, Dependency> dependencies = new HashMap<String, Dependency>(); //private Map<AttributeDBIdentifier, Assignment> dependencies_remove = new HashMap<AttributeDBIdentifier, Assignment>(); private static Logger logger = Logger.getLogger(PDPStateManagement.class); private static final String ATTRIBUTE = "attribute:", DEPENDENCY = "dependency:"; public static final String CONFFILE_NAME = "pdpStateDependencies.conf"; public static PDPStateManagement getInstance() { if ( instance == null ) { instance = new PDPStateManagement(); } return instance; } public static void main(String[] args) throws FileNotFoundException, IOException { Properties log4jProps = new Properties(); log4jProps.load(new BufferedInputStream(new FileInputStream(new File("src/test/log4j.properties")))); PropertyConfigurator.configure(log4jProps); PDPStateManagement.getInstance(); } private PDPStateManagement() { pdpState = PDPState.getInstance(); dbUtil = pdpState.getHibernateUtil(); try { // check if there is a conf file on the class path File confFile = new File(CONFFILE_NAME); if ( ! confFile.exists() ) { // try with conf before... confFile = new File("conf/" +CONFFILE_NAME); } if ( ! confFile.exists() ) { // try from mvn default test location confFile = new File("src/test/resources/" +CONFFILE_NAME); } if ( confFile.exists()) { logger.info("Reading PDPStateManagement configuration from " + confFile.getAbsolutePath()); readConfig(confFile); } else { logger.warn("Reading PDPStateManagement configuration from jar; You might define a more accurate " + CONFFILE_NAME); readConfig(this.getClass().getResourceAsStream("/" + CONFFILE_NAME)); } } catch (IOException e) { logger.error("Could not configuration file from PDPStateManagement: " + e.getMessage()); throw new RuntimeException(e); } } public Map<String, Dependency> getDependencies() { return Collections.unmodifiableMap(dependencies); } public void updatePDPState(AccessControlRequest request) throws SecurityError { //get resource and action URI resource = request.getResource(); Dependency assign = dependencies.get(resource.toString()); if ( assign == null ) { logger.error("For the resource (" + resource + ") defined in log " + request.getEvaluationId() + " no assignment is defined"); throw new SecurityError(ErrorType.CONFIGURATION_ERROR, ReasonType.PDE_ENGINE_ERROR, "Cannot update the PDPState: missing assignment definition"); } else { assign.writeStateChange(request, pdpState); } } private void readConfig(File confFile) throws IOException { readConfig(new FileInputStream(confFile)); } private void readConfig(InputStream stream) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); String key = null; AttributeDBIdentifier attrId = null; String line = null; while ( (line = reader.readLine()) != null ) { line = line.trim(); if ( ! (line.startsWith("#") || line.length() == 0 ) ) { if ( line.startsWith(ATTRIBUTE) ) { key = line.substring(ATTRIBUTE.length(), line.length()); try { attrId = readAttribute(reader); if ( attributes.containsKey(key)) { logger.warn("Overwriting attribute definition with key " + key); } attributes.put(key, attrId); } catch (URISyntaxException e) { logger.warn("Could not read attribute with key " + key + ": URISyntaxException: " + e.getMessage()); } catch (SyntaxError e) { logger.warn("Could not read attribute with key " + key + ": Syntax Error: " + e.getMessage()); } } else if ( line.startsWith(DEPENDENCY)) { key = "null"; try { key = line.substring(DEPENDENCY.length(), line.length()).trim(); Dependency assign = Dependency.readAssignment(key, reader, attributes, dbUtil); if (dependencies.containsKey(key)) { logger.warn("Overwriting dependency definition with key " + key); } this.dependencies.put(key, assign); } catch (SyntaxError e) { logger.warn("Could not read dependency with key " + key + ": SyntaxError: " + e.getMessage()); } } else { logger.warn("Ignoring misplace line " + line); } } } } private AttributeDBIdentifier readAttribute(BufferedReader reader) throws IOException, URISyntaxException, SyntaxError { URI category, attributeId, dataType, issuer; category = readValueLine(reader); dataType = readValueLine(reader); attributeId = readValueLine(reader); issuer = readValueLine(reader); AttributeIdentifier attr = new AttributeIdentifier(category, dataType, attributeId, issuer); return dbUtil.getAttributeDBIdentifier(attr); } private URI readValueLine(BufferedReader reader) throws IOException, URISyntaxException, SyntaxError { String line = reader.readLine().trim(); if ( line.startsWith("#") ) { return readValueLine(reader); } if ( "null".equals(line)) { return null; } if ( line.length() == 0 || line.startsWith(ATTRIBUTE) || line.startsWith(DEPENDENCY)) { throw new SyntaxError("Invalid line after attribute declaration: " + line); } return new URI(line); } // private void addDependency(String dependency) throws SyntaxError { // int m = dependency.indexOf("->"); // if ( m == -1 ) { // throw new SyntaxError("Missing assignment -> "); // } // String key = dependency.substring(0, m).trim(); // AttributeDBIdentifier dbKey = attributes.get(key); // // // if ( dbKey == null ) { // throw new SyntaxError("Attribute with key " + key + " is not defined so far"); // } // List<AttributeDBIdentifier> dependencies = new Vector<AttributeDBIdentifier>(); // StringTokenizer tokenizer = new StringTokenizer(dependency.substring(m + 2), ","); // while (tokenizer.hasMoreTokens()) { // String token = tokenizer.nextToken().trim(); // if ( ! (token.length() == 0) ) { // // some attributes may not depend on any other attribute // if ( dependencies.size() == 0 && "null".equals(token) ) { // this.dependenciesString.put(key, dependencies); // this.dependencies.put(dbKey, dependencies); // return; // } // AttributeDBIdentifier dependent = attributes.get(token); // if ( dependent == null ) { // throw new SyntaxError("Attribute with key " + dependent + " is not defined so far"); // } else { // dependencies.add(dependent); // } // } // } // if ( dependencies.size() == 0 ) { // throw new SyntaxError("No dependency is defined"); // } // this.dependenciesString.put(key, dependencies); // this.dependencies.put(dbKey, dependencies); //} // // }