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.PolicyAdviceConfig; 032import com.unboundid.directory.sdk.broker.internal.BrokerExtension; 033import com.unboundid.directory.sdk.broker.types.AdviceContext; 034import com.unboundid.directory.sdk.broker.types.BrokerContext; 035import com.unboundid.directory.sdk.broker.types.OpenBankingErrorResponse; 036import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider; 037import com.unboundid.directory.sdk.common.internal.UnboundIDExtension; 038import com.unboundid.scim2.common.exceptions.ScimException; 039import com.unboundid.scim2.common.messages.ErrorResponse; 040import com.unboundid.util.Extensible; 041import com.unboundid.util.ThreadSafety; 042import com.unboundid.util.ThreadSafetyLevel; 043import com.unboundid.util.args.ArgumentException; 044import com.unboundid.util.args.ArgumentParser; 045 046import java.util.Collections; 047import java.util.List; 048import java.util.Map; 049 050 051/** 052 * This class defines an API that must be implemented by extensions that 053 * implement custom Policy Advice. This advice is invoked when policy 054 * evaluation results in this type of advice being returned to the Policy 055 * Enforcement Point. 056 * 057 * <H2>Configuring Policy Advice</H2> 058 * In order to configure policy advice created using this API, 059 * use a command like: 060 * 061 * <PRE> 062 * dsconfig create-policy-advice \ 063 * --advice-name "<I>{name}</I>" \ 064 * --type third-party \ 065 * --policy-name "<I>{policy-name}</I>" \ 066 * --rule-name "<I>{rule-name}</I>" \ 067 * --set "extension-class:<I>{class-name}</I>" \ 068 * --set "extension-argument:<I>{name=value}</I>" \ 069 * --set "advice-arguments:<I>{name=jexlExpression}</I>" \ 070 * --set "evaluation-order-index:<I>{index}</I> 071 * </PRE> 072 * where "<I>{name}</I>" is the name to use for the policy advice 073 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java 074 * class that extends 075 * {@code com.unboundid.directory.sdk.broker.api.PolicyAdvice}, 076 * "<I>{policy-name}</I>" and <I>{rule-name}</I>" identify the policy and 077 * policy rule, respectively, that will contain this advice expression. 078 * <I>{name=jexlExpression}</I> pairs specified using advice-arguments identify 079 * arguments whose value may be specified or computed during policy evaluation 080 * before being passed into this advice implementation. 081 * "<I>{index}</I>" is an integer from 1 to 9999 that is used to determine the 082 * order in which this type of advice should be invoked relative to other advice 083 * that may be returned from the same policy evaluation. 084 * "<I>{name=value}</I>" pairs specified using extension-arguments are values 085 * that are provided to the advice implementation at initialization time. 086 * If multiple advice arguments should be provided at each invocation, then the 087 * "<CODE>--set advice-argument:<I>{name=jexlExpression}</I></CODE>" option 088 * should be provided multiple times. 089 * If multiple initialization arguments should be provided to the extension, 090 * then the "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option 091 * should be provided multiple times. 092 */ 093@Extensible() 094@BrokerExtension 095@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE) 096public abstract class PolicyAdvice 097 implements UnboundIDExtension, 098 ExampleUsageProvider { 099 100 /** 101 * No-args constructor. 102 */ 103 public PolicyAdvice() { 104 // no implementation required. 105 } 106 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override 112 public abstract String getExtensionName(); 113 114 115 /** 116 * {@inheritDoc} 117 */ 118 @Override 119 public abstract String[] getExtensionDescription(); 120 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override 126 public Map<List<String>,String> getExamplesArgumentSets() { 127 return Collections.emptyMap(); 128 } 129 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override 135 public void defineConfigArguments(final ArgumentParser parser) 136 throws ArgumentException { 137 // No arguments will be allowed by default. 138 } 139 140 141 /** 142 * Initializes this Policy Advice implementation. 143 * @param serverContext A handle to the server context for the server in 144 * which this extension is running. 145 * @param adviceCfg The general configuration for this policy advice. 146 * @param parser The argument parser which has been initialized from 147 * the configuration for this policy advice. 148 * 149 * @throws Exception If a problem occurs while initializing this 150 * policy advice. 151 */ 152 public void initializePolicyAdvice( 153 final BrokerContext serverContext, 154 final PolicyAdviceConfig adviceCfg, 155 final ArgumentParser parser) throws Exception { 156 // No initialization will be performed by default. 157 } 158 159 160 /** 161 * Performs any cleanup which may be necessary when this policy advice 162 * is to be taken out of service. 163 */ 164 public void finalizePolicyAdvice() { 165 // no implementation is required 166 } 167 168 169 /** 170 * This method is called if this advice is returned by policy when a SCIM 171 * request is denied. 172 * @param context AdviceContext containing any arguments passed 173 * from policy. 174 * @param errorInfo the default error information that will be 175 * returned if nothing is done by the advice 176 * implementation. 177 * @return the modified error info 178 * @throws ScimException if an internal error occurs trying to generate 179 * the advice. 180 */ 181 public ErrorResponse onScimDeny( 182 final AdviceContext context, 183 final ErrorResponse errorInfo) throws ScimException { 184 185 // default implementation: no-op. 186 return errorInfo; 187 } 188 189 /** 190 * This method is called if this advice is returned by policy when an Open 191 * Banking API request is denied. 192 * @param context AdviceContext containing any arguments passed 193 * from policy. 194 * @param errorInfo the default error information that will be 195 * returned if nothing is done by the advice 196 * implementation. 197 * @return the modified error info 198 */ 199 public OpenBankingErrorResponse onOpenBankingDeny( 200 final AdviceContext context, 201 final OpenBankingErrorResponse errorInfo) { 202 203 // default implementation: no-op 204 return errorInfo; 205 } 206}