/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.carbon.identity.entitlement.policy.finder;
import java.io.File;
import java.net.URI;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.caching.core.BaseCache;
import org.wso2.carbon.caching.core.entitlementpolicy.EntitlementPolicyCache;
import org.wso2.carbon.caching.core.entitlementpolicy.EntitlementPolicyCacheEntry;
import org.wso2.carbon.caching.core.entitlementpolicy.EntitlementPolicyCacheKey;
import org.wso2.carbon.identity.base.IdentityException;
import org.wso2.carbon.identity.entitlement.EntitlementException;
import org.wso2.carbon.identity.entitlement.policy.PolicyCollection;
import org.wso2.carbon.identity.entitlement.policy.PolicyStore;
import org.wso2.carbon.identity.entitlement.policy.PolicyStoreReader;
import com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.VersionConstraints;
import com.sun.xacml.combine.DenyOverridesPolicyAlg;
import com.sun.xacml.combine.FirstApplicablePolicyAlg;
import com.sun.xacml.combine.OnlyOneApplicablePolicyAlg;
import com.sun.xacml.combine.OrderedDenyOverridesPolicyAlg;
import com.sun.xacml.combine.OrderedPermitOverridesPolicyAlg;
import com.sun.xacml.combine.PermitOverridesPolicyAlg;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.PolicyFinderResult;
public class RegistryBasedPolicyFinder extends PolicyFinderModule {
private static final String DENY_OVERRIDE = "urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:deny-overrides";
private static final String PERMIT_OVERRIDE = "urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:permit-overrides";
private static final String FIRST_APPLICABLE = "urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable";
private static final String ONLY_ONE_APPLICABLE = "urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:only-one-applicable";
private static final String ORDERED_DENY_OVERRIDE = "urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:ordered-deny-overrides";
private static final String ORDERED_PERMIT_OVERRIDE = "urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:ordered-permit-overrides";
private static final String DEFAULT_POLICY_COMBINING_ALGO = "deny-overrides";
private static final String POLICY_COMBINING_ALGO = "urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:";
// the list of policy URLs passed to the constructor
private PolicyStoreReader policyReader;
// the map of policies
private PolicyCollection policies;
// the optional schema file
private File schemaFile = null;
private EntitlementPolicyCacheKey cacheKey;
private int hashOfPolicyCollection;
private static BaseCache entitlementPolicyCache = EntitlementPolicyCache.getInstance();
private String globalPolicyCombiningAlgorithm;
// the logger we'll use for all messages
private static Log log = LogFactory.getLog(RegistryBasedPolicyFinder.class);
// private static RegistryBasedPolicyFinder policyFinder = null;
/**
* Creates a RegistryBasedPolicyFinderthat provides access to the given collection of policies.
* Any policy that cannot be loaded will be noted in the log, but will not cause an error. The
* schema file used to validate policies is defined by the property
* PolicyReader.POLICY_SCHEMA_PROPERTY. If the retrieved property is null, then no schema
* validation will occur.
*
* @param policyReader Policy store reader for Registry
* @param tenantId tenantId to init the cache key value
*/
public RegistryBasedPolicyFinder(PolicyStoreReader policyReader, int tenantId) {
this.policyReader = policyReader;
this.cacheKey = new EntitlementPolicyCacheKey(tenantId);
String schemaName = System.getProperty(PolicyStoreReader.POLICY_SCHEMA_PROPERTY);
if (schemaName != null) {
schemaFile = new File(schemaName);
}
}
/**
* Creates a RegistryBasedPolicyFinder that provides access to the given collection of
* policyList based on the Registry.
*
* @param policyReader
* @param schemaName
*/
public RegistryBasedPolicyFinder(PolicyStoreReader policyReader, String schemaName) {
this.policyReader = policyReader;
this.cacheKey = new EntitlementPolicyCacheKey(11);
if (schemaName != null) {
schemaFile = new File(schemaName);
}
}
/**
* Always returns <code>true</code> since this module does support finding policies based on
* reference.
*
* @return true
*/
public boolean isIdReferenceSupported() {
return true;
}
/*
* (non-Javadoc)
*
* @see com.sun.xacml.finder.PolicyFinderModule#isRequestSupported()
*/
public boolean isRequestSupported() {
return true;
}
/*
* (non-Javadoc)
*
* @see com.sun.xacml.finder.PolicyFinderModule#init(com.sun.xacml.finder.PolicyFinder)
*/
public void init(PolicyFinder finder) {
AbstractPolicy[] policies;
PolicyCombiningAlgorithm algorithm;
try {
policies = policyReader.readPolicies();
globalPolicyCombiningAlgorithm = findPolicyCombiningAlgorithm();
if (globalPolicyCombiningAlgorithm == null) {
globalPolicyCombiningAlgorithm = DEFAULT_POLICY_COMBINING_ALGO;
}
algorithm = getPolicyCombiningAlgorithm(globalPolicyCombiningAlgorithm);
if (log.isDebugEnabled()) {
log.debug("Global XACML policy combining algorithm used " + globalPolicyCombiningAlgorithm);
}
this.policies = new PolicyCollection(algorithm);
for (int i = 0; i < policies.length; i++) {
if (!this.policies.addPolicy(policies[i])) {
if (log.isWarnEnabled()) {
log.warn(" Trying to load the same policy multiple times: "
+ policies[i].getId());
}
}
}
} catch (Exception e) {
log.error("Error while initializing RegistryBasedPolicyFinder", e);
}
hashOfPolicyCollection = this.policies.hashCode();
EntitlementPolicyCacheEntry cacheEntry = new EntitlementPolicyCacheEntry(this.policies.hashCode());
entitlementPolicyCache.addToCache(cacheKey, cacheEntry);
}
/*
* (non-Javadoc)
*
* @see com.sun.xacml.finder.PolicyFinderModule#findPolicy(java.net.URI, int,
* com.sun.xacml.VersionConstraints, com.sun.xacml.PolicyMetaData)
*/
public PolicyFinderResult findPolicy(URI idReference, int type, VersionConstraints constraints,
PolicyMetaData parentMetaData) {
EntitlementPolicyCacheEntry cacheEntry = (EntitlementPolicyCacheEntry)
entitlementPolicyCache.getValueFromCache(cacheKey);
if(cacheEntry != null){
if(cacheEntry.getEntitlementPolicyCacheEntry() != hashOfPolicyCollection ){
init(new PolicyFinder());
}
} else {
cacheEntry = new EntitlementPolicyCacheEntry(hashOfPolicyCollection);
entitlementPolicyCache.addToCache(cacheKey, cacheEntry);
}
AbstractPolicy policy = policies.getPolicy(idReference.toString(), type, constraints);
if (policy == null) {
return new PolicyFinderResult();
} else {
return new PolicyFinderResult(policy);
}
}
/*
* (non-Javadoc)
*
* @see com.sun.xacml.finder.PolicyFinderModule#findPolicy(com.sun.xacml.EvaluationCtx)
*/
public PolicyFinderResult findPolicy(EvaluationCtx context) {
AbstractPolicy policy;
try {
EntitlementPolicyCacheEntry cacheEntry = (EntitlementPolicyCacheEntry)
entitlementPolicyCache.getValueFromCache(cacheKey);
if(cacheEntry != null){
if(cacheEntry.getEntitlementPolicyCacheEntry() != hashOfPolicyCollection){
init(new PolicyFinder());
}
} else {
cacheEntry = new EntitlementPolicyCacheEntry(hashOfPolicyCollection);
entitlementPolicyCache.addToCache(cacheKey, cacheEntry);
}
policy = policies.getPolicy(context);
if (policy == null) {
return new PolicyFinderResult();
} else {
return new PolicyFinderResult(policy);
}
} catch (EntitlementException e) {
return new PolicyFinderResult(e.getStatus());
}
}
private PolicyCombiningAlgorithm getPolicyCombiningAlgorithm(String uri) throws IdentityException {
if (FIRST_APPLICABLE.equals(POLICY_COMBINING_ALGO + uri)) {
return new FirstApplicablePolicyAlg();
} else if (DENY_OVERRIDE.equals(POLICY_COMBINING_ALGO + uri)) {
return new DenyOverridesPolicyAlg();
} else if (PERMIT_OVERRIDE.equals(POLICY_COMBINING_ALGO + uri)) {
return new PermitOverridesPolicyAlg();
} else if (ONLY_ONE_APPLICABLE.equals(POLICY_COMBINING_ALGO + uri)) {
return new OnlyOneApplicablePolicyAlg();
} else if (ORDERED_DENY_OVERRIDE.equals(POLICY_COMBINING_ALGO + uri)) {
return new OrderedDenyOverridesPolicyAlg();
} else if (ORDERED_PERMIT_OVERRIDE.equals(POLICY_COMBINING_ALGO + uri)) {
return new OrderedPermitOverridesPolicyAlg();
}
throw new IdentityException("Unsupported policy algorithm " + uri);
}
public String findPolicyCombiningAlgorithm() {
try {
return policyReader.readPolicyCombiningAlgorithm();
} catch (IdentityException e) {
log.warn("Error occurs while finding policy combining algorithm");
}
return null;
}
public String getGlobalPolicyCombiningAlgorithm(){
return globalPolicyCombiningAlgorithm;
}
}