DelegationPolicyImpl.java revision ba07e74da87b2caf40d3397e50523632daeb4cac
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2005 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
* 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: DelegationPolicyImpl.java,v 1.12 2010/01/16 06:35:25 dillidorai Exp $
*
* Portions Copyrighted 2011-2014 ForgeRock AS.
*/
/**
* The class <code>DelegationPolicyImpl</code> implements the interface
* <code>DelegationInterface</code> using OpenAM Policy
* Management and Evaluation APIs. It provides access control for access
* manager using the OpenAM's internal policy framework.
*/
public class DelegationPolicyImpl implements DelegationInterface, ServiceListener, IdEventListener, PolicyListener {
private static final String POLICY_REPOSITORY_REALM =
private static final char REPLACEMENT_FOR_COMMA = '^';
private static final String AUTHN_USERS_ID =
"id=All Authenticated Users,ou=role," +
private static final String AUTHENTICATED_USERS_SUBJECT =
"AuthenticatedUsers";
/**
* To configure the delegation cache size, specify the attribute
* "com.sun.identity.delegation.cache.size" in AMConfig.properties.
*/
private static final int DEFAULT_CACHE_SIZE = 20000;
/** delegation cache structure:
* usertokenidstr (key) ---> resource names (value)
* resource name (key) ---> arraylist of two elements (value)
* arraylist(0) contains a <code>Map</code> object of env parameters
* arraylist(1) contains a <code>PolicyDecision</code> regarding the
* resource.
* The cache is a LRU one and is updated based on subject change
* notification and policy change notification.
*/
private static int maxCacheSize = DEFAULT_CACHE_SIZE;
private static ServiceConfigManager scm;
private PolicyEvaluator pe;
/**
* Initialize (or configure) the <code>DelegationInterface</code>
* object. Usually it will be initialized with the environmrnt
* parameters set by the system administrator via Service management service.
*
* @param token <code>SSOToken</code> of an administrator
* @param configParams configuration parameters as a <code>Map</code>.
* The values in the <code>Map</code> is <code>java.util.Set</code>,
* which contains one or more configuration parameters.
*
* @throws DelegationException if an error occurred during
* initialization of <code>DelegationInterface</code> instance
*/
try {
// specifying cache size as 0 would virtually disable the delegation cache.
if (maxCacheSize < 0) {
}
}
// listen on delegation policy changes. once there is
// delegation policy change, we need to update the cache.
pe.addPolicyListener(this);
// listen on root realm subject changes.
idRepo.addEventListener(this);
"DelegationPolicyImpl: IdRepo event listener added "
+ "for root realm.");
}
// listen on sub realm subject changes.
idr.addEventListener(this);
"DelegationPolicyImpl: IdRepo event listener "
}
}
}
scm = new ServiceConfigManager(
//DelegationManager.DELEGATION_SERVICE, token);
/**
* listen on org config changes. once there is realm added,
* or removed, we need to add or remove listeners on the
* affected realm accordingly.
*/
scm.addListener(this);
} catch (Exception e) {
"DelegationPolicyImpl: initialize() failed");
throw new DelegationException(e);
}
}
/**
* Returns all the delegation privileges associated with a realm.
*
* @param token The <code>SSOToken</code> of the requesting user
* @param orgName The name of the realm from which the
* delegation privileges are fetched.
*
* @return <code>Set</code> of <code>DelegationPrivilege</code> objects
* associated with the realm.
*
* @throws SSOException invalid or expired single-sign-on token
* @throws DelegationException for any abnormal condition
*/
throws SSOException, DelegationException {
try {
// Need to check if user has "delegate" permissions for org
// Replace token with AdminToken
}
/* the name of the policy is in the form of
* orgName^^privilegeName, the privilegeName is the
* name of the delegation privilege that the policy
* is corresponding to. In case the orgName is in a
* DN format, the special char ',' is replaced to avoid
* saving problem.
*/
} else {
}
// converts the policy to its corresponding
// delegation privilege
}
}
}
}
return (privileges);
} catch (Exception e) {
"unable to get privileges from realm " + orgName);
throw new DelegationException(e);
}
}
/**
* Adds a delegation privilege to a specific realm. The permission will be
* added to the existing privilege in the event that this method is trying
* to add to an existing privilege.
*
* @param token The <code>SSOToken</code> of the requesting user
* @param orgName The name of the realm to which the delegation privilege
* is to be added.
* @param privilege The delegation privilege to be added.
*
* @throws SSOException invalid or expired single-sign-on token
* @throws DelegationException if any abnormal condition occurred.
*/
try {
// Need to check if user has "delegate" permissions for org
// Replace token with AdminToken
}
if (p != null) {
} else {
pm.replacePolicy(p);
}
} else {
}
}
} else {
}
} catch (Exception e) {
throw new DelegationException(e);
}
}
}
/**
* Removes a delegation privilege from a specific realm.
*
* @param token The <code>SSOToken</code> of the requesting user
* @param orgName The name of the realm from which the delegation
* privilege is to be removed.
* @param privilegeName The name of the delegation privilege to be removed.
*
* @throws SSOException invalid or expired single-sign-on token
* @throws DelegationException for any abnormal condition
*/
try {
// Need to check if user has "delegate" permissions for org
// Replace token with AdminToken
}
/* the name of the policy is in the form of
* orgName^^privilegeName, the privilegeName is the
* name of the delegation privilege that the policy
* is corresponding to. In case the orgName is in a
* DN format, the special char ',' is replaced to
* avoid saving problem.
*/
} else {
}
} catch (Exception e) {
throw new DelegationException(e);
}
}
/**
* Returns a set of selected subjects of specified types matching the
* pattern in the given realm. The pattern accepts "*" as the wild card for
* searching subjects. For example, "a*c" matches with any subject starting
* with a and ending with c.
*
* @param token The <code>SSOToken</code> of the requesting user
* @param orgName The name of the realm from which the subjects are fetched.
* @param types a set of subject types. e.g. ROLE, GROUP.
* @param pattern a filter used to select the subjects.
*
* @return a set of subjects associated with the realm.
*
* @throws SSOException invalid or expired single-sign-on token
* @throws DelegationException for any abnormal condition
*
* @return <code>Set</code> of universal Ids of the subjects associated
* with the realm.
*
* @throws SSOException invalid or expired single-sign-on token
* @throws DelegationException for any abnormal condition
*/
// All Authenticated Users would be returned only if pattern is *
}
"DelegationPolicyImpl.getSubjects(): types=" + types);
}
try {
"DelegationPolicyImpl.getSubjects(): " +
"supported subject types=" + supportedTypes);
}
ctrl.setRecursive(true);
}
}
}
}
}
}
return results;
} catch (IdRepoException ide) {
throw new DelegationException(ide);
}
}
/**
* Returns a set of realm names, based on the input parameter
* <code>organizationNames</code>, in which the "user" has some
* delegation permissions.
*
* @param token The <code>SSOToken</code> of the requesting user
* @param organizationNames a <code>Set</code> of realm names.
*
* @return a <code>Set</code> of realm names in which the user has some
* delegation permissions. It is a subset of
* <code>organizationNames</code>
*
* @throws SSOException invalid or expired single-sign-on token
* @throws DelegationException for any abnormal condition
*/
if ((organizationNames != null) &&
(!organizationNames.isEmpty())) {
}
}
}
return names;
}
/**
* Returns a boolean value; if a user has the specified
* permission returns true, false otherwise.
*
* @param token Single sign on token of the user evaluating permission.
* @param permission Delegation permission to be evaluated
* @param envParams Run-time environment parameters.
* @return the result of the evaluation as a boolean value
*
* @throws SSOException single-sign-on token invalid or expired.
* @throws DelegationException for any other abnormal condition.
*/
boolean result = false;
"DelegationPolicyImpl.isAllowed() is called");
}
&& (permission != null)) {
try {
"got delegation evaluation result from cache.");
}
} else {
// decision not found in the cache. compute it.
// add the result in the cache.
"put delegation evaluation result into cache.");
}
}
result = true;
result = false;
}
} else {
result = false;
}
}
}
} catch (PolicyException pe) {
throw new DelegationException(pe);
}
}
"DelegationPolicyImpl.isAllowed(): " +
"actions=" + actions +
" resource=" + resource +
" result is:" + result);
}
}
return result;
}
/**
* Returns a policy decision given a resource and the user's token,
* for the resource from the delegation cache.
* @param tokenIdStr <code>String</code> representation of user's token
* @param resource resource for which results are sought.
* @param envParams <code>Map</code> of environment params to be
* used to fetch the decisions.
* @return policy decision
*/
throws SSOException, DelegationException {
}
}
if (pdTTL > currentTime) {
return pd;
} else {
}
}
}
}
}
}
}
return null;
}
/**
* adds the data in the delegation cache.
* @param tokenIdStr <code>String</code> representation of user's token
* @param resource resource for which results are being put in cache.
* @param envParams <code>Map</code> of environment params applicable
for the decision.
* @param pd policy decision being cached.
*
*/
private void putResultIntoCache(String tokenIdStr, String resource, Map envParams, PolicyDecision pd)
throws SSOException, DelegationException {
synchronized (delegationCache) {
}
}
}
}
/**
* Cleans up the entire delegation cache, gets called
* when any identity gets changed in the repository.
*/
private void cleanupCache() {
}
}
// Clear the SubjectEvaluationCache on any identity changes if active and not empty.
if (SubjectEvaluationCache.subjectEvalCacheTTL > 0 && !SubjectEvaluationCache.subjectEvaluationCache.isEmpty()) {
"DelegationPolicyImpl.cleanupCache(): subjectEvaluationCache cleared");
}
}
}
/**
* Returns a set of permissions that a user has.
*
* @param token sso token of the user requesting permissions
* @param orgName The name of the realm from which the delegation
* permissions are fetched.
*
* @return a <code>Set</code> of permissions that a user has
*
* @throws SSOException if single-sign-on token invalid or expired
* @throws DelegationException for any other abnormal condition
*/
throws SSOException, DelegationException {
"DelegationPolicyImpl.getPermissions():"
+ "user sso token is null");
}
return perms;
}
try {
if (userIdentity == null) {
"DelegationPolicyImpl.getPermissions():"
+ "could not get user's identity from token");
}
return perms;
}
ctrl.setRecursive(true);
if (userIdentity.isMember(
subjectIdentity)) {
}
}
}
}
}
}
}
}
} catch (Exception e) {
throw new DelegationException(e);
}
return perms;
}
/**
* Converts a delegation privilege to a policy.
* @param pm PolicyManager object to be used to create the <code>Policy
* </code> object.
* @param priv <code>DelegationPrivilege</code> which needs to be
converted.
* @return policy object.
*/
private Policy privilegeToPolicy(
) throws DelegationException {
try {
/* the name of the policy is in the form of
* orgName^^privilegeName, the privilegeName is the
* name of the delegation privilege that the policy
* is corresponding to. In case the orgName is in a
* DN format, the special char ',' is replaced to
* avoid saving problem.
*/
} else {
}
int seqNum = 0;
if (permActions != null) {
}
}
if (seqNum != 0) {
}
seqNum++;
}
}
}
}
return policy;
} catch (Exception e) {
"unable to convert a privilege to a policy", e);
throw new DelegationException(e);
}
}
/**
* Converts a policy to a delegation privilege.
* @param policy policy to be converted
* @return priv <code>DelegationPrivilege</code> represting policy.
*/
throws DelegationException {
return null;
}
try {
// get policy name, which is the privilege name as well
// get privilege subjects
}
}
}
}
"SubjectValues=" + svalues);
}
// now try to get resource and action names
if (service.equalsIgnoreCase(
// parse the resource to get information
// required to construct a delegation permission
if (st.hasMoreTokens()) {
if (st.hasMoreTokens()) {
if (st.hasMoreTokens()) {
if (st.hasMoreTokens()) {
while (st.hasMoreTokens()) {
}
}
}
}
}
}
}
"DelegationPolicyImpl.policyToPrivilege(): "
+ "create DelegationPermission object with: "
+ "; configType=" + configType
+ "; subconfig=" + subconfigName
+ "; actions=" + actions);
}
}
}
}
} catch (Exception e) {
throw new DelegationException(e);
}
}
/**
* gets a resource string based on a delegation permission object
* @param perm <code>DelegationPermission</code> from which resource
name needs to be determined.
* @return resource name
*/
}
if (serviceName != null) {
}
}
if (configType != null) {
}
if (subConfigName != null) {
}
}
// The following three methods implement ServiceListener interface
/**
* This method will be invoked when a service's schema has been changed.
*
* @param serviceName name of the service
* @param version version of the service
*/
// NO-OP
}
/**
* This method will be invoked when a service's global configuration
* data has been changed. The parameter <code>groupName</code> denote
* the name of the configuration grouping (e.g. default) and
* <code>serviceComponent</code> denotes the service's sub-component
* that changed (e.g. <code>/NamedPolicy</code>, <code>/Templates</code>).
*
* @param serviceName name of the service.
* @param version version of the service.
* @param groupName name of the configuration grouping.
* @param serviceComponent name of the service components that
* changed.
* @param type change type, i.e., ADDED, REMOVED or MODIFIED.
*/
// NO-OP
}
/**
* This method will be invoked when a service's organization
* configuration data has been changed. The parameters orgName,
* groupName and serviceComponent denotes the organization name,
* configuration grouping name and service's sub-component that
* are changed respectively.
*
* @param serviceName name of the service
* @param version version of the service
* @param orgName organization name as DN
* @param groupName name of the configuration grouping
* @param serviceComponent the name of the service components that
* changed
* @param type change type, i.e., ADDED, REMOVED or MODIFIED
*/
"DelegationPolicyImpl: org config changed: " + orgName);
}
synchronized(idRepoListeners) {
try {
idRepo.addEventListener(this);
"DelegationPolicyImpl: IdRepo event listener"
}
} catch (Exception e) {
"DelegationPolicyImpl: failed to process " +
"organization config changes. ", e);
}
}
"DelegationPolicyImpl: IdRepo event listener"
}
}
}
}
// The following four methods implement IdEventListener interface
/**
* This method is called back for all identities that are
* modified in a repository.
* @param universalId Universal Identifier of the identity.
*/
"DelegationPolicyImpl: changed universalId=" + universalId);
}
cleanupCache();
}
/**
* This method is called back for all identities that are
* deleted from a repository. The universal identifier
* of the identity is passed in as an argument
* @param universalId Univerval Identifier
*/
"DelegationPolicyImpl: deleted universalId=" + universalId);
}
cleanupCache();
}
/**
* This method is called for all identities that are
* renamed in a repository. The universal identifier
* of the identity is passed in as an argument
* @param universalId Universal Identifier
*/
"DelegationPolicyImpl: renamed universalId=" + universalId);
}
cleanupCache();
}
/**
* The method is called when all identities in the repository are
* changed. This could happen due to a organization deletion or
* permissions change etc
*
*/
public void allIdentitiesChanged() {
"DelegationPolicyImpl: all identities changed.");
}
cleanupCache();
}
// The following two methods implement PolicyListener interface.
/** Gets the service type name for which this listener wants to get
* notifications
* @return delegation service name
*/
public String getServiceTypeName() {
return DelegationManager.DELEGATION_SERVICE;
}
/** This method is called by the policy framework whenever
* a policy is added, removed or changed. The notification
* is sent only if the policy has any rule that has the
* <code>serviceTypeName</code> of this listener
*
* @param policyEvent event object sent by the policy framework
* @see com.sun.identity.policy.PolicyEvent
*/
"DelegationPolicyImpl: delegation policy changed.");
}
cleanupCache();
}
/**
* Returns true if the user has delegation permissions for the
* organization
*/
// Construct delegation permission object
// Call DelegationEvaluator to handle super and internal users
}
}