/* 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.finder.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.URI;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.log4j.Logger;
import org.tmatesoft.svn.core.SVNException;
import eu.aniketos.securebpmn.xacml.SVNPDPConfig;
import eu.aniketos.securebpmn.xacml.finder.MySVNClient;
import eu.aniketos.securebpmn.xacml.finder.SVNPolicyFinderModule;
import com.sun.xacml.ConfigurationStore;
import com.sun.xacml.Constants;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.BagAttribute;
import com.sun.xacml.attr.StringAttribute;
import com.sun.xacml.attr.TypeIdentifierConstants;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.finder.AttributeFinderModule;
/**
*
* This module selects a bag of roles which are assigned
* to the subject in the current evaluation context.
* The role assignment is read from a configuration
* file roles.config at startup of the PDP. This is
* intended for simple tests, for a more sohpisticated
* setup use PDPStateModule which retrieves the current
* state of the assignment from a database at runtime.
*
*/
public class RoleFinderFileModule extends AttributeFinderModule {
public static final String USER_ROLES = "subject-roles",
CONFIG_FILE = "roles.config";
public static final URI USER_ROLES_URI = URI.create(USER_ROLES);
private Map<String, Collection<AttributeValue>> roleAssignments;
private ConfigurationStore conf;
private static final Logger logger = Logger.getLogger(RoleFinderFileModule.class);
public RoleFinderFileModule() {
// roleAssignments = readConfig(
// "burli:Role1;MasterGuru;UseCaseCaptain\n" +
// "maxi:fuzzi;Ruzzi;bulli\n" +
// "\n" +
// " \n" +
// "root:Role1;MasterGuru;Nurse;asdf"
// );
}
public boolean isDesignatorSupported() {
return true;
}
public void setConfigurationStore(ConfigurationStore conf) {
this.conf = conf;
if (this.conf != null) {
String config = null;
//check, if there is a svn client
MySVNClient svn = (MySVNClient) conf.getCustomAttr(SVNPDPConfig.SVN_CLIENT);
if ( svn != null ) {
try {
roleAssignments = readConfig(svn.getTextFile(SVNPolicyFinderModule.XACML_FOLDER + "/" + CONFIG_FILE));
} catch (SVNException e) {
logger.error("Could not retreive " + CONFIG_FILE + " for role configuration from SVN storage");
}
} else
//if there is no config from the svn
if ( config == null ) {
String baseDir = conf.getBaseDir();
File confFile = new File(baseDir + CONFIG_FILE);
logger.debug("Try to load role configuration from file: " + confFile.getAbsolutePath() + " (baseDir: " + baseDir + ")");
if ( confFile.exists() ) {
try {
roleAssignments = readConfig(new InputStreamReader(new FileInputStream(confFile)));
} catch (FileNotFoundException e) {
logger.error("File (role configuration) not found: " + confFile.getAbsolutePath() + ": " + e.getMessage(), e);
}
} else {
logger.error("File (role configuration) not found: " + confFile.getAbsolutePath());
}
}
} else {
logger.error("Did not retreive a valid configuration!");
}
}
private Map<String, Collection<AttributeValue>> readConfig(Reader in) {
Map<String, Collection<AttributeValue>> roleConfig
= new HashMap<String, Collection<AttributeValue>>();
BufferedReader reader = new BufferedReader(in);
String line = null, user, roles;
try {
for ( int i = 0; (line = reader.readLine()) != null ; ++i) {
if ( line.startsWith("#") || line.trim().length() == 0) {
//ignore comments;
continue;
}
int a = line.indexOf(":");
if ( a < 1 ) {
logger.warn("Error in line " + i + ": Did not find \":\"");
continue;
}
else {
user = line.substring(0, a).trim();
roles = line.substring(a + 1, line.length());
StringTokenizer tokenizer = new StringTokenizer(roles, ";");
Collection<AttributeValue> tmpCol = new Vector<AttributeValue>();
while ( tokenizer.hasMoreElements()) {
tmpCol.add(StringAttribute.getInstance(tokenizer.nextToken().trim()));
}
roleConfig.put(user, tmpCol);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return roleConfig;
}
/**
* helper function to read the configuration and save it into the local map
* @param config
* @return
*/
private Map<String, Collection<AttributeValue>> readConfig(String config) {
return readConfig(new StringReader(config));
}
@Override
public EvaluationResult findAttribute(URI category, URI attributeType,
URI attributeId, URI issuer,
EvaluationCtx context) {
if ( USER_ROLES_URI.equals(attributeId) &&
TypeIdentifierConstants.STRING_URI.equals(attributeType) ) {
String user = getUserID(context);
if ( user == null || roleAssignments.get(user) == null
|| roleAssignments.get(user).size() == 0 ) {
logger.warn("Found no role assignments for user " + user);
} else {
return new EvaluationResult(new BagAttribute(attributeType, roleAssignments.get(user)));
}
}
// if found nothing or not responsible, return empty bag
return new EvaluationResult(BagAttribute.createEmptyBag(attributeType));
}
private String getUserID(EvaluationCtx context) {
// if ( context instanceof AttrCachingEvaluationCtx ) {
// AttrCachingEvaluationCtx c_context = (AttrCachingEvaluationCtx) context;
// }
// if ( context instanceof EvaluationIdContext )
// more efficient impl
// else get "classical"
// if user == null
//logger.warn("Could not retreive the subject-id from the current context");
EvaluationResult result = context.getAttribute(Constants.SUBJECT_CAT, TypeIdentifierConstants.STRING_URI,
Constants.SUBJECT_ID, null);
if (! result.getAttributeValue().isBag()) {
logger.error("Did not retreive a bag after attribute search");
return null;
} else {
Iterator<AttributeValue> it = ((BagAttribute) result.getAttributeValue()).iterator();
String firstUser = null;
for ( int i = 0; it.hasNext(); ++i) {
String user = ((StringAttribute)it.next()).getValue();
if ( i > 0) {
logger.warn("Retreived more than subjectID: " + user + " which will be ignored");
} else {
firstUser = user;
}
}
return firstUser;
}
}
}