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 2013-2017 Ping Identity Corporation 026 */ 027 028package com.unboundid.directory.sdk.broker.api; 029 030import com.unboundid.directory.sdk.broker.internal.BrokerExtension; 031import com.unboundid.directory.sdk.broker.types.BrokerContext; 032import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider; 033import com.unboundid.directory.sdk.common.internal.Reconfigurable; 034import com.unboundid.directory.sdk.common.internal.UnboundIDExtension; 035import com.unboundid.directory.sdk.broker.config. 036 PolicyInformationProviderConfig; 037import com.unboundid.directory.sdk.broker.types.RequestAttribute; 038import com.unboundid.directory.sdk.broker.types.RequestContext; 039import com.unboundid.ldap.sdk.ResultCode; 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 Broker 053 * extensions that retrieve XACML attributes as part of the Policy Information 054 * Point (PIP). 055 * 056 * <H2>Configuring Policy Information Providers</H2> 057 * In order to configure a policy information provider created using this API, 058 * use a command like: 059 * 060 * <PRE> 061 * dsconfig create-policy-information-provider \ 062 * --provider-name "<I>{name}</I>" \ 063 * --type third-party \ 064 * --set enabled:true \ 065 * --set "extension-class:<I>{class-name}</I>" \ 066 * --set "extension-argument:<I>{name=value}</I>" \ 067 * --set "xacml-attribute-id:<I>{attributeId}</I> \ 068 * --set "evaluation-order-index:<I>{index}</I> 069 * </PRE> 070 * where "<I>{name}</I>" is the name to use for the policy information provider 071 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java 072 * class that extends 073 * {@code com.unboundid.directory.sdk.broker.api.PolicyInformationProvider}, 074 * "<I>{index}</I>" is an integer from 1 to 9999 that is used to determine the 075 * position of this Policy Information Provider in the order of evaluation 076 * among all Policy Information Providers, "<I>{attributeId}</I>" identifies 077 * the XACML attribute(s) that this provider knows how to retrieve, and 078 * "<I>{name=value}</I>" represents name-value pairs for any additional 079 * arguments to provide to the Policy Information Provider. If multiple 080 * arguments should be provided to extension, then the 081 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be 082 * provided multiple times. If the Policy Information Provider can retrieve 083 * more than one attribute type, then the 084 * "<CODE>--set xacml-attribute-id:<I>{attributeId}</I></CODE>" option can also 085 * be provided multiple times. 086 */ 087@Extensible() 088@BrokerExtension() 089@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE) 090public abstract class PolicyInformationProvider 091 implements UnboundIDExtension, 092 Reconfigurable<PolicyInformationProviderConfig>, 093 ExampleUsageProvider 094{ 095 096 /** 097 * {@inheritDoc} 098 */ 099 public abstract String getExtensionName(); 100 101 /** 102 * {@inheritDoc} 103 */ 104 public abstract String[] getExtensionDescription(); 105 106 107 /** 108 * {@inheritDoc} 109 */ 110 public void defineConfigArguments(final ArgumentParser parser) 111 throws ArgumentException 112 { 113 // No arguments will be allowed by default. 114 } 115 116 117 /** 118 * Initializes this policy information provider. 119 * 120 * @param serverContext A handle to the server context for the server in 121 * which this extension is running. 122 * @param config The general configuration for this policy 123 * information provider. 124 * @param parser The argument parser which has been initialized from 125 * the configuration for this policy information 126 * provider. 127 * 128 * @throws Exception If a problem occurs while initializing this 129 * policy information provider. 130 */ 131 public void initializePolicyInformationProvider( 132 final BrokerContext serverContext, 133 final PolicyInformationProviderConfig config, 134 final ArgumentParser parser) 135 throws Exception 136 { 137 // No initialization will be performed by default. 138 } 139 140 141 /** 142 * {@inheritDoc} 143 */ 144 public boolean isConfigurationAcceptable( 145 final PolicyInformationProviderConfig config, 146 final ArgumentParser parser, 147 final List<String> unacceptableReasons) 148 { 149 150 // No extended validation will be performed by default. 151 return true; 152 } 153 154 155 /** 156 * {@inheritDoc} 157 */ 158 public ResultCode applyConfiguration( 159 final PolicyInformationProviderConfig config, 160 final ArgumentParser parser, 161 final List<String> adminActionsRequired, 162 final List<String> messages) 163 { 164 // By default, no configuration changes will be applied. If there are any 165 // arguments, then add an admin action message indicating that the 166 // extension needs to be restarted for any changes to take effect. 167 if (! parser.getNamedArguments().isEmpty()) 168 { 169 adminActionsRequired.add( 170 "No configuration change has actually been applied. The new " + 171 "configuration will not take effect until this policy " + 172 "information provider is disabled and re-enabled or until " + 173 "the server is restarted."); 174 } 175 return ResultCode.SUCCESS; 176 177 } 178 179 180 /** 181 * Performs any cleanup which may be necessary when this policy information 182 * provider is to be taken out of service. 183 */ 184 public void finalizePolicyInformationProvider() 185 { 186 // no implementation is required 187 } 188 189 190 /** 191 * Retrieve an attribute that has been requested by the policy engine in order 192 * to resolve a XACML AttributeDesignator element. 193 * @param categoryId XACML category identifier. This is the category Id 194 * specified by the AttributeDesignator element in the 195 * policy that is requesting this attribute. 196 * @param attributeId XACML attribute identifier. This will be one of the 197 * identifiers specified by the xacml-attribute-id 198 * property of the configuration for this Policy 199 * Information Provider. 200 * @param context request context, can be used to retrieve other 201 * attributes from the request that may be needed 202 * in order to evaluate the requested attribute 203 * @return RequestAttribute object containing the requested attribute, 204 * never null. 205 * @throws Exception if an error occurs retrieving the attribute 206 */ 207 public abstract RequestAttribute getAttribute( 208 final String categoryId, 209 final String attributeId, 210 final RequestContext context) throws Exception; 211 212 /** 213 * Retrieve JSON content that has been requested by the policy engine in 214 * order to resolve a XACML AttributeSelector element. 215 * @param categoryId XACML category identifier. This is the category Id 216 * specified by the AttributeSelector element in the 217 * policy that is requesting this attribute. 218 * @param context request context, can be used to retrieve other 219 * attributes from the request that may be needed 220 * in order to retrieve the requested content 221 * @return a JSON-formatted object string, or null if no content 222 * is available. 223 * @throws Exception if an error occurs retrieving the content 224 */ 225 public abstract String getJsonContent( 226 final String categoryId, 227 final RequestContext context) throws Exception; 228 229 /** 230 * Retrieve additional or narrowed JSON content using the specified context 231 * selector. 232 * @param categoryContent Previously retrieved content for the Attributes 233 * category. 234 * @param contextSelectorId optional ContextSelectorId. This is the 235 * context selector string specified in the 236 * AttributeSelector. 237 * @param context request context, can be used to retrieve other 238 * attributes from the request that may be needed 239 * in order to retrieve the requested content 240 * @return a JSON-formatted object string, or null if no content 241 * is available. 242 * @throws Exception if an error occurs retrieving the content 243 */ 244 public String getJsonContent( 245 final String categoryContent, 246 final String contextSelectorId, 247 final RequestContext context) throws Exception { 248 249 // default implementation: context selectors not supported. Override 250 // this if the extension can support contextSelector elements. 251 throw new UnsupportedOperationException( 252 String.format("Context Selectors not supported by PIP extension %s", 253 this.getExtensionName())); 254 } 255 256 257 /** 258 * Determine whether this Policy Information Provider can retrieve the 259 * specified attribute from the specified attributes category. 260 * @param categoryId XACML category identifier. This is the category Id 261 * specified by the AttributeDesignator element in the 262 * policy that is requesting this attribute. 263 * @param attributeId XACML attribute identifier as specified in the 264 * AttributeDesignator element in the policy that is 265 * requesting the attribute. 266 * @param context request context 267 * @return true if this PolicyInformationProvider is able to retrieve the 268 * specified attribute. 269 */ 270 public abstract boolean canGetAttribute( 271 final String categoryId, 272 final String attributeId, 273 final RequestContext context); 274 275 276 /** 277 * Determine whether this Policy Information Provider can retrieve JSON 278 * content for the specified attributes category and optionally, 279 * ContextSelectorId. 280 * @param categoryId XACML category identifier. This is the category Id 281 * specified by the AttributeSelector element in the 282 * policy that is requesting this attribute. 283 * @param contextSelectorId optional ContextSelectorId. This is the 284 * context selector string specified in the 285 * AttributeSelector. 286 * @param context request context 287 * @return true if this PolicyInformationProvider is able to retrieve the 288 * specified content. 289 */ 290 public abstract boolean canGetJsonContent( 291 final String categoryId, 292 final String contextSelectorId, 293 final RequestContext context); 294 295 296 /** 297 * {@inheritDoc} 298 */ 299 public Map<List<String>,String> getExamplesArgumentSets() 300 { 301 return Collections.emptyMap(); 302 } 303} 304