001package com.identityworksllc.iiq.common; 002 003import com.identityworksllc.iiq.common.auth.DummyAuthContext; 004import sailpoint.api.SailPointContext; 005import sailpoint.authorization.LcmRequestAuthorizer; 006import sailpoint.authorization.QuickLinkLaunchAuthorizer; 007import sailpoint.authorization.UnauthorizedAccessException; 008import sailpoint.object.Identity; 009import sailpoint.object.Identity.CapabilityManager; 010import sailpoint.object.QuickLink; 011import sailpoint.tools.GeneralException; 012 013import java.util.Objects; 014 015/** 016 * Utilities for authorization, e.g., whether a user can view a QuickLink. For the 017 * Common Security style of authorization, use ThingAccessUtils instead. 018 */ 019public class AuthUtilities extends AbstractBaseUtility { 020 021 /** 022 * Indicates the type of access to a QuickLink we are checking 023 */ 024 public enum QuickLinkAccessType { 025 /** 026 * Check ANY type of access (self or other) 027 */ 028 ANY, 029 /** 030 * Check whether this user can invoke this QuickLink on other users 031 */ 032 OTHER, 033 /** 034 * Check whether this user can invoke this QuickLink on themselves 035 */ 036 SELF 037 } 038 039 /** 040 * Constructs a new instance of AuthUtilities 041 * @param c 042 */ 043 public AuthUtilities(SailPointContext c) { 044 super(c); 045 } 046 047 /** 048 * Returns true if the given person could launch the given QuickLink against the given target. 049 * 050 * You may pass a null target or a target the same as the launcher to infer an access type of 051 * SELF. If the target is not null and does not match the launcher, an access type of OTHER 052 * will be inferred. 053 * 054 * @param launcher The person we're testing for access 055 * @param target The (optional) target against whom the QuickLink would be executed 056 * @param what The QuickLink we're testing 057 * @return true if the launcher could perform this QL operation 058 * @throws GeneralException if any IIQ failure occurs 059 */ 060 public boolean canAccessQuicklink(Identity launcher, Identity target, QuickLink what) throws GeneralException { 061 Objects.requireNonNull(launcher, "The 'launcher' Identity must not be null"); 062 if (target == null || target.getId().equals(launcher.getId())) { 063 return canAccessQuicklink(launcher, launcher, what, QuickLinkAccessType.SELF); 064 } else { 065 return canAccessQuicklink(launcher, target, what, QuickLinkAccessType.SELF); 066 } 067 } 068 069 /** 070 * Returns true if the given person could launch the given QuickLink against the given target. Pass a 071 * null target to take the QuickLinkAccessType into account, e.g. if you just need a general "can see 072 * in any circumstance" answer. 073 * 074 * @param launcher The person we're testing for access 075 * @param target The (optional) target against whom the QuickLink would be executed 076 * @param what The QuickLink we're testing 077 * @param accessType The access type we're interested in 078 * @return true if the launcher could perform this QL operation 079 * @throws GeneralException if any IIQ failure occurs 080 */ 081 public boolean canAccessQuicklink(Identity launcher, Identity target, QuickLink what, QuickLinkAccessType accessType) throws GeneralException { 082 Objects.requireNonNull(launcher, "The 'launcher' Identity must not be null"); 083 DummyAuthContext authContext = new DummyAuthContext(context, launcher.getName()); 084 if (accessType == QuickLinkAccessType.ANY) { 085 return canViewQuicklink(launcher, what, accessType); 086 } else { 087 String lcmAction = null; 088 if (!(what.getAction().equals(QuickLink.ACTION_WORKFLOW) || what.getAction().equals(QuickLink.ACTION_EXTERNAL))) { 089 lcmAction = what.getAction(); 090 } 091 if (target == null && accessType == QuickLinkAccessType.SELF) { 092 target = launcher; 093 } 094 LcmRequestAuthorizer authorizer = new LcmRequestAuthorizer(target); 095 authorizer.setQuickLinkName(what.getName()); 096 authorizer.setAction(lcmAction); 097 try { 098 authorizer.authorize(authContext); 099 return true; 100 } catch(UnauthorizedAccessException e) { 101 return false; 102 } 103 } 104 } 105 106 /** 107 * Returns true if the user in question can view the QuickLink under any circumstances (i.e. if it would be displayed on their sidebar). 108 * @param launcher The user to query 109 * @param what The QuickLink to check 110 * @param accessType The access type to check for 111 * @return If the user would have access to this QuickLink, true, otherwise false 112 * @throws GeneralException if any IIQ failure occurs 113 */ 114 public boolean canViewQuicklink(Identity launcher, QuickLink what, QuickLinkAccessType accessType) throws GeneralException { 115 DummyAuthContext authContext = new DummyAuthContext(context, launcher.getName()); 116 try { 117 QuickLinkLaunchAuthorizer authorizer = new QuickLinkLaunchAuthorizer(what, accessType == QuickLinkAccessType.ANY || accessType == QuickLinkAccessType.SELF); 118 authorizer.authorize(authContext); 119 return true; 120 } catch(UnauthorizedAccessException e) { 121 if (accessType == QuickLinkAccessType.ANY) { 122 try { 123 QuickLinkLaunchAuthorizer authorizer = new QuickLinkLaunchAuthorizer(what, false); 124 authorizer.authorize(authContext); 125 return true; 126 } catch(UnauthorizedAccessException e2) { 127 return false; 128 } 129 } 130 return false; 131 } 132 } 133 134 /** 135 * Throws an exception if the given Identity does not have the given right (optionally 136 * also allowing sysadmins). 137 * 138 * @param who The identity to test 139 * @param what The SPRight to test for 140 * @param allowAdmins If true, SystemAdministrators will also be allowed, even without the SPRight 141 * @throws UnauthorizedAccessException if the user does not have access 142 */ 143 public void checkAuthorization(Identity who, String what, boolean allowAdmins) throws UnauthorizedAccessException { 144 boolean allowed = false; 145 CapabilityManager cm = who.getCapabilityManager(); 146 if (allowAdmins) { 147 allowed = cm.hasCapability("SystemAdministrator"); 148 } 149 if (!allowed) { 150 allowed = cm.hasRight(what); 151 } 152 if (!allowed) { 153 throw new UnauthorizedAccessException("Access to this resource requires SPRight " + what); 154 } 155 } 156 157}