/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2008 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: Entitlement.java,v 1.7 2010/01/25 23:48:14 veiming Exp $ * * Portions copyright 2010-2016 ForgeRock AS. */ package com.sun.identity.entitlement; import static org.forgerock.openam.entitlement.PolicyConstants.SUPER_ADMIN_SUBJECT; import static org.forgerock.openam.entitlement.utils.EntitlementUtils.getApplicationService; import com.sun.identity.entitlement.interfaces.ResourceName; import com.sun.identity.shared.JSONUtils; import java.security.Principal; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.security.auth.Subject; import org.forgerock.openam.entitlement.PolicyConstants; import org.forgerock.openam.ldap.LDAPUtils; import org.forgerock.openam.utils.CollectionUtils; import org.json.JSONException; import org.json.JSONObject; /** * This class encapsulates entitlement of a subject. *

* Example of how to use this class *

 *     Set set = new HashSet();
 *     set.add("GET");
 *     Evaluator evaluator = new Evaluator(adminToken);
 *     boolean isAllowed = evaluator.hasEntitlement(subject,
 *         new Entitlement("http://www.sun.com/example", set),
 *         Collections.EMPTY_MAP);
 * 
* Or do a sub tree search like this. *
 *     Evaluator evaluator = new Evaluator(adminToken);
 *     List<Entitlement> entitlements = evaluator.getEntitlements(
 *         subject, "http://www.sun.com", Collections.EMPTY_MAP, true);
 *     for (Entitlement e : entitlements) {
 *         String resource = e.getResourceNames();
 *         boolean isAllowed =((Boolean)e.getActionValue("GET")).booleanValue();
 *         ...
 *     }
 * 
*/ public class Entitlement { private String name; private String applicationName = ApplicationTypeManager.URL_APPLICATION_TYPE_NAME; private Set resourceNames; private Set requestedResourceNames; private Map actionValues; private Map> advices; private Map> attributes; private Application application; private long timeToLive = Long.MAX_VALUE; /** * Creates an entitlement object with default service name. */ public Entitlement() { } public Entitlement(JSONObject jo) throws JSONException { name = (String) jo.opt("name"); applicationName = (String) jo.opt("applicationName"); resourceNames = JSONUtils.getSet(jo, "resourceNames"); actionValues = JSONUtils.getMapStringBoolean(jo, "actionsValues"); advices = JSONUtils.getMapStringSetString(jo, "advices"); attributes = JSONUtils.getMapStringSetString(jo, "attributes"); } /** * Creates an entitlement object. * * @param resourceNames Resource names. * @param actionNames Set of action names. */ public Entitlement(Set resourceNames, Set actionNames) { setResourceNames(resourceNames); setActionNames(actionNames); } /** * Creates an entitlement object. * * @param resourceName Resource name. * @param actionNames Set of action names. */ public Entitlement(String resourceName, Set actionNames) { setResourceName(resourceName); setActionNames(actionNames); } /** * Creates an entitlement object. * * @param applicationName Application name. * @param resourceName Resource name. * @param actionNames Set of action names. */ public Entitlement(String applicationName, String resourceName, Set actionNames) { setApplicationName(applicationName); setResourceName(resourceName); setActionNames(actionNames); } /** * Creates an entitlement object. * * @param resourceName Resource namess. * @param actionValues Map of action name to set of values. */ public Entitlement(String resourceName, Map actionValues) { setResourceName(resourceName); setActionValues(actionValues); } /** * Creates an entitlement object. * * @param applicationName applicationName * @param resourceName Resource namess. * @param actionValues Map of action name to set of values. */ public Entitlement(String applicationName, String resourceName, Map actionValues) { setApplicationName(applicationName); setResourceName(resourceName); setActionValues(actionValues); } /** * Creates an entitlement object. * * @param applicationName Application name. * @param resourceNames Resource names. * @param actionValues Map of action name to set of values. */ public Entitlement(String applicationName, Set resourceNames, Map actionValues) { setApplicationName(applicationName); setResourceNames(resourceNames); setActionValues(actionValues); } /** * Sets the name of the entitlement * @param name the name of the entitlement */ public void setName(String name) { this.name = name; } /** * Returns the name of the entitlement * @return the name of the entitlement */ public String getName() { return this.name; } /** * Sets resource names. * * @param resourceNames Resource Names. */ public void setResourceNames(Set resourceNames) { this.resourceNames = resourceNames; } /** * Returns resource names. * * @return resource names. */ public Set getResourceNames() { return resourceNames; } /** * Sets resource name. * * @param resourceName Resource Name. */ public void setResourceName(String resourceName) { Set rn = new HashSet(); rn.add(resourceName); setResourceNames(rn); } /** * Returns resource name. * * @return resource names. */ public String getResourceName() { if (resourceNames == null || resourceNames.isEmpty()) { return null; } return resourceNames.iterator().next(); } /** * Sets the non normalised resource names. * * @param requestedResourceNames Non normalised resource names. */ public void setRequestedResourceNames(Set requestedResourceNames) { this.requestedResourceNames = requestedResourceNames; } /** * Returns non normalised resource names. If this has not been set the resource names (which is most * probably normalised) will be returned. * * @return Non normalised resource names or if that has not been set, the normalised resource names. */ public Set getRequestedResourceNames() { if (requestedResourceNames == null || requestedResourceNames.isEmpty()) { return getResourceNames(); } return requestedResourceNames; } /** * Sets non normalised resource name. * * @param requestedResourceName Non normalised resource name. */ public void setRequestedResourceName(String requestedResourceName) { setRequestedResourceNames(Collections.singleton(requestedResourceName)); } /** * Returns non normalised resource name. If this has not been set the resource name (which is most * probably normalised) will be returned. * * @return Non normalised resource name or if that has not been set, the normalised resource name. */ public String getRequestedResourceName() { if (requestedResourceNames == null || requestedResourceNames.isEmpty()) { return getResourceName(); } return requestedResourceNames.iterator().next(); } /** * Returns application name. * * @return application name. */ public String getApplicationName() { return applicationName; } /** * Sets application name. * * @param applicationName application name. */ public void setApplicationName(String applicationName) { this.applicationName = applicationName; } /** * Sets action name * * @param actionName Action name. */ public void setActionName(String actionName) { actionValues = new HashMap(); actionValues.put(actionName, Boolean.TRUE); } /** * Sets action names * * @param actionNames Set of action names. */ public void setActionNames(Set actionNames) { actionValues = new HashMap(); for (String i : actionNames) { actionValues.put(i, Boolean.TRUE); } } /** * Sets action values map. * * @param actionValues Action values. */ public void setActionValues(Map actionValues) { this.actionValues = new HashMap(actionValues); } /** * Returns action value. * * @param name Name of the action. * @return action values. */ public Boolean getActionValue(String name) { return actionValues.get(name); } /** * Returns action values. * * @return action values. */ public Map getActionValues() { return actionValues; } /** * Returns action values. * * @param name Name of the action. * @return action values. */ public Set getActionValues(String name) { Object o = actionValues.get(name); if (o instanceof Set) { return (Set) o; } Set set = new HashSet(); set.add(o); return set; } /** * Sets advices. * * @param advices Advices. */ public void setAdvices(Map> advices) { this.advices = advices; } /** * Returns advices. * * @return Advices. */ public Map> getAdvices() { return advices; } /** * @return Whether this entitlement has any advice. */ public boolean hasAdvice() { return advices != null && !advices.isEmpty(); } /** * Sets attributes. * * @param attributes Attributes. */ public void setAttributes(Map> attributes) { this.attributes = attributes; } /** * Returns attributes. * * @return Attributes. */ public Map> getAttributes() { return attributes; } /** * Sets this entitlements TTL * * @param ttl The TTL to set */ public void setTTL(long ttl) { this.timeToLive = ttl; } /** * Returns the TTL * * @return The TTL in ms */ public long getTTL() { return this.timeToLive; } /** * Returns a set of resource names that match the given resource. * * @param adminSubject Admin Subject. * @param realm Realm Name * @param subject Subject who is under evaluation. * @param applicationName application name. * @param resourceName Resource name. * @param environment Environment parameters. * @return a set of resource names that match the given resource. * @throws EntitlementException if resource names cannot be returned. */ public Set evaluate( Subject adminSubject, String realm, Subject subject, String applicationName, String resourceName, Set actionNames, Map> environment, boolean recursive) throws EntitlementException { if (CollectionUtils.isNotEmpty(actionNames)) { boolean passedActionFound = false; for (String actionName : actionNames) { if (actionValues.keySet().contains(actionName)) { passedActionFound = true; break; } } if (!passedActionFound) { return Collections.emptySet(); } } return getMatchingResources(adminSubject, realm, subject, applicationName, resourceName, recursive); } protected Set getMatchingResources( Subject adminSubject, String realm, Subject subject, String applicationName, String resourceName, boolean recursive ) throws EntitlementException { if ((resourceNames == null) || resourceNames.isEmpty()) { return Collections.EMPTY_SET; } if (!this.applicationName.endsWith(applicationName)) { return Collections.EMPTY_SET; } ResourceName resComparator = getResourceComparator(adminSubject, realm); Set matched = new HashSet(); Set resources = (subject != null) ? tagswapResourceNames(subject, resourceNames) : resourceNames; for (String r : resources) { if (!recursive) { if (resComparator instanceof RegExResourceName) { ResourceMatch match = resComparator.compare( resourceName, r, true); if (match.equals(ResourceMatch.EXACT_MATCH) || match.equals(ResourceMatch.SUPER_RESOURCE_MATCH) || match.equals(ResourceMatch.WILDCARD_MATCH)) { matched.add(r); } } else { ResourceMatch match = resComparator.compare(r, resourceName, false); if (match.equals(ResourceMatch.EXACT_MATCH)) { matched.add(r); } else { match = resComparator.compare(resourceName, r, true); if (match.equals(ResourceMatch.WILDCARD_MATCH)) { matched.add(r); } } } } else { if (resComparator instanceof RegExResourceName) { ResourceMatch match = resComparator.compare(r, resourceName, true); if (!match.equals(ResourceMatch.NO_MATCH)) { matched.add(r); } } else { ResourceMatch match = resComparator.compare(resourceName, r, true); if (match.equals(ResourceMatch.WILDCARD_MATCH) || match.equals(ResourceMatch.SUB_RESOURCE_MATCH)) { matched.add(r); } else { match = resComparator.compare(r, resourceName, false); if (match.equals(ResourceMatch.EXACT_MATCH) || match.equals(ResourceMatch.SUPER_RESOURCE_MATCH)) { matched.add(r); } } } } } return matched; } private Set tagswapResourceNames(Subject sbj, Set set) throws EntitlementException { if (sbj == null) { return set; } Set resources = new HashSet(); Set userIds = new HashSet(); Set principals = sbj.getPrincipals(); if (!principals.isEmpty()) { for (Principal p : principals) { String pName = p.getName(); if (LDAPUtils.isDN(pName)) { userIds.add(LDAPUtils.rdnValueFromDn(pName)); } else { userIds.add(pName); } } } if (!userIds.isEmpty()) { for (String r : set) { for (String uid : userIds) { resources.add(r.replaceAll("\\$SELF", uid)); } } } return resources; } /** * Returns string representation of the object * @return string representation of the object */ @Override public String toString() { String s = null; try { JSONObject jo = toJSONObject(); s = (jo == null) ? super.toString() : jo.toString(2); } catch (JSONException joe) { PolicyConstants.DEBUG.error("Entitlement.toString()", joe); } return s; } /** * Returns JSONObject mapping of the object * @return JSONObject mapping of the object * @throws JSONException if can not map to JSONObject */ public JSONObject toJSONObject() throws JSONException { JSONObject jo = new JSONObject(); jo.put("name", name); jo.put("applicationName", applicationName); if (resourceNames != null) { jo.put("resourceNames", resourceNames); } if (actionValues != null) { jo.put("actionsValues", actionValues); } if (advices != null) { jo.put("advices", advices); } if (attributes != null) { jo.put("attributes", attributes); } return jo; } /** * Returns true if the passed in object is equal to this object * @param obj object to check for equality * @return true if the passed in object is equal to this object */ @Override public boolean equals(Object obj) { boolean equalled = true; if (obj == null) { return false; } if (!getClass().equals(obj.getClass())) { return false; } Entitlement object = (Entitlement) obj; if (name == null) { if (object.getName() != null) { return false; } } else { // name not null if ((object.getName()) == null) { return false; } else if (!name.equals(object.getName())) { return false; } } if (applicationName == null) { if (object.getApplicationName() != null) { return false; } } else { // serviceName not null if ((object.getApplicationName()) == null) { return false; } else if (!applicationName.equals(object.getApplicationName())) { return false; } } if (resourceNames == null) { if (object.getResourceNames() != null) { return false; } } else { // resourceNames not null if ((object.getResourceNames()) == null) { return false; } else if (!resourceNames.equals(object.getResourceNames())) { return false; } } if (actionValues == null) { if ((object.getActionValues() != null) && !object.getActionValues().isEmpty()) { return false; } } else { // actionValues not null if ((object.getActionValues()) == null) { return false; } else if (!actionValues.equals(object.getActionValues())) { return false; } } if (advices == null) { if ((object.getAdvices() != null) && !object.getAdvices().isEmpty()) { return false; } } else { // advices not null if ((object.getAdvices()) == null) { return false; } else if (!advices.equals(object.getAdvices())) { return false; } } if (attributes == null) { if ((object.getAttributes() != null) && !object.getAttributes().isEmpty()) { return false; } } else { // attributes not null if ((object.getAttributes()) == null) { return false; } else if (!attributes.equals(object.getAttributes())) { return false; } } return equalled; } /** * Returns hash code of the object * @return hash code of the object */ @Override public int hashCode() { int code = 0; if (name != null) { code += name.hashCode(); } if (applicationName != null) { code += applicationName.hashCode(); } if (resourceNames != null) { code += resourceNames.hashCode(); } if (actionValues != null) { code += actionValues.hashCode(); } if (advices != null) { code += advices.hashCode(); } if (attributes != null) { code += attributes.hashCode(); } return code; } /** * Returns resource search indexes. * * @param adminSubject Admin Subject. * @param realm Realm Name * @return resource search indexes. */ public ResourceSearchIndexes getResourceSearchIndexes( Subject adminSubject, String realm ) throws EntitlementException { ResourceSearchIndexes result = null; ApplicationType applicationType = getApplication(adminSubject, realm).getApplicationType(); for (String r : resourceNames) { ResourceSearchIndexes rsi = applicationType.getResourceSearchIndex(r, realm); if (result == null) { result = rsi; } else { result.addAll(rsi); } } return result; } /** * Returns resource save indexes. * * @param adminSubject Admin Subject. * @param realm Realm Name * @return resource save indexes. */ public ResourceSaveIndexes getResourceSaveIndexes( Subject adminSubject, String realm ) throws EntitlementException { ResourceSaveIndexes result = null; Application application1 = getApplication(adminSubject, realm); // application can be null if the referred privilege is removed. // get the application from root realm if (application1 == null) { application1 = getApplication(adminSubject, "/"); } if (application1 != null) { ApplicationType applicationType = application1.getApplicationType(); if (resourceNames != null) { for (String r : resourceNames) { ResourceSaveIndexes rsi = applicationType.getResourceSaveIndex(r); if (result == null) { result = rsi; } else { result.addAll(rsi); } } } } return result; } /** * Sets this entitlement's current application to null. * For ensuring that we read the Application fresh from its store next time we access it. */ public void clearCache() { this.application = null; } /** * Returns application for this entitlement. * * @param adminSubject Admin Subject. * @param realm Realm Name * @return application for this entitlement. */ public Application getApplication(Subject adminSubject, String realm) throws EntitlementException { if (application == null) { application = getApplicationService(SUPER_ADMIN_SUBJECT, realm).getApplication(applicationName); } if (application == null) { PolicyConstants.DEBUG.error("Entitlement.getApplication null" + "realm=" + realm + " applicationname=" + applicationName); } return application; } ResourceName getResourceComparator(Subject adminSubject, String realm) throws EntitlementException { final Application application = getApplication(SUPER_ADMIN_SUBJECT, realm); if (application == null) { throw new EntitlementException(EntitlementException.NO_SUCH_APPLICATION, applicationName); } return application.getResourceComparator(); } /** * Canonicalizes resource name before persistence. * * @param adminSubject Admin Subject. * @param realm Realm Name */ public void canonicalizeResources(Subject adminSubject, String realm) throws EntitlementException { ResourceName resComp = getResourceComparator(adminSubject, realm); if ((resourceNames != null) && !resourceNames.isEmpty()) { Set temp = new HashSet(); for (String r : resourceNames) { temp.add(resComp.canonicalize(r)); } resourceNames = temp; } } }