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