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 * Portions Copyright 2018-2024 Ping Identity Corporation 026 */ 027 028package com.unboundid.directory.sdk.broker.api; 029 030import com.unboundid.directory.sdk.broker.config.AdviceConfig; 031import com.unboundid.directory.sdk.broker.internal.BrokerExtension; 032import com.unboundid.directory.sdk.broker.types.AdviceStatement; 033import com.unboundid.directory.sdk.broker.types.BrokerContext; 034import com.unboundid.directory.sdk.broker.types.HttpRequestResponse; 035import com.unboundid.directory.sdk.broker.types.NotFulfilledException; 036import com.unboundid.directory.sdk.broker.types.PolicyRequestDetails; 037import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider; 038import com.unboundid.directory.sdk.common.internal.UnboundIDExtension; 039import com.unboundid.util.Extensible; 040import com.unboundid.util.ThreadSafety; 041import com.unboundid.util.ThreadSafetyLevel; 042import com.unboundid.util.args.ArgumentException; 043import com.unboundid.util.args.ArgumentParser; 044 045import java.util.Collections; 046import java.util.List; 047import java.util.Map; 048 049 050/** 051 * This class defines an API that must be implemented by extensions that 052 * implement custom Advice for policies. This advice is invoked when policy 053 * evaluation results in this type of advice being returned to the Policy 054 * Enforcement Point. 055 * 056 * <H2>Configuring Advice</H2> 057 * In order to configure policy advice created using this API, 058 * use a command like: 059 * 060 * <PRE> 061 * dsconfig create-advice \ 062 * --advice-name "<I>{name}</I>" \ 063 * --type third-party \ 064 * --set "advice-id:<I>{advice-code}</I> 065 * --set "extension-class:<I>{class-name}</I>" \ 066 * --set "extension-argument:<I>{name=value}</I>" \ 067 * --set "evaluation-order-index:<I>{index}</I> 068 * </PRE> 069 * where "<I>{name}</I>" is a user-friendly name to use for the advice 070 * type, "<I>{advice-code}</I>" is a unique advice code that must match the 071 * "code" string returned from a policy invocation, and "<I>{class-name}</I>" 072 * is the fully-qualified name of the Java class that extends 073 * {@code com.unboundid.directory.sdk.broker.api.Advice}. 074 * 075 * "<I>{index}</I>" is an integer from 1 to 9999 that is used to determine the 076 * order in which this type of advice should be invoked relative to other advice 077 * that may be returned from the same policy evaluation. 078 * "<I>{name=value}</I>" pairs specified using extension-arguments are values 079 * that are provided to the advice implementation at initialization time. 080 * If multiple initialization arguments should be provided to the extension, 081 * then the "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option 082 * should be provided multiple times. 083 */ 084@Extensible() 085@BrokerExtension 086@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE) 087public abstract class Advice 088 implements UnboundIDExtension, ExampleUsageProvider { 089 090 /** 091 * No-args constructor. 092 */ 093 public Advice() { 094 // no implementation is required. 095 } 096 097 /** 098 * {@inheritDoc} 099 */ 100 @Override 101 public abstract String getExtensionName(); 102 103 104 /** 105 * {@inheritDoc} 106 */ 107 @Override 108 public abstract String[] getExtensionDescription(); 109 110 111 /** 112 * {@inheritDoc} 113 */ 114 @Override 115 public Map<List<String>,String> getExamplesArgumentSets() { 116 return Collections.emptyMap(); 117 } 118 119 120 /** 121 * {@inheritDoc} 122 */ 123 @Override 124 public void defineConfigArguments(final ArgumentParser parser) 125 throws ArgumentException { 126 // No arguments will be allowed by default. 127 } 128 129 /** 130 * Initializes this Advice implementation. 131 * @param serverContext A handle to the server context for the server in 132 * which this extension is running. 133 * @param config The general configuration for this Advice. 134 * @param parser The argument parser which has been initialized from 135 * the configuration for this Advice. 136 * @throws Exception If a problem occurs while initializing this Advice. 137 */ 138 public void initializeAdvice( 139 final BrokerContext serverContext, 140 final AdviceConfig config, 141 final ArgumentParser parser) throws Exception { 142 // No initialization performed by default. 143 } 144 145 146 /** 147 * Performs any cleanup which may be necessary when this advice 148 * is to be taken out of service. 149 */ 150 public void finalizeAdvice() { 151 // No implementation is required. 152 } 153 154 155 /** 156 * This method is invoked when the specified Advice type is returned by 157 * policy evaluation. 158 * @param requestDetails Details of the authorization request that 159 * triggered the advice. 160 * @param statements List of advice instances with payload and 161 * attributes containing advice details. 162 * @param requestResponse HTTP Request or Response that may be examined or 163 * manipulated by the advice implementation. The 164 * resource details are dependent upon the API method 165 * that requested authorization and the type of request 166 * being authorized. As an example, for a create 167 * operation the request body may represent the 168 * resource the client is attempting to create, while 169 * for a retrieve operation the response body may 170 * represent the resource to be returned to the client. 171 * @return the (possibly modified) request or response. 172 * @throws NotFulfilledException if the advice cannot be successfully 173 * applied. If the advice is defined to be obligatory, throwing this 174 * exception will cause the requested operation to fail. If the advice is 175 * not obligatory, throwing this exception will cause an error to be logged, 176 * however the requested operation will not otherwise be impacted. 177 */ 178 public abstract HttpRequestResponse apply( 179 final PolicyRequestDetails requestDetails, 180 List<? extends AdviceStatement> statements, 181 HttpRequestResponse requestResponse) throws NotFulfilledException; 182}