001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * docs/licenses/cddl.txt 011 * or http://www.opensource.org/licenses/cddl1.php. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * docs/licenses/cddl.txt. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2017-2018 Ping Identity Corporation 026 */ 027 028 029package com.unboundid.directory.sdk.broker.api; 030 031import com.unboundid.directory.sdk.broker.config.PolicyObligationConfig; 032import com.unboundid.directory.sdk.broker.internal.BrokerExtension; 033import com.unboundid.directory.sdk.broker.types.BrokerContext; 034import com.unboundid.directory.sdk.broker.types.NotFulfilledException; 035import com.unboundid.directory.sdk.broker.types.ObligationContext; 036import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider; 037import com.unboundid.directory.sdk.common.internal.UnboundIDExtension; 038 039import com.unboundid.scim2.common.GenericScimResource; 040import com.unboundid.scim2.common.exceptions.ScimException; 041import com.unboundid.scim2.common.messages.PatchRequest; 042import com.unboundid.util.Extensible; 043import com.unboundid.util.ThreadSafety; 044import com.unboundid.util.ThreadSafetyLevel; 045import com.unboundid.util.args.ArgumentException; 046import com.unboundid.util.args.ArgumentParser; 047 048import java.util.Collections; 049import java.util.List; 050import java.util.Map; 051 052 053/** 054 * This class defines an API that must be implemented by extensions that 055 * implement custom Policy Obligations. This obligation is invoked when 056 * policy evaluation results in this type of obligation being returned to the 057 * Policy Enforcement Point. 058 * 059 * <H2>Configuring Policy Obligation</H2> 060 * In order to configure a policy obligation created using this API, 061 * use a command like: 062 * 063 * <PRE> 064 * dsconfig create-policy-obligation \ 065 * --obligation-name "<I>{name}</I>" \ 066 * --type third-party \ 067 * --policy-name "<I>{policy-name}</I>" \ 068 * --rule-name "<I>{rule-name}</I>" \ 069 * --set "extension-class:<I>{class-name}</I>" \ 070 * --set "extension-argument:<I>{name=value}</I>" \ 071 * --set "obligation-arguments:<I>{name=jexlExpression}</I>" \ 072 * --set "evaluation-order-index:<I>{index}</I> 073 * </PRE> 074 * where "<I>{name}</I>" is the name to use for the policy obligation 075 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java 076 * class that extends 077 * {@code com.unboundid.directory.sdk.broker.api.PolicyObligation}, 078 * "<I>{policy-name}</I>" and <I>{rule-name}</I>" identify the policy and 079 * policy rule, respectively, that will contain this obligation expression. 080 * <I>{name=jexlExpression}</I> pairs specified using obligation-arguments 081 * identify arguments whose value may be specified or computed during policy 082 * evaluation before being passed into this obligation implementation. 083 * "<I>{index}</I>" is an integer from 1 to 9999 that is used to determine the 084 * order in which this type of obligation should be invoked relative to other 085 * obligations that may be returned from the same policy evaluation. 086 * "<I>{name=value}</I>" pairs specified using extension-arguments are 087 * constant-valued arguments that are provided to the obligation implementation 088 * at initialization time. 089 * If multiple obligation arguments should be provided at each invocation, then 090 * the "<CODE>--set obligation-argument:<I>{name=jexlExpression}</I></CODE>" 091 * option should be provided multiple times. 092 * If multiple initialization arguments should be provided to the extension, 093 * then the "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" 094 * option should be provided multiple times. 095 */ 096@Extensible() 097@BrokerExtension 098@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE) 099public abstract class PolicyObligation 100 implements UnboundIDExtension, 101 ExampleUsageProvider { 102 103 /** 104 * No-args constructor. 105 */ 106 public PolicyObligation() { 107 // No implementation is required. 108 } 109 110 111 /** 112 * {@inheritDoc} 113 */ 114 @Override 115 public abstract String getExtensionName(); 116 117 118 /** 119 * {@inheritDoc} 120 */ 121 @Override 122 public abstract String[] getExtensionDescription(); 123 124 125 /** 126 * {@inheritDoc} 127 */ 128 @Override 129 public Map<List<String>,String> getExamplesArgumentSets() { 130 return Collections.emptyMap(); 131 } 132 133 134 /** 135 * {@inheritDoc} 136 */ 137 @Override 138 public void defineConfigArguments(final ArgumentParser parser) 139 throws ArgumentException { 140 // No arguments will be allowed by default. 141 } 142 143 144 /** 145 * Initializes this Policy Obligation implementation. 146 * @param serverContext A handle to the server context for the server in 147 * which this extension is running. 148 * @param config The general configuration for this policy 149 * obligation. 150 * @param parser The argument parser which has been initialized from 151 * the configuration for this policy obligation. 152 * 153 * @throws Exception If a problem occurs while initializing this 154 * policy obligation. 155 */ 156 public void initializePolicyObligation( 157 final BrokerContext serverContext, 158 final PolicyObligationConfig config, 159 final ArgumentParser parser) throws Exception { 160 // No initialization will be performed by default. 161 } 162 163 164 /** 165 * Performs any cleanup which may be necessary when this policy obligation 166 * is to be taken out of service. 167 */ 168 public void finalizePolicyObligation() { 169 // no implementation is required 170 } 171 172 173 /** 174 * This method is invoked if this obligation is returned from policy during a 175 * SCIM create operation. The method is invoked before the new resource 176 * has been saved to the data store. 177 * 178 * @param context ObligationContext containing any arguments passed 179 * from policy. 180 * @param resource The resource to be created. 181 * @return The (possibly modified) resource to be created. 182 * @throws NotFulfilledException thrown if the obligation cannot be 183 * fulfilled. Will abort the SCIM create operation and 184 * will cause an unauthorized response to be returned to 185 * the caller. 186 * @throws ScimException thrown if an internal error occurs. 187 */ 188 public GenericScimResource onScimCreate( 189 final ObligationContext context, 190 final GenericScimResource resource) 191 throws NotFulfilledException, ScimException { 192 193 // no implementation required 194 return resource; 195 } 196 197 198 /** 199 * This method is invoked if this obligation is returned from policy during 200 * a SCIM delete operation. The method is invoked before the deletion is 201 * committed to the data store. 202 * 203 * @param context ObligationContext containing any arguments passed 204 * from policy. 205 * @throws NotFulfilledException thrown if the obligation cannot be 206 * fulfilled. Will abort the SCIM delete operation and 207 * will cause an unauthorized response to be returned to 208 * the caller. 209 * @throws ScimException thrown if an internal error occurs. 210 */ 211 public void onScimDelete( 212 final ObligationContext context) 213 throws NotFulfilledException, ScimException { 214 215 // no implementation required 216 } 217 218 219 /** 220 * This method is invoked if this obligation is returned from policy during a 221 * SCIM PATCH or PUT operation. The method is invoked before the modified 222 * resource has been saved to the data store. 223 * 224 * @param context ObligationContext containing any arguments passed 225 * from policy. 226 * @param patchRequest A normalized SCIM patch request describing the 227 * requested modifications. A "normalized" patch request 228 * in this context means that the patch will have the 229 * following characteristics: 230 * 231 * For add and remove operations, sub-attributes will 232 * always appear in the value portion rather than in the 233 * path. 234 * 235 * Paths referencing core attributes will not contain the 236 * schema URN. 237 * 238 * Operations without a path will be broken down into 239 * separate operations for each attribute originally 240 * referenced in the value portion. 241 * 242 * @return The (possibly modified) patch request. 243 * @throws NotFulfilledException thrown if the obligation cannot be 244 * fulfilled. Will abort the SCIM modify operation and 245 * will cause an unauthorized response to be returned to 246 * the caller. 247 * @throws ScimException thrown if an internal error occurs. 248 */ 249 public PatchRequest onScimModify( 250 final ObligationContext context, 251 final PatchRequest patchRequest) 252 throws NotFulfilledException, ScimException { 253 254 // no implementation required 255 return patchRequest; 256 } 257 258 259 /** 260 * This method is invoked if this obligation is returned from policy during a 261 * SCIM retrieve operation. The method is invoked before the resource 262 * is added to the SCIM response. 263 * 264 * @param context ObligationContext containing any arguments passed 265 * from policy. 266 * @param resource The resource to be returned to the client. 267 * @return The (possibly modified) resource to be returned. 268 * @throws NotFulfilledException thrown if the obligation cannot be 269 * fulfilled. Will abort the SCIM retrieve operation and 270 * will cause an unauthorized response to be returned to 271 * the caller. 272 * @throws ScimException thrown if an internal error occurs. 273 */ 274 public GenericScimResource onScimRetrieve( 275 final ObligationContext context, 276 final GenericScimResource resource) 277 throws NotFulfilledException, ScimException { 278 279 // no implementation required 280 return resource; 281 } 282 283 284 /** 285 * This method is invoked if this obligation is returned from policy prior to 286 * a SCIM search operation. The method is invoked before the search is 287 * executed. 288 * 289 * @param context ObligationContext containing any arguments passed 290 * from policy. 291 * @param filter The SCIM search filter requested by the client, or 292 * null if no filter was specified. 293 * @return The (possibly modified) SCIM search filter. 294 * @throws NotFulfilledException thrown if the obligation cannot be 295 * fulfilled. Will abort the SCIM search operation and 296 * will cause an unauthorized response to be returned to 297 * the caller. 298 * @throws ScimException thrown if an internal error occurs. 299 */ 300 public String onScimSearch( 301 final ObligationContext context, 302 final String filter) 303 throws NotFulfilledException, ScimException { 304 305 // no implementation required 306 return filter; 307 } 308 309}