/*
* 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;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.core.AbstractAdmin;
import org.wso2.carbon.identity.base.IdentityException;
import org.wso2.carbon.identity.core.IdentityRegistryResources;
import org.wso2.carbon.identity.entitlement.dto.PolicyDTO;
import org.wso2.carbon.identity.entitlement.dto.PaginatedPolicySetDTO;
import org.wso2.carbon.identity.entitlement.internal.EntitlementServiceComponent;
import org.wso2.carbon.identity.entitlement.pdp.EntitlementEngine;
import org.wso2.carbon.identity.entitlement.policy.PolicyAdmin;
import org.wso2.carbon.identity.entitlement.policy.PolicyReader;
import org.wso2.carbon.identity.entitlement.policy.PolicyStore;
import org.wso2.carbon.identity.entitlement.policy.PolicyStoreReader;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.identity.entitlement.policy.finder.RegistryBasedPolicyFinder;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import com.sun.xacml.AbstractPolicy;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* Entitlement Admin Service Class
*/
public class EntitlementPolicyAdminService extends AbstractAdmin {
private final static String TEMPLATE_POLICY = "WSO2_TEMPLATE_POLICY";
private static final int DEFAULT_ITEMS_PER_PAGE = 15;
private static Log log = LogFactory.getLog(EntitlementPolicyAdminService.class);
/**
* This method persists a new XACML policy
*
* @param policy
* PolicyDTO object
* @throws org.wso2.carbon.identity.base.IdentityException
* throws if invalid policy or if policy with same id is exist
*/
public void addPolicy(PolicyDTO policy) throws IdentityException {
PolicyAdmin policyAdmin;
AbstractPolicy policyObj;
EntitlementEngine entitlementEngine = EntitlementEngine
.getInstance(getGovernanceUserRegistry(), CarbonContext.getCurrentContext().getTenantId());
policyObj = PolicyReader.getInstance(null, null).getPolicy(policy.getPolicy());
if (policyObj != null) {
policyAdmin = new PolicyAdmin(new PolicyStore(getGovernanceUserRegistry()));
policy.setPolicyId(policyObj.getId().toASCIIString());
// All the policies wont be active at the time been added.
policy.setActive(policy.isActive());
if (getPolicy(policy.getPolicyId()) != null) {
throw new IdentityException(
"An Entitlement Policy with the given ID already exists");
}
policyAdmin.addOrUpdatePolicy(policy);
entitlementEngine.getRegistryModule().init(null);
} else {
throw new IdentityException("Invalid Entitlement Policy");
}
}
/**
* This method finds the policy file from given registry path and adds the policy
*
* @param policyRegistryPath
* given registry path
* @throws org.wso2.carbon.identity.base.IdentityException
* throws when fails or registry error occurs
*/
public void importPolicyFromRegistry(String policyRegistryPath) throws IdentityException {
Registry registry;
PolicyDTO policyDTO = new PolicyDTO();
String policy = "";
BufferedReader bufferedReader = null;
InputStream inputStream = null;
// Finding from which registry by comparing prefix of resource path
String resourceUri = policyRegistryPath.substring(policyRegistryPath.lastIndexOf(':') + 1);
String registryIdentifier = policyRegistryPath.substring(0,
policyRegistryPath.lastIndexOf(':'));
if (IdentityRegistryResources.CONFIG_REGISTRY_IDENTIFIER.equals(registryIdentifier)) {
registry = getConfigSystemRegistry();
} else {
registry = getGovernanceUserRegistry();
}
try {
Resource resource = registry.get(resourceUri);
inputStream = resource.getContentStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String stringLine;
StringBuffer buffer = new StringBuffer(policy);
while ((stringLine = bufferedReader.readLine()) != null) {
buffer.append(stringLine);
}
policy = buffer.toString();
policyDTO.setPolicy(policy.replaceAll(">\\s+<", "><"));
addPolicy(policyDTO);
} catch (RegistryException e) {
throw new IdentityException("Registry Error occurs while reading policy from registry");
} catch (IOException e) {
throw new IdentityException("I/O Error occurs while reading policy from registry");
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
log.error("Error occurs while closing inputStream", e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error("Error occurs while closing inputStream", e);
}
}
}
}
/**
* This method paginates policies
*
* @param policyTypeFilter policy type to filter
* @param policySearchString policy search String
* @param pageNumber page number
* @return paginated and filtered policy set
* @throws org.wso2.carbon.identity.base.IdentityException
* throws
*/
public PaginatedPolicySetDTO getAllPolicies(String policyTypeFilter, String policySearchString,
int pageNumber) throws IdentityException {
PolicyStoreReader policyReader;
List<PolicyDTO> policyDTOList = new ArrayList<PolicyDTO>();
EntitlementEngine.getInstance(getGovernanceUserRegistry(), CarbonContext.getCurrentContext().getTenantId());
policyReader = new PolicyStoreReader(new PolicyStore(getGovernanceUserRegistry()));
PolicyDTO[] policyDTOs = policyReader.readAllPolicyDTOs();
for (PolicyDTO policyDTO : policyDTOs){
// Filter out services based on service type
if (!policyTypeFilter.equals("ALL") && !policyTypeFilter.equals(policyDTO.getPolicyType())) {
continue;
}
// Filter out services based on serviceSearchString
if (policySearchString != null && policySearchString.trim().length() > 0 ){
if(policyDTO.getPolicyId().toLowerCase().indexOf(policySearchString.toLowerCase()) == -1){
continue;
}
}
policyDTOList.add(policyDTO);
}
// Do the pagination and return the set of policies.
return doPaging(pageNumber, policyDTOList.toArray(new PolicyDTO[policyDTOList.size()]));
}
/**
* Get policy for given policy id
*
* @param policyId
* policy id
* @return returns policy
* @throws org.wso2.carbon.identity.base.IdentityException
* throws
*/
public PolicyDTO getPolicy(String policyId) throws IdentityException {
PolicyStoreReader policyReader = null;
EntitlementEngine.getInstance(getGovernanceUserRegistry(), CarbonContext.getCurrentContext().getTenantId());
if (TEMPLATE_POLICY.equals(policyId)) {
PolicyDTO policy = new PolicyDTO();
policy.setPolicy(EntitlementServiceComponent.getTemplatePolicy());
policy.setPolicyId(policyId);
return policy;
}
policyReader = new PolicyStoreReader(new PolicyStore(getGovernanceUserRegistry()));
return policyReader.readPolicyDTO(policyId);
}
/**
* Remove policy for given policy object
*
* @param policy
* policy object
* @throws org.wso2.carbon.identity.base.IdentityException
* throws
*/
public void removePolicy(PolicyDTO policy) throws IdentityException {
PolicyAdmin policyAdmin;
EntitlementEngine entitlementEngine = EntitlementEngine
.getInstance(getGovernanceUserRegistry(), CarbonContext.getCurrentContext().getTenantId());
policyAdmin = new PolicyAdmin(new PolicyStore(getGovernanceUserRegistry()));
policyAdmin.removePolicy(policy);
// Reload the policies to the memory.
entitlementEngine.getRegistryModule().init(null);
}
/**
* Updates given policy
*
* @param policy
* policy object
* @throws org.wso2.carbon.identity.base.IdentityException
* throws if invalid policy
*/
public void updatePolicy(PolicyDTO policy) throws IdentityException {
PolicyAdmin policyAdmin;
AbstractPolicy policyObj;
EntitlementEngine entitlementEngine = EntitlementEngine
.getInstance(getGovernanceUserRegistry(), CarbonContext.getCurrentContext().getTenantId());
policyObj = PolicyReader.getInstance(null, null).getPolicy(policy.getPolicy());
if (policyObj != null) {
policyAdmin = new PolicyAdmin(new PolicyStore(getGovernanceUserRegistry()));
policy.setPolicyId(policyObj.getId().toASCIIString());
policyAdmin.addOrUpdatePolicy(policy);
// Reload the policies to the memory.
entitlementEngine.getRegistryModule().init(null);
} else {
throw new IdentityException("Invalid Policy");
}
}
/**
* This method is used internally to do the pagination purposes.
*
* @param pageNumber
* page Number
* @param policySet
* set of policies
* @return PaginatedPolicySetDTO object containing the number of pages and the set of policies
* that reside in the given page.
*/
private PaginatedPolicySetDTO doPaging(int pageNumber, PolicyDTO[] policySet) {
PaginatedPolicySetDTO paginatedPolicySet = new PaginatedPolicySetDTO();
if (policySet.length == 0) {
paginatedPolicySet.setPolicySet(new PolicyDTO[0]);
return paginatedPolicySet;
}
String itemsPerPage = ServerConfiguration.getInstance().getFirstProperty("ItemsPerPage");
int itemsPerPageInt = DEFAULT_ITEMS_PER_PAGE;
if (itemsPerPage != null) {
itemsPerPageInt = Integer.parseInt(itemsPerPage);
}
int numberOfPages = (int) Math.ceil((double) policySet.length / itemsPerPageInt);
if (pageNumber > numberOfPages - 1) {
pageNumber = numberOfPages - 1;
}
int startIndex = pageNumber * itemsPerPageInt;
int endIndex = (pageNumber + 1) * itemsPerPageInt;
PolicyDTO[] returnedPolicySet = new PolicyDTO[itemsPerPageInt];
for (int i = startIndex, j = 0; i < endIndex && i < policySet.length; i++, j++) {
returnedPolicySet[j] = policySet[i];
}
paginatedPolicySet.setPolicySet(returnedPolicySet);
paginatedPolicySet.setNumberOfPages(numberOfPages);
return paginatedPolicySet;
}
/**
* This method is used get pre-defined data-types, functions, identifiers and algorithms related
* to XACML Policy
*
* @param resourceName
* Registry resource Name related to one bag of data
* @return data as String array
* @throws org.wso2.carbon.identity.base.IdentityException
* throws when registry error occurs
*/
public String[] getEntitlementPolicyDataFromRegistry(String resourceName)
throws IdentityException {
PolicyStore policyStoreAdmin;
List<String> entitlementPolicyResources = new ArrayList<String>();
Resource resource;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
policyStoreAdmin = new PolicyStore(EntitlementServiceComponent.getRegistryService().
getGovernanceSystemRegistry());
resource = policyStoreAdmin.getEntitlementPolicyResources(resourceName);
inputStream = resource.getContentStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String stringLine;
while ((stringLine = bufferedReader.readLine()) != null) {
entitlementPolicyResources.add(stringLine.trim());
}
} catch (IOException e) {
throw new IdentityException("Error occurs while reading resource content", e);
} catch (RegistryException e) {
throw new IdentityException("Error occurs while creating inputStream from registry "
+ "resource", e);
} catch (IdentityException e) {
throw new IdentityException("Error occurs while initializing PolicyStore", e);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
log.error("Error occurs while closing inputStream", e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error("Error occurs while closing inputStream", e);
}
}
}
return entitlementPolicyResources.toArray(new String[entitlementPolicyResources.size()]);
}
/**
* This methods returns the list of policy id available in PDP
* @return list of ids
* @throws IdentityException throws
*/
public String[] getAllPolicyIds() throws IdentityException {
List<String> policyIds = new ArrayList<String>();
PolicyStoreReader policyReader;
EntitlementEngine.getInstance(getGovernanceUserRegistry(), CarbonContext.getCurrentContext().getTenantId());
policyReader = new PolicyStoreReader(new PolicyStore(getGovernanceUserRegistry()));
for(PolicyDTO policyDTO : policyReader.readAllPolicyDTOs()){
policyIds.add(policyDTO.getPolicyId());
}
return policyIds.toArray(new String[policyIds.size()]);
}
/**
* Clears the decision cache.
*
* @throws IdentityException
*/
public void clearDecisionCache() throws IdentityException {
EntitlementEngine.getInstance(getGovernanceUserRegistry(),
CarbonContext.getCurrentContext().getTenantId()).clearDecisionCache();
}
/**
* Set policy combining algorithm globally
* @param policyCombiningAlgorithm policy combining algorithm as a String
* @throws IdentityException throws
*/
public void setGlobalPolicyAlgorithm(String policyCombiningAlgorithm) throws IdentityException {
PolicyStore policyStore;
EntitlementEngine entitlementEngine = EntitlementEngine
.getInstance(getGovernanceUserRegistry(), CarbonContext.getCurrentContext().getTenantId());
policyStore = new PolicyStore(getGovernanceUserRegistry());
policyStore.addPolicyCombiningAlgorithm(policyCombiningAlgorithm);
entitlementEngine.getRegistryModule().init(null);
}
/**
* Get globally defined policy combining algorithm
* @return policy combining algorithm as a String
* @throws IdentityException throws
*/
public String getGlobalPolicyAlgorithm() throws IdentityException {
RegistryBasedPolicyFinder policyFinder = EntitlementEngine.getInstance(getGovernanceUserRegistry(),
CarbonContext.getCurrentContext().getTenantId()).getRegistryModule();
if(policyFinder != null){
return policyFinder.getGlobalPolicyCombiningAlgorithm();
}
return null;
}
}