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-2014 UnboundID Corp. 026 */ 027 028 package com.unboundid.directory.sdk.broker.api; 029 030 import com.unboundid.directory.sdk.broker.internal.IdentityBrokerExtension; 031 import com.unboundid.directory.sdk.broker.types.IdentityBrokerContext; 032 import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider; 033 import com.unboundid.directory.sdk.common.internal.Reconfigurable; 034 import com.unboundid.directory.sdk.common.internal.UnboundIDExtension; 035 import com.unboundid.directory.sdk.broker.config. 036 PolicyInformationProviderConfig; 037 import com.unboundid.directory.sdk.broker.types.RequestAttribute; 038 import com.unboundid.directory.sdk.broker.types.RequestContext; 039 import com.unboundid.ldap.sdk.ResultCode; 040 import com.unboundid.util.Extensible; 041 import com.unboundid.util.ThreadSafety; 042 import com.unboundid.util.ThreadSafetyLevel; 043 import com.unboundid.util.args.ArgumentException; 044 import com.unboundid.util.args.ArgumentParser; 045 046 import java.util.Collections; 047 import java.util.List; 048 import java.util.Map; 049 050 051 /** 052 * This class defines an API that must be implemented by Identity 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 @IdentityBrokerExtension() 089 @ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE) 090 public 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 IdentityBrokerContext 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. 192 * @param categoryId XACML category identifier. This is the category Id 193 * specified by the AttributeDesignator element in the 194 * policy that is requesting this attribute. 195 * @param attributeId XACML attribute identifier. This will be one of the 196 * identifiers specified by the xacml-attribute-id 197 * property of the configuration for this Policy 198 * Information Provider. 199 * @param context request context, can be used to retrieve other 200 * attributes from the request that may be needed 201 * in order to evaluate the requested attribute 202 * @return RequestAttribute object containing the requested attribute, 203 * never null. 204 * @throws Exception if an error occurs retrieving the attribute 205 */ 206 public abstract RequestAttribute getAttribute( 207 final String categoryId, 208 final String attributeId, 209 RequestContext context) throws Exception; 210 211 212 /** 213 * {@inheritDoc} 214 */ 215 public Map<List<String>,String> getExamplesArgumentSets() 216 { 217 return Collections.emptyMap(); 218 } 219 } 220