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