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 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