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