001/* 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: PolicyManager.java,v 1.19 2010/01/25 23:48:15 veiming Exp $ 026 * 027 * Portions Copyrighted 2011-2015 ForgeRock AS. 028 */ 029 030package com.sun.identity.policy; 031 032import java.io.ByteArrayInputStream; 033import java.net.MalformedURLException; 034import java.net.URL; 035import java.security.AccessController; 036import java.util.Collections; 037import java.util.Date; 038import java.util.HashMap; 039import java.util.HashSet; 040import java.util.Iterator; 041import java.util.Map; 042import java.util.Set; 043import java.util.concurrent.locks.Lock; 044 045import com.iplanet.am.sdk.AMCommonUtils; 046import com.iplanet.am.util.SystemProperties; 047import com.iplanet.sso.SSOException; 048import com.iplanet.sso.SSOToken; 049import com.iplanet.sso.SSOTokenManager; 050import com.sun.identity.entitlement.Application; 051import com.sun.identity.entitlement.ApplicationManager; 052import com.sun.identity.entitlement.EntitlementConfiguration; 053import com.sun.identity.entitlement.EntitlementException; 054import com.sun.identity.entitlement.IPrivilege; 055import com.sun.identity.entitlement.PrivilegeIndexStore; 056import com.sun.identity.entitlement.opensso.PrivilegeUtils; 057import com.sun.identity.entitlement.opensso.SubjectUtils; 058import com.sun.identity.idm.IdRepoException; 059import com.sun.identity.idm.IdUtils; 060import com.sun.identity.policy.interfaces.Subject; 061import com.sun.identity.security.AdminTokenAction; 062import com.sun.identity.shared.debug.Debug; 063import com.sun.identity.shared.xml.XMLUtils; 064import com.sun.identity.sm.DNMapper; 065import com.sun.identity.sm.OrganizationConfigManager; 066import com.sun.identity.sm.PluginSchema; 067import com.sun.identity.sm.SMSEntry; 068import com.sun.identity.sm.SMSException; 069import com.sun.identity.sm.ServiceAlreadyExistsException; 070import com.sun.identity.sm.ServiceConfig; 071import com.sun.identity.sm.ServiceConfigManager; 072import com.sun.identity.sm.ServiceListener; 073import com.sun.identity.sm.ServiceManager; 074import com.sun.identity.sm.ServiceNotFoundException; 075import com.sun.identity.sm.ServiceSchemaManager; 076import org.forgerock.openam.entitlement.PolicyConstants; 077import org.forgerock.openam.ldap.LDAPUtils; 078import org.forgerock.openam.shared.concurrency.LockFactory; 079import org.forgerock.opendj.ldap.DN; 080import org.w3c.dom.Document; 081import org.w3c.dom.Node; 082 083/** 084 * The <code>PolicyManager</code> class manages policies 085 * for a specific organization, sub organization or a container. 086 * This class is the 087 * starting point for policy management, and provides methods to 088 * create/modify/delete policies. 089 * <p>It is a final class 090 * and hence cannot be further extended. The methods in this class 091 * works directly with the backend datastore (usually a 092 * directory server) to store and manage policies. Hence, user 093 * of this class must have valid <code>SSOToken</code> 094 * and privileges to the backend datastore. 095 * 096 * @supported.api 097 * @deprecated since 12.0.0 098 */ 099@Deprecated 100public final class PolicyManager { 101 102 /** 103 * The service name for Policy component. 104 * @supported.api 105 */ 106 public static final String POLICY_SERVICE_NAME = "iPlanetAMPolicyService"; 107 public static final String POLICY_DEBUG_NAME = "amPolicy"; 108 109 /** 110 * The key for the plugins to get the organization name. 111 * @supported.api 112 */ 113 public static final String ORGANIZATION_NAME = "OrganizationName"; 114 public static final String DELEGATION_REALM = 115 "/sunamhiddenrealmdelegationservicepermissions"; 116 117 public static final String NAMED_POLICY = "Policies"; 118 static final String REALM_SUBJECTS = "RealmSubjects"; 119 static final String XML_REALM_SUBJECTS = "xmlRealmSubjects"; 120 private static final String NAMED_POLICY_ID = "NamedPolicy"; 121 static final String RESOURCES_POLICY = "Resources"; 122 static final String RESOURCES_POLICY_ID = "ServiceType"; 123 private static final String SUBJECTS_POLICY = "Subjects"; 124 static final String SUBJECT_POLICY = "Subject"; 125 static final String REALM_SUBJECT_POLICY = "RealmSubject"; 126 static final String CONDITION_POLICY = "Condition"; 127 static final String RESP_PROVIDER_POLICY = "ResponseProvider"; 128 static final String REFERRAL_POLICY = "Referral"; 129 static final String REFERRALS_POLICY = "Referrals"; 130 private static final String POLICY_XML = "xmlpolicy"; 131 static final String POLICY_VERSION = "1.0"; 132 133 public static final String POLICY_ROOT_NODE = "Policy"; 134 static final String POLICY_RULE_NODE = "Rule"; 135 static final String POLICY_SUBJECTS_NODE = "Subjects"; 136 static final String POLICY_CONDITIONS_NODE = "Conditions"; 137 static final String POLICY_RESP_PROVIDERS_NODE = "ResponseProviders"; 138 static final String POLICY_REFERRALS_NODE = "Referrals"; 139 static final String POLICY_RULE_SERVICE_NODE = "ServiceName"; 140 static final String POLICY_RULE_RESOURCE_NODE = "ResourceName"; 141 static final String POLICY_RULE_EXCLUDED_RESOURCE_NODE = 142 "ExcludedResourceName"; 143 static final String POLICY_RULE_APPLICATION_NAME_NODE = "ApplicationName"; 144 static final String ATTR_VALUE_PAIR_NODE = "AttributeValuePair"; 145 static final String ATTR_NODE = "Attribute"; 146 static final String ATTR_VALUE_NODE = "Value"; 147 static final String NAME_ATTRIBUTE = "name"; 148 static final String TYPE_ATTRIBUTE = "type"; 149 static final String DESCRIPTION_ATTRIBUTE = "description"; 150 static final String CREATED_BY_ATTRIBUTE = "createdby"; 151 static final String CREATION_DATE_ATTRIBUTE = "creationdate"; 152 static final String LAST_MODIFIED_BY_ATTRIBUTE = "lastmodifiedby"; 153 static final String LAST_MODIFIED_DATE_ATTRIBUTE = "lastmodifieddate"; 154 static final String PRIORITY_ATTRIBUTE = "priority"; 155 static final String STATUS_ATTRIBUTE = "priority"; 156 static final String STATUS_ACTIVE = "active"; 157 static final String STATUS_INACTIVE = "inactive"; 158 static final String SERVICE_TYPE_NAME_ATTRIBUTE = "serviceName"; 159 160 static final String POLICY_INDEX_ROOT_NODE = "PolicyCrossReferences"; 161 static final String POLICY_INDEX_ROOT_NODE_NAME_ATTR = "name"; 162 static final String POLICY_INDEX_ROOT_NODE_TYPE_ATTR = "type"; 163 static final String 164 POLICY_INDEX_ROOT_NODE_TYPE_ATTR_RESOURCES_VALUE = "Resources"; 165 static final String POLICY_INDEX_REFERENCE_NODE = "Reference"; 166 static final String POLICY_INDEX_REFERENCE_NODE_NAME_ATTR = "name"; 167 static final String POLICY_INDEX_POLICYNAME_NODE = "PolicyName"; 168 static final String POLICY_INDEX_POLICYNAME_NODE_NAME_ATTR = "name"; 169 static final long DEFAULT_SUBJECTS_RESULT_TTL = 10 * 60 * 1000; 170 171 static final String WEB_AGENT_SERVICE = "iPlanetAMWebAgentService"; 172 public static final String ID_REPO_SERVICE = "sunIdentityRepositoryService"; 173 public static final String ORG_ALIAS = "sunOrganizationAliases"; 174 public static final String ORG_ALIAS_URL_HTTP_PREFIX = "http://"; 175 public static final String ORG_ALIAS_URL_HTTPS_PREFIX = "https://"; 176 public static final String ORG_ALIAS_URL_SUFFIX = ":*"; 177 178 private String org = "/"; 179 private String givenOrgName = ""; 180 private ServiceConfigManager scm; 181 private OrganizationConfigManager ocm; 182 private ResourceManager rm; 183 private ServiceTypeManager svtm; 184 private SubjectTypeManager stm; 185 private ConditionTypeManager ctm; 186 private ResponseProviderTypeManager rpm; 187 private ReferralTypeManager rtm; 188 private PolicyCache policyCache; 189 private ResourceIndexManager rim; 190 private final LockFactory<String> lockFactory; 191 192 private static ServiceSchemaManager ssm; 193 private static javax.security.auth.Subject adminSubject; 194 195 SSOToken token; 196 197 // Can be shared by classes 198 static Debug debug = Debug.getInstance(POLICY_DEBUG_NAME); 199 static DN delegationRealm = DN.valueOf(DNMapper.orgNameToDN(DELEGATION_REALM)); 200 private static boolean migratedToEntitlementService = false; 201 202 /** 203 * Constructor for <code>PolicyManager</code> for the 204 * top (or root) organization. It requires a <code>SSOToken 205 * </code> which will be used to perform all data store 206 * operations. If the user does not have sufficient 207 * privileges <code>NoPermissionException</code> will be thrown. 208 * 209 * @param token <code>SSOToken</code> of the user managing policy 210 * 211 * @throws SSOException invalid or expired single-sign-on token 212 * @throws PolicyException for any other abnormal condition 213 * 214 * @supported.api 215 */ 216 public PolicyManager(SSOToken token) throws SSOException, PolicyException { 217 this(token, ""); 218 if (debug.messageEnabled()) { 219 debug.message("Policy Manager constructed using SSO token"); 220 } 221 } 222 223 /** 224 * Constructor for <code>PolicyManager</code> for the 225 * specified organization, sub organization or a container object. 226 * The names of the organization, sub organization or the 227 * container object could be either "/" separated (as per SMS) 228 * or could be the complete DN of the object. 229 * For example: <code>/isp/coke<code>, <code>/isp/pepsi/tacobell<code>, 230 * etc., or <code>"ou=tacobell, o=pepsi, o=isp"<code>, 231 * <code>"o=coke, o=isp"</code>, etc. 232 * The constructor also requires a single sign on token. 233 * which will be used to perform all data store 234 * operations. If the user does not have sufficient 235 * privileges <code>NoPermissionException</code> will be thrown. 236 * 237 * @param token single-sign-on token of the user managing policies 238 * @param name name of the organization, sub organization 239 * or container for which to manage policies. 240 * The name could be either slash (/) separated 241 * or the complete DN. 242 * 243 * @throws SSOException invalid or expired single-sign-on token 244 * @throws NameNotFoundException if the given organization, 245 * sub-organization or container name is not present 246 * @throws PolicyException for any other abnormal condition 247 * 248 * @supported.api 249 */ 250 public PolicyManager(SSOToken token, String name) 251 throws SSOException, NameNotFoundException, PolicyException { 252 SSOTokenManager.getInstance().validateToken(token); 253 this.token = token; 254 try { 255 scm = new ServiceConfigManager(POLICY_SERVICE_NAME, token); 256 257 // Check name i.e., org name 258 org = verifyOrgName(name); 259 givenOrgName = name; 260 261 rm = new ResourceManager(org); 262 } catch (SMSException se) { 263 debug.error("In constructor for PolicyManager with orgName" + 264 "Unable to get service config manager", se); 265 throw (new PolicyException(se)); 266 } 267 268 if (debug.messageEnabled()) { 269 debug.message("Policy Manager constructed with SSO token " + 270 " for organization: " + org); 271 } 272 if (SystemProperties.isServerMode()) { 273 policyCache = PolicyCache.getInstance(); 274 svtm = ServiceTypeManager.getServiceTypeManager(); 275 } else { 276 policyCache = PolicyCache.getInstance(token); 277 svtm = new ServiceTypeManager(token); 278 } 279 rim = new ResourceIndexManager(rm); 280 281 // Retrieves a singleton instance of LockFactory shared across policy. 282 lockFactory = PolicyLockFactory.INSTANCE.getFactory(); 283 } 284 285 /** 286 * Gets the organization name for which the policy manager 287 * was initialized with. The organization name could either be 288 * slash ("/") separated or could be the distinguished name 289 * depending on the manner in which it was initialized. 290 * 291 * @return organization name for which the policy manager was 292 * instantiated 293 * 294 * @supported.api 295 */ 296 public String getOrganizationName() { 297 return (givenOrgName); 298 } 299 300 /** 301 * Gets the policy config attribute values defined for this policy manager 302 * @return policy config attributes defined for this policy manager. Also, 303 * includes the organization distinguished name. 304 */ 305 public Map getPolicyConfig() { 306 Map policyConfig = null; 307 try { 308 policyConfig = PolicyConfig.getPolicyConfig(org); 309 } catch (PolicyException pe) { 310 debug.error("PolicyManager:can not get policy config " 311 + " for org : " + org, pe); 312 } 313 if (policyConfig != null) { 314 Set set = new HashSet(); 315 set.add(org); 316 policyConfig.put(ORGANIZATION_NAME, set); 317 } else { 318 debug.error("PolicyManager: policy config is null for org:" 319 + org + ". Most likely it has been unregistered." 320 + " It is not recommended to unregister the policy" 321 + " configuration serivce. If you do so, the result" 322 + " is undefined."); 323 } 324 return policyConfig; 325 } 326 327 /** 328 * Gets the organization DN 329 * @return DN of the organization for which this policy manager 330 * was created 331 */ 332 String getOrganizationDN() { 333 return (org); 334 } 335 336 /** 337 * Gets a set of names of polices defined in the 338 * organization for which the policy manager was instantiated. 339 * If there are no policies defined, this method returns 340 * an empty set (not null). 341 * 342 * @return <code>Set</code> of names of policies defined in the organization 343 * 344 * @throws SSOException invalid or expired single-sign-on token 345 * @throws NoPermissionException user does not have sufficient 346 * privileges to get policy names 347 * @throws PolicyException for any other abnormal condition 348 * 349 * @supported.api 350 */ 351 public Set getPolicyNames() throws SSOException, NoPermissionException, 352 PolicyException { 353 return (getPolicyNames("*")); 354 } 355 356 /** 357 * Gets a set of selected policy names matching the 358 * pattern in the given organization. The pattern 359 * accepts "*" as the wild card for searching policy names. 360 * For example if the pattern is "co*", it returns policies 361 * starting with "co". Similarly, if the pattern is "*net", it returns 362 * policies ending with "net". The wildcard can be anywhere in the 363 * the string. If there are no policies that match the provided filter, 364 * this method returns an empty set (not null). 365 * 366 * @param pattern search pattern that will be used to select policy names 367 * 368 * @return <code>Set</code> of policy names that satisfy the pattern 369 * 370 * @throws SSOException invalid or expired single-sign-on token 371 * @throws NoPermissionException user does not have sufficient 372 * privileges to get policy names 373 * @throws PolicyException for any other abnormal condition 374 * 375 * @supported.api 376 */ 377 public Set getPolicyNames(String pattern) throws SSOException, 378 NoPermissionException, PolicyException { 379 try { 380 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 381 ServiceConfig namedPolicy = (oConfig == null) ? null : 382 oConfig.getSubConfig(NAMED_POLICY); 383 if (namedPolicy == null) { 384 return (Collections.EMPTY_SET); 385 } else { 386 if (pattern.equals("*")) { 387 return (namedPolicy.getSubConfigNames()); 388 } else { 389 return (namedPolicy.getSubConfigNames(pattern)); 390 } 391 } 392 } catch (SMSException se) { 393 debug.error("Unable to get named policies for organization: " 394 + org); 395 // Check for permission exception 396 String objs[] = { org }; 397 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 398 throw (new NoPermissionException(ResBundleUtils.rbName, 399 "insufficient_access_rights", null)); 400 } else { 401 // Throw generic policy exception 402 throw (new PolicyException(ResBundleUtils.rbName, 403 "unable_to_get_policies_for_organization", objs, 404 se)); 405 } 406 } 407 } 408 409 /** 410 * Gets the LDAP DN (distinguished name) for the named policy 411 * @param policyName name of the policy 412 * @return DN of the policy 413 * @throws SSOException if single sign on token associated with the policy 414 * manager is not valid. 415 * @throws NoPermissionException if not enough permissions 416 * @throws NameNotFoundException if the policy is not found 417 * @throws PolicyException for any other abnormal condition 418 * 419 */ 420 public String getPolicyDN(String policyName) throws 421 SSOException, NoPermissionException, NameNotFoundException, 422 PolicyException { 423 // Get the policy. If the policy does not exists it will 424 // throw NameNotFoundException 425 getPolicy(policyName); 426 427 // Policy is present, construct the DN and return 428 StringBuilder answer = new StringBuilder(100); 429 answer.append("ou="); 430 answer.append(policyName); 431 answer.append(",ou="); 432 answer.append(NAMED_POLICY); 433 answer.append(",ou=default,ou=organizationConfig,ou="); 434 answer.append(POLICY_VERSION); 435 answer.append(",ou="); 436 answer.append(POLICY_SERVICE_NAME); 437 answer.append(",ou=services,"); 438 answer.append(org); 439 return (answer.toString()); 440 } 441 442 /** 443 * Gets the policy object given the name of the policy. 444 * 445 * @param policyName name of the policy 446 * @return policy with the given policy name 447 * @throws SSOException if single sign on token associated with the policy 448 * manager is not valid. 449 * @throws NoPermissionException if not enough permissions. 450 * @throws InvalidFormatException if <code>policyName</code> has 451 * invalid format. 452 * @throws NameNotFoundException if the policy is not found. 453 * @throws InvalidNameException if <code>policyName</code> is invalid. 454 * @throws PolicyException for any other abnormal condition. 455 * 456 * 457 * @supported.api 458 */ 459 public Policy getPolicy(String policyName) throws SSOException, 460 NoPermissionException, InvalidFormatException, 461 NameNotFoundException, 462 InvalidNameException, PolicyException { 463 if (policyName == null) { 464 throw (new InvalidNameException(ResBundleUtils.rbName, 465 "null_name", null, "null", PolicyException.POLICY)); 466 } 467 if (debug.messageEnabled()) { 468 debug.message("searching for named policy: " + policyName + 469 " in organization: " + org); 470 } 471 472 // Check the cache %%% Need to have notification for policy changes 473 Policy answer = null; 474 475 try { 476 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 477 ServiceConfig namedPolicy = (oConfig == null) ? null : 478 oConfig.getSubConfig(NAMED_POLICY); 479 ServiceConfig policy = null; 480 Map attrs = null; 481 Set res = null; 482 if ((namedPolicy == null) || 483 ((policy = namedPolicy.getSubConfig(policyName)) == null) || 484 ((attrs = policy.getAttributes()) == null) || 485 ((res = (Set) attrs.get(POLICY_XML)) == null) || 486 (res.size() <= 0)) { 487 // Named policy node or policy node does not exist 488 if (debug.warningEnabled()) { 489 debug.warning("Unable to find named policy: " + policyName + 490 " in organization: " + org); 491 } 492 String objs[] = { policyName, org }; 493 throw (new NameNotFoundException(ResBundleUtils.rbName, 494 "policy_not_found_in_organization", objs, policyName, 495 PolicyException.POLICY)); 496 } 497 498 // Now create a policy object out of the XML blob 499 Iterator it = res.iterator(); 500 String policyXml = (String) it.next(); 501 Document doc = null; 502 try { 503 doc = XMLUtils.getXMLDocument( 504 new ByteArrayInputStream(policyXml.getBytes("UTF8"))); 505 } catch (Exception xmle) { 506 debug.error("XML parsing error for policy: " + policyName + 507 " in organization: " + org); 508 // throw generic policy exception 509 throw (new PolicyException(xmle)); 510 } 511 Node rootNode = XMLUtils.getRootNode(doc, POLICY_ROOT_NODE); 512 if (rootNode == null) { 513 debug.error("invalid xml policy blob for named policy: " + 514 policyName + " in organization: " + org); 515 throw (new InvalidFormatException(ResBundleUtils.rbName, 516 "invalid_xml_policy_root_node", null, policyName, 517 PolicyException.POLICY)); 518 } 519 520 if (debug.messageEnabled()) { 521 debug.message("returning named policy: " + policyName + 522 " for organization: " + org); 523 } 524 525 // Return the policy object 526 answer = new Policy(this, rootNode); 527 Map policyConfig = getPolicyConfig(); 528 if (policyConfig != null) { 529 answer.setSubjectsResultTtl( 530 PolicyConfig.getSubjectsResultTtl(policyConfig)); 531 } 532 533 return (answer); 534 } catch (SMSException se) { 535 debug.error("SMS error in finding named policy: " + policyName + 536 " in organization: " + org); 537 // Check for permission exception 538 String objs[] = { policyName, org }; 539 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 540 throw (new NoPermissionException(ResBundleUtils.rbName, 541 "insufficient_access_rights", null)); 542 } else { 543 // Throw generic policy exception 544 throw (new PolicyException(ResBundleUtils.rbName, 545 "unable_to_get_policy", objs, se)); 546 } 547 } 548 549 } 550 551 /** 552 * Adds a policy to the data store. 553 * 554 * @param policy policy object to be added to the organization 555 * 556 * @throws SSOException invalid or expired single-sign-on token 557 * @throws NoPermissionException user does not have sufficient 558 * privileges to add policy 559 * @throws InvalidFormatException the data in the policy object 560 * has been corrupted or does not have a valid format 561 * @throws NameAlreadyExistsException a policy with the same 562 * name already exists 563 * @throws PolicyException for any other abnormal condition 564 * 565 * @supported.api 566 */ 567 public void addPolicy(Policy policy) throws SSOException, 568 NameAlreadyExistsException, NoPermissionException, 569 InvalidFormatException, PolicyException { 570 571 String realmName = getOrganizationDN(); 572 573 //TODO: handle non DNs/ 574 realmName = LDAPUtils.formatToRFC(realmName); 575 String subjectRealm = policy.getSubjectRealm(); 576 String[] realmNames = {realmName, subjectRealm}; 577 if ((subjectRealm != null) && !subjectRealm.equals(realmName)) { 578 if (debug.messageEnabled()) { 579 debug.message("Can not add policy in realm :" 580 + realmName + ", policy has realm subjects " 581 + " from realm : " + subjectRealm); 582 } 583 584 //TODO : add logging? 585 586 throw (new InvalidFormatException(ResBundleUtils.rbName, 587 "policy_realm_does_not_match", realmNames, null, realmName, 588 PolicyException.POLICY)); 589 } 590 validateForResourcePrefix(policy); 591 validateReferrals(policy); 592 593 String testCreatedBy = policy.getCreatedBy(); 594 //testCreatedBy is set if we are doing policy replaced. 595 if ((testCreatedBy == null) || (testCreatedBy.length() == 0)) { 596 Date creationDate = new Date(); 597 policy.setCreatedBy(token.getPrincipal().getName()); 598 policy.setCreationDate(creationDate.getTime()); 599 policy.setLastModifiedBy(token.getPrincipal().getName()); 600 policy.setLastModifiedDate(creationDate.getTime()); 601 } 602 603 // Construct the named policy 604 String policyXml = policy.toXML(); 605 Map attrs = new HashMap(); 606 Set set = new HashSet(); 607 set.add(policyXml); 608 attrs.put(POLICY_XML, set); 609 610 // Get(create if necessary) ou=policies entry 611 ServiceConfig namedPolicy = createOrGetPolicyConfig( 612 NAMED_POLICY, NAMED_POLICY, scm, org); 613 try { 614 //create the policy entry 615 namedPolicy.addSubConfig(policy.getName(), 616 NAMED_POLICY_ID, 0, attrs); 617 if (isMigratedToEntitlementService()) { 618 PrivilegeIndexStore pis = PrivilegeIndexStore.getInstance( 619 adminSubject, realmName); 620 Set<IPrivilege> privileges = PrivilegeUtils.policyToPrivileges( 621 policy); 622 pis.add(privileges); 623 policyCache.sendPolicyChangeNotification(null, policy, 624 ServiceListener.ADDED); 625 } else { 626 // do the addition in resources tree 627 //rm.addPolicyToResourceTree(policy); 628 rim.addPolicyToResourceTree(svtm, token, policy); 629 } 630 } catch (EntitlementException e) { 631 String[] objs = { policy.getName(), org }; 632 throw (new PolicyException(ResBundleUtils.rbName, 633 "unable_to_add_policy", objs, e)); 634 } catch (ServiceAlreadyExistsException e) { 635 String[] objs = { policy.getName(), org }; 636 if (PolicyUtils.logStatus) { 637 PolicyUtils.logErrorMessage( 638 "POLICY_ALREADY_EXISTS_IN_REALM", objs, token); 639 } 640 throw (new NameAlreadyExistsException(ResBundleUtils.rbName, 641 "policy_already_exists_in_org", objs, policy.getName(), 642 PolicyException.POLICY)); 643 } catch (SMSException se) { 644 String[] objs = { policy.getName(), org }; 645 if (PolicyUtils.logStatus) { 646 PolicyUtils.logErrorMessage("UNABLE_TO_ADD_POLICY", objs, 647 token); 648 } 649 debug.error("SMS error in add policy: " + 650 policy.getName() + " for org: " + org, se); 651 652 // Check for permission exception 653 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 654 throw (new NoPermissionException(ResBundleUtils.rbName, 655 "insufficient_access_rights", null)); 656 } else { 657 // Throw generic policy exception 658 throw (new PolicyException(ResBundleUtils.rbName, 659 "unable_to_add_policy", 660 objs, se)); 661 } 662 } 663 if (PolicyUtils.logStatus) { 664 String[] objs = { policy.getName(), org }; 665 PolicyUtils.logAccessMessage("POLICY_CREATE_SUCCESS", objs, token); 666 } 667 } 668 669 /** 670 * Replaces a policy object in the data store with the same policy name 671 * 672 * @param policy policy object to be added to the organization 673 * 674 * @throws SSOException invalid or expired single-sign-on token 675 * @throws NoPermissionException user does not have sufficient 676 * privileges to replace policy 677 * @throws NameNotFoundException policy with the same name does 678 * not exist. 679 * @throws InvalidFormatException the provide policy from the 680 * data store has been corrupted or does not have a valid format 681 * @throws PolicyException for any other abnormal condition. 682 * 683 * @supported.api 684 */ 685 public void replacePolicy(Policy policy) throws SSOException, 686 NameNotFoundException, NoPermissionException, 687 InvalidFormatException, PolicyException { 688 689 String realm = getOrganizationDN(); 690 String subjectRealm = policy.getSubjectRealm(); 691 String[] realmNames = {realm, subjectRealm}; 692 if ((subjectRealm != null) && !subjectRealm.equals(realm)) { 693 694 if (debug.messageEnabled()) { 695 debug.message("Can not replace policy in realm :" 696 + realm + ", policy has realm subjects " 697 + " from realm : " + subjectRealm); 698 } 699 700 throw (new InvalidFormatException(ResBundleUtils.rbName, 701 "policy_realm_does_not_match", realmNames, null, realm, 702 PolicyException.POLICY)); 703 } 704 705 policy.setLastModifiedBy(token.getPrincipal().getName()); 706 Date lastModifiedDate = new Date(); 707 policy.setLastModifiedDate(lastModifiedDate.getTime()); 708 709 // Construct the named policy 710 String policyXml = policy.toXML(); 711 Map attrs = new HashMap(); 712 Set set = new HashSet(); 713 set.add(policyXml); 714 attrs.put(POLICY_XML, set); 715 716 String name = null; 717 // Get(create if necessary) ou=policies entry 718 ServiceConfig namedPolicy = createOrGetPolicyConfig( 719 NAMED_POLICY, NAMED_POLICY, scm, org); 720 try { 721 String policyName = policy.getName(); 722 String oldPolicyName = policy.getOriginalName(); 723 ServiceConfig policyEntry = namedPolicy.getSubConfig(policyName); 724 ServiceConfig oldPolicyEntry = null; 725 if ( oldPolicyName != null ) { 726 oldPolicyEntry = namedPolicy.getSubConfig(oldPolicyName); 727 name = oldPolicyName; 728 } else { 729 name = policy.getName(); 730 } 731 if ( policyEntry == null ) { 732 if ( oldPolicyEntry != null ) { 733 removePolicy(oldPolicyName); 734 addPolicy(policy); 735 // reset the policy name 736 // TODO: need to think this through 737 policy.resetOriginalName(); 738 } else { 739 // neither the new policy nor the old policy is present 740 String objs[] = { policy.getName(), org }; 741 throw (new NameNotFoundException(ResBundleUtils.rbName, 742 "policy_not_found_in_organization", objs, 743 policy.getName(), PolicyException.POLICY)); 744 } 745 } else { //newPolicy exisits 746 String[] objs = { policy.getName(), org }; 747 if((oldPolicyName != null) && 748 !policy.getName().equalsIgnoreCase(oldPolicyName)) { 749 if (PolicyUtils.logStatus) { 750 PolicyUtils.logErrorMessage( 751 "DID_NOT_REPLACE_POLICY", 752 objs, token); 753 } 754 throw (new NameAlreadyExistsException(ResBundleUtils.rbName, 755 "policy_already_exists_in_org", objs, policy.getName(), 756 PolicyException.POLICY)); 757 } 758 759 Policy oldPolicy = getPolicy(policy.getName()); 760 validateForResourcePrefix(policy); 761 validateReferrals(policy); 762 policyEntry.setAttributes(attrs); 763 if (oldPolicy != null) { 764 // Acquire lock to ensure atomicity when updating policy. 765 Lock lock = lockFactory.acquireLock(policyName); 766 767 try { 768 lock.lock(); 769 if (isMigratedToEntitlementService()) { 770 PrivilegeIndexStore pis = PrivilegeIndexStore.getInstance( 771 SubjectUtils.createSubject(token), realm); 772 pis.delete(PrivilegeUtils.policyToPrivileges(oldPolicy)); 773 pis.add(PrivilegeUtils.policyToPrivileges(policy)); 774 } else { 775 rim.replacePolicyInResourceTree(svtm, token, oldPolicy, policy); 776 } 777 } finally { 778 lock.unlock(); 779 } 780 781 policyCache.sendPolicyChangeNotification(oldPolicy, policy, ServiceListener.MODIFIED); 782 } 783 } 784 } catch (EntitlementException e) { 785 String[] objs = { name, org }; 786 throw (new PolicyException(ResBundleUtils.rbName, 787 "unable_to_replace_policy", objs, e)); 788 } catch (SMSException se) { 789 String[] objs = { name, org }; 790 if (PolicyUtils.logStatus) { 791 PolicyUtils.logErrorMessage("UNABLE_TO_REPLACE_POLICY", objs, 792 token); 793 } 794 debug.error("SMS error in replacing policy: " + 795 policy.getOriginalName() + " for org: " + org, se); 796 // Check for permission exception 797 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 798 throw (new NoPermissionException(ResBundleUtils.rbName, 799 "insufficient_access_rights", null)); 800 } else { 801 // Throw generic policy exception 802 throw (new PolicyException(ResBundleUtils.rbName, 803 "unable_to_replace_policy", objs, se)); 804 } 805 } 806 if (PolicyUtils.logStatus) { 807 String[] objs = { name, org }; 808 PolicyUtils.logAccessMessage("POLICY_MODIFY_SUCCESS", objs, token); 809 } 810 } 811 812 /** 813 * Deletes a policy in the organization with the given name. 814 * 815 * @param policyName name of the policy to be deleted 816 * 817 * @throws SSOException invalid or expired single-sign-on token 818 * @throws NoPermissionException user does not have sufficient 819 * privileges to remove policies 820 * @throws PolicyException for any other abnormal condition 821 * 822 * @supported.api 823 */ 824 public void removePolicy(String policyName) throws 825 SSOException, NoPermissionException, PolicyException { 826 // Check if name is valid 827 if (policyName == null) { 828 if (debug.warningEnabled()) { 829 debug.warning("In PolicyManager::removePolicy(), name is null"); 830 } 831 throw (new InvalidNameException(ResBundleUtils.rbName, 832 "null_name", null, "null", PolicyException.POLICY)); 833 } 834 835 try { 836 // Get service config for named policy node 837 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 838 ServiceConfig namedPolicy = (oConfig == null) ? null : 839 oConfig.getSubConfig(NAMED_POLICY); 840 if (namedPolicy != null) { 841 /* Remove the named policy 842 * before removing the named policy 843 * prepare for changes in resources tree 844 */ 845 Policy policy = getPolicy(policyName); 846 847 // do the removal of policy 848 namedPolicy.removeSubConfig(policyName); 849 850 if (policy != null) { 851 if (isMigratedToEntitlementService()) { 852 // should use super admin token to remove the index store 853 // entry 854 PrivilegeIndexStore pis = PrivilegeIndexStore. 855 getInstance( 856 SubjectUtils.createSuperAdminSubject(), 857 getOrganizationDN()); 858 if (policy.isReferralPolicy()) { 859 pis.deleteReferral((policyName)); 860 } else { 861 pis.delete( 862 PrivilegeUtils.policyToPrivileges(policy)); 863 } 864 policyCache.sendPolicyChangeNotification(null, policy, 865 ServiceListener.REMOVED); 866 } else { 867 // do the removal in resources tree 868 rim.removePolicyFromResourceTree(svtm, token, policy); 869 870 } 871 } 872 } 873 } catch (EntitlementException e) { 874 debug.error("Error while removing policy : " + e.getMessage()); 875 } catch (ServiceNotFoundException snfe) { 876 debug.error("Error while removing policy : " + 877 snfe.getMessage() ); 878 } catch (SMSException smse) { 879 String objs[] = { policyName, org }; 880 if (PolicyUtils.logStatus) { 881 PolicyUtils.logErrorMessage("UNABLE_TO_REMOVE_POLICY", objs, 882 token); 883 } 884 debug.error("SMS error in deleting policy: " + 885 policyName + " for org: " + org, smse); 886 // Check for permission exception 887 if (smse.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 888 throw (new NoPermissionException(ResBundleUtils.rbName, 889 "insufficient_access_rights", null)); 890 } else { 891 // Throw generic policy exception 892 throw (new PolicyException(ResBundleUtils.rbName, 893 "unable_to_remove_policy", objs, smse)); 894 } 895 } 896 String objs[] = { policyName, org }; 897 if (PolicyUtils.logStatus) { 898 PolicyUtils.logAccessMessage("POLICY_REMOVE_SUCCESS", objs, token); 899 } 900 } 901 902 /** 903 * Gets the <code>ResourceManager</code> object instance associated 904 * with this <code>PolicyManager</code> object instance 905 * 906 * @return <code>ResourceManager</code> object 907 * 908 * @supported.api 909 */ 910 public ResourceManager getResourceManager() { 911 return rm; 912 } 913 914 /** 915 * Gets the <code>SubjectTypeManager</code> object instance associated 916 * with this <code>PolicyManager</code> object instance 917 * 918 * @return <code>SubjectTypeManager</code> object 919 * 920 * @supported.api 921 */ 922 public SubjectTypeManager getSubjectTypeManager() { 923 if (stm == null) { 924 stm = new SubjectTypeManager(this); 925 } 926 return (stm); 927 } 928 929 /** 930 * Gets the <code>ConditionTypeManager</code> object instance associated 931 * with this <code>PolicyManager</code> object instance 932 * 933 * @return <code>ConditionTypeManager</code> object 934 * 935 * @supported.api 936 */ 937 public ConditionTypeManager getConditionTypeManager() { 938 if (ctm == null) { 939 ctm = new ConditionTypeManager(this); 940 } 941 return (ctm); 942 } 943 944 /** 945 * Gets the <code>ResponseProviderTypeManager</code> object instance 946 * associated with this <code>PolicyManager</code> object instance 947 * 948 * @return <code>ResponseProviderTypeManager</code> object 949 * 950 */ 951 public ResponseProviderTypeManager getResponseProviderTypeManager() { 952 if (rpm == null) { 953 rpm = new ResponseProviderTypeManager(this); 954 } 955 return (rpm); 956 } 957 958 /** Creates or gets a node (namedPolicy, resources, or userCollection) 959 * under ou=policies 960 */ 961 static ServiceConfig createOrGetPolicyConfig(String configName, 962 String configId, ServiceConfigManager scm, String org) 963 throws NoPermissionException, PolicyException, SSOException { 964 // Get service config that represents named policy node 965 ServiceConfig sConfig = null; 966 try { 967 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 968 sConfig = (oConfig == null) ? null : 969 oConfig.getSubConfig(configName); 970 if (sConfig == null) { 971 if (debug.messageEnabled()) { 972 debug.message("Creating the " + configName + 973 " tree for org: " + org); 974 } 975 // create the named policy node 976 createPolicyTree(configName, configId, scm, org); 977 978 // Check if policy tree is created 979 if (oConfig == null) { 980 oConfig = scm.getOrganizationConfig(org, null); 981 } 982 if ((oConfig == null) || ((sConfig = oConfig.getSubConfig( 983 configName)) == null)) { 984 // Throw generic policy exception 985 String objs[] = { configName }; 986 throw (new PolicyException(ResBundleUtils.rbName, 987 "unable_to_get_policy_node", objs, null)); 988 } 989 } 990 } catch (SMSException smse) { 991 // Debug messages 992 debug.error("SMS error in creating " + configName + 993 " node for org: " + org, smse); 994 995 // Check for permission exception 996 if (smse.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 997 String objs[] = { configName }; 998 throw (new NoPermissionException(ResBundleUtils.rbName, 999 "insufficient_access_rights", objs)); 1000 } else { 1001 // Throw generic policy exception 1002 String objs[] = { configName }; 1003 throw (new PolicyException(ResBundleUtils.rbName, 1004 "unable_to_get_policy_node", objs, smse)); 1005 } 1006 } 1007 return (sConfig); 1008 } 1009 1010 /** 1011 * Creates the policy tree, ou=policy, ou=services, ... 1012 */ 1013 static void createPolicyTree(String configName, String configId, 1014 ServiceConfigManager scm, String org) throws NoPermissionException, 1015 PolicyException, SSOException { 1016 try { 1017 // Get the iPlanetPolicyService node 1018 ServiceConfig pConfig = scm.getOrganizationConfig(org, null); 1019 if (pConfig == null) { 1020 // Since not present, create organization services node 1021 // i.e, ou=services, <org dn> and ou=iPlanetPolicyService, 1022 // ou=services, ... 1023 scm.createOrganizationConfig(org, null); 1024 // Since it is created above, get it 1025 pConfig = scm.getOrganizationConfig(org, null); 1026 } 1027 // Create requested policy sub node 1028 // i.e., ou=<configName>, ou=iPlanetPolicyService, ou=services, ... 1029 pConfig.addSubConfig(configName, configId, 0, null); 1030 } catch (ServiceAlreadyExistsException se) { 1031 // do nothing 1032 if (debug.messageEnabled()) { 1033 debug.message("PolicyManager->createPolicyTree: Name: " + 1034 configName + " ID: " + configId + 1035 " Policy service already exists under org->" + org); 1036 } 1037 } catch (SMSException e) { 1038 // Check for permission exception 1039 String[] objs = { org }; 1040 if (e.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 1041 throw (new NoPermissionException(ResBundleUtils.rbName, 1042 "insufficient_access_rights", null)); 1043 } else { 1044 throw (new PolicyException(ResBundleUtils.rbName, 1045 "unable_to_create_policy_for_org", objs, e)); 1046 } 1047 } 1048 } 1049 1050 /** 1051 * Verifies if the name, which specifies a organization, 1052 * a suborganization or a container object, is in DN format; If not, 1053 * the name will be converted to a DN. Furthermore, whether the entry 1054 * corresponding to the DN exists is also checked. 1055 * 1056 * @param name name of the organization, suborganization 1057 * or container for which to manage policies. 1058 * The name could be either slash (/) separated 1059 * or the complete DN. 1060 * 1061 * @return the name in DN format (possibly converted from slash format) 1062 * 1063 * @throws SSOException invalid or expired single-sign-on token 1064 * @throws InvalidNameException the name is null 1065 * @throws NameNotFoundException if the given organization, 1066 * sub-organization or container name is not present 1067 */ 1068 String verifyOrgName(String name) 1069 throws InvalidNameException, NameNotFoundException, SSOException { 1070 String orgName = null; 1071 1072 // Check for null name 1073 if (name == null) { 1074 throw (new InvalidNameException(ResBundleUtils.rbName, "null_name", 1075 null, "null", PolicyException.ORGANIZATION)); 1076 } 1077 1078 /* this mapping call is required if name is not a DN 1079 * or if the name is not DN of a realm 1080 * This call is harmless if the DN is already DN of a realm 1081 */ 1082 orgName = DNMapper.orgNameToDN(name); 1083 1084 // Check to see if the organization exists 1085 // if not present throw NameNotFoundException 1086 if (!SMSEntry.checkIfEntryExists(orgName, token)) { 1087 if (debug.warningEnabled()) { 1088 debug.warning("Checking for organization name: " + 1089 orgName + " failed since entry does not exist"); 1090 } 1091 String[] objs = { name }; 1092 throw (new NameNotFoundException(ResBundleUtils.rbName, 1093 "org_not_found", objs, orgName, 1094 PolicyException.ORGANIZATION)); 1095 } 1096 return (orgName); 1097 } 1098 1099 /** 1100 * Gets a list of subordinate organizations or containers. If 1101 * there are no subordinate organizations or containers, returns 1102 * an empty set (not null). 1103 * 1104 * @return set of valid subordinate organizations or containers 1105 * 1106 * @throws SSOException invalid or expired single-sign-on token 1107 * @throws NoPermissionException user does not have sufficient 1108 * privileges to replace policy 1109 */ 1110 Set getSubOrganizationNames() throws SSOException, 1111 NoPermissionException, PolicyException { 1112 throw (new UnsupportedOperationException()); 1113 } 1114 1115 /** 1116 * Gets sub-organizations, given a filter. The filter 1117 * accepts "*" as the wild card for searching sub-organization names. 1118 * For example if the filter is "co*", it returns sub-organizations 1119 * starting with "co". Similarly, if the filter is "*net", it returns 1120 * sub-organizations ending with "net". 1121 * 1122 * @param filter the search filter that be used to 1123 * identify sub-organizations 1124 * 1125 * @return a set of sub-organizations 1126 */ 1127 Set getSubOrganizationNames(String filter) 1128 throws SSOException, PolicyException { 1129 throw (new UnsupportedOperationException()); 1130 } 1131 1132 /** 1133 * Gets sub-organization's policy manager. 1134 * 1135 * @param subOrgName name of the sub-organization organization. This 1136 * should be relative to the current organization. 1137 * 1138 * @return returns the policy manager for the organization; 1139 * else returns <code>null</code>. 1140 */ 1141 PolicyManager getSubOrganizationPolicyManager(String subOrgName) 1142 throws SSOException, PolicyException { 1143 // the assumption is that orgnames are / separated 1144 return (new PolicyManager(token, org + "/" + subOrgName)); 1145 } 1146 1147 /** 1148 * Gets <code>ServiceTypeManager</code> associated with this 1149 * policy manager 1150 */ 1151 ServiceTypeManager getServiceTypeManager() { 1152 return svtm; 1153 } 1154 1155 /** 1156 * Returns <code>ReferralTypeManager</code> associated with this 1157 * policy manager. 1158 * 1159 * @return <code>ReferralTypeManager</code> associated with this 1160 * policy manager. 1161 * @supported.api 1162 */ 1163 public ReferralTypeManager getReferralTypeManager() { 1164 if ( rtm == null ) { 1165 rtm = new ReferralTypeManager(this); 1166 } 1167 return rtm; 1168 } 1169 1170 1171 /** 1172 * Gets plugins schemas for a given interface name 1173 */ 1174 static Set getPluginSchemaNames(String interfaceName) { 1175 if (ssm == null || !ssm.isSSOTokenValid()) { 1176 try { 1177 ssm = new ServiceSchemaManager( 1178 PolicyManager.POLICY_SERVICE_NAME, 1179 ServiceTypeManager.getSSOToken()); 1180 } catch (Exception se) { 1181 PolicyManager.debug.error( 1182 "Cannot create service schema " + 1183 "manager for policy", se); 1184 return (Collections.EMPTY_SET); 1185 } 1186 } 1187 1188 Set answer = null; 1189 try { 1190 /* Get the plugin schema names for the root 1191 * In the future might want to customize it for org 1192 */ 1193 answer = ssm.getPluginSchemaNames(interfaceName, null); 1194 } catch (Exception e) { 1195 PolicyManager.debug.error( 1196 "Cannot get plugin schemas: " + 1197 interfaceName + " for policy", e); 1198 return (Collections.EMPTY_SET); 1199 } 1200 return ((answer == null) ? Collections.EMPTY_SET : answer); 1201 } 1202 1203 1204 /** 1205 * Gets PluginSchema object for the given plugin interface name 1206 * and plugin name. Returns <code>null</code> if not present. 1207 */ 1208 static PluginSchema getPluginSchema(String interfaceName, 1209 String pluginName) { 1210 Set plugins = getPluginSchemaNames(interfaceName); 1211 if (plugins.contains(pluginName)) { 1212 try { 1213 return (ssm.getPluginSchema(pluginName, interfaceName, null)); 1214 } catch (Exception e) { 1215 PolicyManager.debug.error( 1216 "Cannot get plugin schemas: " + 1217 interfaceName + " for policy", e); 1218 } 1219 } 1220 return (null); 1221 } 1222 1223 /** 1224 * Gets the view bean URL given the plugin type 1225 * and the plugin java class name 1226 * 1227 * @param pluginType type of plugin such as Subject, Referral, Condition 1228 * @param pluginClassName name of java class name implementing the plugin 1229 * type 1230 * 1231 * @return view bean URL defined for pluginType with name pluginName 1232 */ 1233 static String getViewBeanURL(String pluginType, String pluginClassName) { 1234 String viewBeanURL = null; 1235 if (pluginType != null) { 1236 Iterator items = PolicyManager.getPluginSchemaNames( 1237 pluginType).iterator(); 1238 while (items.hasNext()) { 1239 String pluginName = (String) items.next(); 1240 PluginSchema ps = PolicyManager.getPluginSchema(pluginType, 1241 pluginName); 1242 if (pluginClassName.equals(ps.getClassName())) { 1243 viewBeanURL = ps.getPropertiesViewBeanURL(); 1244 break; 1245 } 1246 } 1247 } 1248 return viewBeanURL; 1249 } 1250 1251 /** Gets a policy using policy cache. 1252 * @param policyName policy name 1253 * @param useCache flag to indicate whether to use cache or not 1254 * @return the policy with the given policy name 1255 * @throws SSOException 1256 * @throws NoPermissionException 1257 * @throws InvalidFormatException 1258 * @throws PolicyException 1259 */ 1260 Policy getPolicy(String policyName, boolean useCache) throws SSOException, 1261 NoPermissionException, InvalidFormatException, 1262 NameNotFoundException, 1263 InvalidFormatException, PolicyException { 1264 Policy policy = null; 1265 if ( useCache ) { 1266 policy = policyCache.getPolicy(org, policyName); 1267 } else { 1268 policy = getPolicy(policyName); 1269 } 1270 return policy; 1271 } 1272 1273 ResourceIndexManager getResourceIndexManager() { 1274 return rim; 1275 } 1276 1277 private boolean validateResourceForPrefix(ServiceType resourceType, 1278 String resourceName) throws PolicyException { 1279 Set<String> resourcePrefixes = getManagedResourceNames( 1280 resourceType.getName()); 1281 return validateResourceForPrefix(resourceType, 1282 resourcePrefixes, resourceName); 1283 } 1284 1285 private boolean validateResourceForPrefixE( 1286 String realm, 1287 String serviceName, 1288 Set<String> resourcePrefixes, 1289 String resourceName) throws PolicyException, EntitlementException { 1290 1291 String realmName = LDAPUtils.isDN(realm) ? 1292 DNMapper.orgNameToRealmName(realm) :realm; 1293 1294 Application appl = ApplicationManager.getApplication( 1295 PolicyConstants.SUPER_ADMIN_SUBJECT, realmName, serviceName); 1296 com.sun.identity.entitlement.interfaces.ResourceName resComp = appl. 1297 getResourceComparator(); 1298 resourceName = resComp.canonicalize(resourceName); 1299 1300 for (String prefix : resourcePrefixes) { 1301 boolean interpretWildCard = true; 1302 com.sun.identity.entitlement.ResourceMatch resMatch = 1303 resComp.compare(resourceName, 1304 resComp.canonicalize(prefix), interpretWildCard); 1305 if ( resMatch.equals( 1306 com.sun.identity.entitlement.ResourceMatch.SUPER_RESOURCE_MATCH) 1307 || resMatch.equals( 1308 com.sun.identity.entitlement.ResourceMatch.WILDCARD_MATCH) 1309 || resMatch.equals( 1310 com.sun.identity.entitlement.ResourceMatch.EXACT_MATCH) ) { 1311 return true; 1312 } 1313 1314 } 1315 return false; 1316 } 1317 1318 private boolean validateResourceForPrefix( 1319 ServiceType resourceType, 1320 Set<String> resourcePrefixes, 1321 String resourceName) throws PolicyException { 1322 1323 for (String prefix : resourcePrefixes) { 1324 boolean interpretWildCard = true; 1325 ResourceMatch resMatch = resourceType.compare(resourceName, prefix, 1326 interpretWildCard); 1327 if ( resMatch.equals(ResourceMatch.SUPER_RESOURCE_MATCH) 1328 || resMatch.equals(ResourceMatch.WILDCARD_MATCH) 1329 || resMatch.equals(ResourceMatch.EXACT_MATCH) ) { 1330 return true; 1331 } 1332 1333 } 1334 return false; 1335 } 1336 1337 private void validateForResourcePrefix(Policy policy) 1338 throws SSOException, PolicyException { 1339 if (isMigratedToEntitlementService()) { 1340 validateForResourcePrefixE(policy); 1341 } else { 1342 validateForResourcePrefixO(policy); 1343 } 1344 } 1345 1346 private void validateForResourcePrefixE(Policy policy) 1347 throws SSOException, PolicyException { 1348 DN orgDN = DN.valueOf(org); 1349 DN baseDN = DN.valueOf(ServiceManager.getBaseDN()); 1350 1351 if (!orgDN.equals(baseDN) && !orgDN.equals(delegationRealm)) { 1352 String realm = DNMapper.orgNameToRealmName(getOrganizationDN()); 1353 Iterator ruleNames = policy.getRuleNames().iterator(); 1354 while (ruleNames.hasNext()) { 1355 try { 1356 String ruleName = (String) ruleNames.next(); 1357 Rule rule = (Rule) policy.getRule(ruleName); 1358 String serviceTypeName = rule.getServiceTypeName(); 1359 String ruleResource = rule.getResourceName(); 1360 // Make sure adminSubject has been set before using 1361 if (adminSubject == null) { 1362 initialise(); 1363 } 1364 Set<String> referredResources = ApplicationManager. 1365 getReferredResources(adminSubject, 1366 realm, serviceTypeName); 1367 if ((referredResources == null) || referredResources. 1368 isEmpty()) { 1369 String[] objs = {org}; 1370 throw new PolicyException(ResBundleUtils.rbName, 1371 "no_referral_can_not_create_policy", objs, null); 1372 } 1373 ServiceType resourceType = getServiceTypeManager(). 1374 getServiceType(serviceTypeName); 1375 1376 if (!validateResourceForPrefixE(realm, serviceTypeName, 1377 referredResources, ruleResource)) { 1378 String[] objs = {ruleResource, resourceType.getName()}; 1379 throw new PolicyException(ResBundleUtils.rbName, 1380 "resource_name_not_permitted_by_prefix_names", objs, 1381 null); 1382 } 1383 } catch (EntitlementException ex) { 1384 String[] objs = {org}; 1385 throw new PolicyException(ResBundleUtils.rbName, 1386 "no_referral_can_not_create_policy", objs, null); 1387 } 1388 } 1389 } 1390 } 1391 1392 private void validateForResourcePrefixO(Policy policy) 1393 throws SSOException, PolicyException { 1394 DN orgDN = DN.valueOf(org); 1395 DN baseDN = DN.valueOf(ServiceManager.getBaseDN()); 1396 Set prefixes = getManagedResourceNames(); 1397 if (!orgDN.equals(baseDN) && !orgDN.equals(delegationRealm) 1398 && ((prefixes == null ) || prefixes.isEmpty()) ) { 1399 String[] objs = {org}; 1400 throw new PolicyException( 1401 ResBundleUtils.rbName, 1402 "no_referral_can_not_create_policy", objs, null); 1403 } 1404 Iterator ruleNames = policy.getRuleNames().iterator(); 1405 while ( ruleNames.hasNext() ) { 1406 String ruleName = (String) ruleNames.next(); 1407 Rule rule = (Rule) policy.getRule(ruleName); 1408 String serviceTypeName = rule.getServiceTypeName(); 1409 ServiceType resourceType = getServiceTypeManager() 1410 .getServiceType(serviceTypeName); 1411 String ruleResource = rule.getResourceName(); 1412 boolean validResource = true; 1413 if (!orgDN.equals(baseDN) && !orgDN.equals(delegationRealm)) { 1414 validResource = validateResourceForPrefix(resourceType, 1415 ruleResource); 1416 } 1417 if (!validResource) { 1418 String[] objs = { ruleResource, resourceType.getName() }; 1419 throw new PolicyException( 1420 ResBundleUtils.rbName, 1421 "resource_name_not_permitted_by_prefix_names", 1422 objs, null); 1423 } 1424 } 1425 1426 } 1427 1428 private void validateReferrals(Policy policy) 1429 throws SSOException, PolicyException { 1430 Set candidateOrgs = policy.getReferredToOrganizations(); 1431 if ( candidateOrgs.contains(org.toLowerCase()) ) { 1432 String[] objs = { org }; 1433 throw new PolicyException( 1434 ResBundleUtils.rbName, 1435 "invalid_referral_pointing_to_self", 1436 objs, null); 1437 } 1438 Iterator iter = candidateOrgs.iterator(); 1439 while ( iter.hasNext() ) { 1440 String candidateOrg = (String) iter.next(); 1441 1442 /* 1443 * check org orgName exisits - would result in 1444 * PolicyException if the orgName does not exist 1445 */ 1446 verifyOrgName(candidateOrg); 1447 } 1448 1449 } 1450 1451 void saveRealmSubjects(Subjects subjects) 1452 throws PolicyException, SSOException { 1453 ServiceConfig realmSubjects = createOrGetPolicyConfig( 1454 REALM_SUBJECTS, REALM_SUBJECTS, scm, org); 1455 Map attributes = new HashMap(1); 1456 Set values = new HashSet(1); 1457 String subjectsXML = subjects.toXML(); 1458 values.add(subjectsXML); 1459 attributes.put(XML_REALM_SUBJECTS, values); 1460 try { 1461 realmSubjects.setAttributes(attributes); 1462 } catch (SMSException se) { 1463 debug.error("SMS error in saving realm subjects " 1464 + " in organization: " + org); 1465 // Check for permission exception 1466 String objs[] = { org }; 1467 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 1468 throw new PolicyException(ResBundleUtils.rbName, 1469 "insufficient_access_rights", null, se); 1470 } else { 1471 // Throw generic policy exception 1472 throw new PolicyException(ResBundleUtils.rbName, 1473 "unable_to_save_realm_subjects", objs, se); 1474 } 1475 } 1476 if (debug.messageEnabled()) { 1477 debug.message("saved realm subjects:" + subjectsXML); 1478 } 1479 } 1480 1481 Subjects readRealmSubjects() throws PolicyException, SSOException { 1482 Subjects subjects = null; 1483 ServiceConfig realmSubjects = createOrGetPolicyConfig( 1484 REALM_SUBJECTS, REALM_SUBJECTS, scm, org); 1485 Set values = null; 1486 values = (Set)realmSubjects.getAttributes().get(XML_REALM_SUBJECTS); 1487 if ((values != null) && !values.isEmpty()) { 1488 String xmlSubjects = (String)values.iterator().next(); 1489 Document doc = null; 1490 try { 1491 doc = XMLUtils.getXMLDocument( 1492 new ByteArrayInputStream(xmlSubjects.getBytes("UTF8"))); 1493 } catch (Exception xmle) { 1494 debug.error("XML parsing error for realmSubjects: " 1495 + " in organization: " + org); 1496 // throw generic policy exception 1497 throw (new PolicyException(xmle)); 1498 } 1499 Node subjectsNode = XMLUtils.getRootNode(doc, SUBJECTS_POLICY); 1500 if (subjectsNode == null) { 1501 debug.error("invalid xmlRealmSubjects blob " 1502 + " in organization: " + org); 1503 throw (new InvalidFormatException(ResBundleUtils.rbName, 1504 "invalid_xml_realmsubjects_root_node", null, 1505 org, PolicyException.POLICY)); 1506 } 1507 subjects = new Subjects(this, subjectsNode); 1508 } else { 1509 subjects = new Subjects(); 1510 } 1511 if (debug.messageEnabled()) { 1512 debug.message("read realm subjects:" + subjects.toXML()); 1513 } 1514 subjects.setPolicyConfig(getPolicyConfig()); 1515 return subjects; 1516 } 1517 1518 /** 1519 * Gets the set of policies that use the realm subject 1520 * @param subjectName name of the realm subject to check for 1521 * @return a <code>Set</code> of <code>Policy</code> objects 1522 * that use the realm subject 1523 */ 1524 public Set getPoliciesUsingRealmSubject(String subjectName) 1525 throws PolicyException, SSOException { 1526 Set policies = new HashSet(); 1527 Set policyNames = getPolicyNames(); 1528 for (Iterator policyIter = policyNames.iterator(); 1529 policyIter.hasNext();) { 1530 String policyName = (String)policyIter.next(); 1531 Policy policy = getPolicy(policyName); 1532 Set subjectNames = policy.getSubjectNames(); 1533 if (subjectNames.contains(subjectName)) { 1534 Subject subject = policy.getSubject(subjectName); 1535 if (subject instanceof SharedSubject) { 1536 policies.add(policy); 1537 } 1538 } 1539 } 1540 return policies; 1541 } 1542 1543 Policy getPolicyUsingRealmSubject(String subjectName) 1544 throws PolicyException, SSOException { 1545 Policy policy = null; 1546 Set policyNames = getPolicyNames(); 1547 for (Iterator policyIter = policyNames.iterator(); 1548 policyIter.hasNext();) { 1549 String policyName = (String)policyIter.next(); 1550 Policy p = getPolicy(policyName); 1551 Set subjectNames = p.getSubjectNames(); 1552 if (subjectNames.contains(subjectName)) { 1553 Subject subject = p.getSubject(subjectName); 1554 if (subject instanceof SharedSubject) { 1555 policy = p; 1556 break; 1557 } 1558 } 1559 } 1560 return policy; 1561 } 1562 1563 private Set getOrgAliasMappedResourceNames() 1564 throws PolicyException { 1565 if (debug.messageEnabled()) { 1566 debug.message("PolicyManager.getOrgAliasMappedResourceNames(): " 1567 + " entering:orgName = " + org); 1568 } 1569 Set managedResourceNames = new HashSet(3); 1570 if (ocm == null) { 1571 try { 1572 ocm = new OrganizationConfigManager(token, givenOrgName); 1573 } catch (SMSException sme) { 1574 String[] objs = { org }; 1575 throw (new PolicyException(ResBundleUtils.rbName, 1576 "unable_to_get_org_config_manager_for_org", 1577 objs, sme)); 1578 } 1579 } 1580 1581 Set orgAliases = null; 1582 try { 1583 Map orgAttributes = ocm.getAttributes(ID_REPO_SERVICE); 1584 orgAliases 1585 = (Set)orgAttributes.get(ORG_ALIAS); 1586 if (debug.messageEnabled()) { 1587 debug.message("PolicyManager.getOrgAliasMappedResourceNames(): " 1588 + " orgName = " + org 1589 + ":orgAliases=" + orgAliases); 1590 } 1591 } catch (SMSException sme) { 1592 String[] objs = { org }; 1593 throw (new PolicyException(ResBundleUtils.rbName, 1594 "unable_to_get_org_alias_for_org", objs, sme)); 1595 } 1596 if (orgAliases != null) { 1597 Iterator iter = orgAliases.iterator(); 1598 while (iter.hasNext()) { 1599 String orgAlias = (String)iter.next(); 1600 managedResourceNames.add(ORG_ALIAS_URL_HTTP_PREFIX 1601 + orgAlias.trim() 1602 + ORG_ALIAS_URL_SUFFIX); 1603 managedResourceNames.add(ORG_ALIAS_URL_HTTPS_PREFIX 1604 + orgAlias.trim() 1605 + ORG_ALIAS_URL_SUFFIX); 1606 } 1607 } 1608 if (debug.messageEnabled()) { 1609 debug.message("PolicyManager.getOrgAliasMappedResourceNames(): " 1610 + " returning: orgName = " + org 1611 + ":orgAliases=" + orgAliases 1612 + ":managedResourceNames=" + managedResourceNames); 1613 } 1614 return managedResourceNames; 1615 } 1616 1617 public Set getManagedResourceNames(String serviceName) 1618 throws PolicyException { 1619 return (isMigratedToEntitlementService()) ? 1620 getManagedResourceNamesE(serviceName) : 1621 getManagedResourceNamesO(serviceName); 1622 } 1623 1624 public Set getManagedResourceNamesE(String serviceName) { 1625 // Legacy code and application model has changed. Simply returning an empty set. 1626 return Collections.emptySet(); 1627 } 1628 1629 1630 public Set getManagedResourceNamesO(String serviceName) 1631 throws PolicyException { 1632 Set managedResourceNames = new HashSet(); 1633 Set delegatedResourceNames = rm.getManagedResourceNames(serviceName); 1634 if (delegatedResourceNames != null) { 1635 managedResourceNames.addAll(delegatedResourceNames); 1636 } 1637 if (WEB_AGENT_SERVICE.equalsIgnoreCase(serviceName) 1638 && PolicyConfig.orgAliasMappedResourcesEnabled() ) { 1639 managedResourceNames.addAll(getOrgAliasMappedResourceNames()); 1640 } 1641 if (debug.messageEnabled()) { 1642 debug.message("PolicyManager.getManagedResourceNames(): " 1643 + " returning: orgName = " + org 1644 + ":serviceName=" + serviceName 1645 + ":managedResourceNames=" + managedResourceNames); 1646 } 1647 return managedResourceNames; 1648 } 1649 1650 public Set getManagedResourceNames() 1651 throws PolicyException { 1652 Set managedResourceNames = rm.getManagedResourceNames(); 1653 if ((managedResourceNames == null) 1654 || (managedResourceNames == Collections.EMPTY_SET)) { 1655 managedResourceNames = new HashSet(); 1656 } 1657 managedResourceNames.addAll(getOrgAliasMappedResourceNames()); 1658 if (debug.messageEnabled()) { 1659 debug.message("PolicyManager.getManagedResourceNames(): " 1660 + " returning: orgName = " + org 1661 + ":managedResourceNames=" + managedResourceNames); 1662 } 1663 return managedResourceNames; 1664 } 1665 1666 String getOrgAliasWithResource(String resourceName) 1667 throws PolicyException, SSOException { 1668 if (debug.messageEnabled()) { 1669 debug.message("PolicyManager.getOrgAliasWithResource(): " 1670 + " orgName = " + org 1671 + ", resourceName = " + resourceName); 1672 } 1673 if (resourceName == null) { 1674 return null; 1675 } 1676 String orgAlias = null; 1677 try { 1678 URL url = new URL(resourceName); 1679 orgAlias = url.getHost(); 1680 } catch (MalformedURLException mfe) { 1681 String[] objs = { resourceName }; 1682 if (debug.messageEnabled()) { 1683 debug.message("PolicyManager.getOrgAliasWithResource(): " 1684 + " orgName = " + org 1685 + ", resourceName = " + resourceName 1686 + " is invalid URL, no org alias mapping can be found"); 1687 } 1688 } 1689 return orgAlias; 1690 } 1691 1692 String getOrgNameWithAlias(String orgAlias) 1693 throws PolicyException, SSOException { 1694 String aliasMappedOrg = null; 1695 try { 1696 aliasMappedOrg = IdUtils.getOrganization(token, orgAlias); 1697 } catch (IdRepoException re) { 1698 //idRepo throws exception if there is no mapping 1699 if (debug.messageEnabled()) { 1700 debug.message("PolicyManager.getOrgNameWithAlias(): " 1701 + " can not get orgName for orgAlias = " + orgAlias); 1702 } 1703 } 1704 if (debug.messageEnabled()) { 1705 debug.message("PolicyManager.getOrgNameWithAlias(): " 1706 + " orgAlias = " + orgAlias 1707 + ", mapped org = " + aliasMappedOrg); 1708 } 1709 return aliasMappedOrg; 1710 } 1711 1712 public boolean canCreatePolicies(Set<String> services) 1713 throws EntitlementException { 1714 String realm = DNMapper.orgNameToRealmName(getOrganizationDN()); 1715 if (realm.equals("/")) { 1716 return true; 1717 } 1718 1719 if (isMigratedToEntitlementService()) { 1720 for (String s : services) { 1721 Set<String> res = ApplicationManager.getReferredResources( 1722 adminSubject, realm, s); 1723 if ((res != null) && !res.isEmpty()) { 1724 return true; 1725 } 1726 } 1727 return false; 1728 } else { 1729 return canCreateNewResource(services) || 1730 hasReferredResources(); 1731 } 1732 } 1733 1734 private boolean canCreateNewResource(Set<String> services) { 1735 boolean can = false; 1736 ResourceManager resMgr = getResourceManager(); 1737 1738 if (resMgr != null) { 1739 if ((services != null) && !services.isEmpty()) { 1740 for (Iterator i = services.iterator(); (i.hasNext() && !can);) { 1741 String svcName = (String)i.next(); 1742 try { 1743 can = resMgr.canCreateNewResource(svcName); 1744 } catch (PolicyException e) { 1745 debug.warning("PolicyManager.canCreateNewResource",e); 1746 } 1747 } 1748 } 1749 } 1750 1751 return can; 1752 } 1753 1754 private boolean hasReferredResources() { 1755 boolean hasPrefixes = false; 1756 try { 1757 Set prefixes = getManagedResourceNames(); 1758 hasPrefixes = (prefixes != null) && !prefixes.isEmpty(); 1759 } catch (PolicyException e) { 1760 debug.warning("PolicyManager.hasReferredResources", e); 1761 } 1762 return hasPrefixes; 1763 } 1764 1765 static boolean isMigratedToEntitlementService() { 1766 1767 // This must be non-null for the migratedToEntitlementService to have been 1768 // calculated correctly 1769 if (adminSubject == null) { 1770 initialise(); 1771 } 1772 1773 return migratedToEntitlementService; 1774 } 1775 1776 private static void initialise() { 1777 1778 // Do this outside of a static block to avoid issues on container shutdown/restart 1779 adminSubject = SubjectUtils.createSubject( 1780 (SSOToken)AccessController.doPrivileged(AdminTokenAction.getInstance())); 1781 EntitlementConfiguration ec = 1782 EntitlementConfiguration.getInstance(adminSubject, "/"); 1783 migratedToEntitlementService = ec.migratedToEntitlementService(); 1784 } 1785 1786 public boolean canCreateNewResource(String svcTypeName) { 1787 boolean can = false; 1788 if (isMigratedToEntitlementService()) { 1789 ResourceManager resMgr = getResourceManager(); 1790 if (resMgr != null) { 1791 try { 1792 can = resMgr.canCreateNewResource(svcTypeName); 1793 } catch (PolicyException e) { 1794 debug.warning("PolicyManager.canCreateNewResource",e); 1795 } 1796 } 1797 } else { 1798 String realm = DNMapper.orgNameToRealmName(getOrganizationDN()); 1799 can = realm.equals("/"); 1800 } 1801 return can; 1802 } 1803}