View Javadoc
1   /*
2    * Copyright 2024 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.bremersee.spring.boot.autoconfigure.ldaptive;
18  
19  import java.time.Duration;
20  import java.util.ArrayList;
21  import java.util.List;
22  import lombok.Data;
23  import lombok.EqualsAndHashCode;
24  import lombok.Getter;
25  import lombok.Setter;
26  import lombok.ToString;
27  import org.springframework.boot.context.properties.ConfigurationProperties;
28  
29  /**
30   * The ldaptive connection properties.
31   *
32   * @author Christian Bremer
33   */
34  @ConfigurationProperties(prefix = "bremersee.ldaptive")
35  @Getter
36  @Setter
37  @ToString(exclude = {"bindCredentials"})
38  @EqualsAndHashCode(exclude = {"bindCredentials"})
39  public class LdaptiveConnectionProperties {
40  
41    /**
42     * The ldaptive template class.
43     */
44    private Class<?> ldaptiveTemplateClass;
45  
46    /**
47     * Specifies whether the connection configuration is immutable or not.
48     */
49    private boolean immutable;
50  
51    /**
52     * URL of the LDAP server(s) separated by space. For example
53     * {@code ldaps://ldap1.example.org:636 ldaps://ldap2.example.org:636}.
54     */
55    private String ldapUrl;
56  
57    /**
58     * Duration of time that connects will block.
59     */
60    private Duration connectTimeout = Duration.ofMinutes(1);
61  
62    /**
63     * Duration of time to wait for startTLS responses.
64     */
65    private Duration startTlsTimeout = Duration.ofMinutes(1);
66  
67    /**
68     * Duration of time to wait for responses.
69     */
70    private Duration responseTimeout = Duration.ofMinutes(1);
71  
72    /**
73     * Duration of time that operations will block on reconnects, should generally be longer than
74     * connect timeout.
75     */
76    private Duration reconnectTimeout = Duration.ofMinutes(2);
77  
78    /**
79     * Whether to automatically reconnect to the server when a connection is lost. Default is true.
80     */
81    private boolean autoReconnect = true;
82  
83    /**
84     * The reconnect strategy.
85     */
86    private ReconnectStrategy reconnectStrategy = ReconnectStrategy.ONE_RECONNECT_ATTEMPT;
87  
88    /**
89     * Whether pending operations should be replayed after a reconnect. Default is true.
90     */
91    private boolean autoReplay = true;
92  
93    /**
94     * The ssl configuration.
95     */
96    private SslProperties sslConfig = new SslProperties();
97  
98    /**
99     * Connect to LDAP using startTLS.
100    */
101   private boolean useStartTls;
102 
103   /**
104    * DN to bind as before performing operations.
105    */
106   private String bindDn;
107 
108   /**
109    * Credential for the bind DN.
110    */
111   private String bindCredentials;
112 
113   /**
114    * Perform a fast bind, if no credentials are present.
115    */
116   private boolean fastBind = false;
117 
118   /**
119    * The connection strategy.
120    */
121   private ConnectionStrategy connectionStrategy = ConnectionStrategy.ACTIVE_PASSIVE;
122 
123   /**
124    * The connection validator.
125    */
126   private ConnectionValidatorProperties connectionValidator = new ConnectionValidatorProperties();
127 
128   /**
129    * Specifies whether the connection should be pooled or not. Default is {@code false}.
130    */
131   private boolean pooled = false;
132 
133   /**
134    * The connection pool configuration.
135    */
136   private ConnectionPoolProperties connectionPool = new ConnectionPoolProperties();
137 
138   /**
139    * Instantiates new ldaptive connection properties.
140    */
141   public LdaptiveConnectionProperties() {
142     super();
143   }
144 
145   /**
146    * The reconnection strategy.
147    */
148   public enum ReconnectStrategy {
149 
150     /**
151      * One reconnect attempt strategy.
152      */
153     ONE_RECONNECT_ATTEMPT,
154 
155     /**
156      * Infinite reconnect attempts strategy.
157      */
158     INFINITE_RECONNECT_ATTEMPTS,
159 
160     /**
161      * Infinite reconnect attempts with backoff strategy.
162      */
163     INFINITE_RECONNECT_ATTEMPTS_WITH_BACKOFF
164 
165   }
166 
167   /**
168    * The ssl configuration.
169    */
170   @Data
171   public static class SslProperties {
172 
173     /**
174      * Path of the trust certificates to use for the SSL connection.
175      */
176     private String trustCertificates;
177 
178     /**
179      * Path of the authentication certificate to use for the SSL connection.
180      */
181     private String authenticationCertificate;
182 
183     /**
184      * Path of the key to use for the SSL connection.
185      */
186     private String authenticationKey;
187 
188     /**
189      * The hostname verifier.
190      */
191     private HostnameVerifier hostnameVerifier = HostnameVerifier.DEFAULT;
192 
193     /**
194      * Instantiates new ssl properties.
195      */
196     public SslProperties() {
197       super();
198     }
199 
200     /**
201      * The hostname verifier.
202      */
203     public enum HostnameVerifier {
204 
205       /**
206        * The default hostname verifier.
207        */
208       DEFAULT,
209 
210       /**
211        * Hostname verifier that returns true for any hostname. Use with caution.
212        */
213       ALLOW_ANY
214 
215     }
216   }
217 
218   /**
219    * The connection strategy.
220    */
221   public enum ConnectionStrategy {
222 
223     /**
224      * Attempt each URL in the order provided for each connection. The URLs are always tried in the
225      * order in which they were provided.
226      */
227     ACTIVE_PASSIVE,
228 
229     /**
230      * Attempt a random URL from a list of URLs.
231      */
232     RANDOM,
233 
234     /**
235      * Attempt the next URL in the order provided for each connection. URLs are rotated regardless
236      * of connection success or failure.
237      */
238     ROUND_ROBIN,
239 
240     /**
241      * Queries a DNS server for SRV records and uses those records to construct a list of URLs. When
242      * configuring this strategy you must use your DNS server for {@code setLdapUrl(String)} in the
243      * form {@code dns://my.server.com}.
244      */
245     DNS
246 
247   }
248 
249   /**
250    * The search validator properties.
251    */
252   @Data
253   public static class ConnectionValidatorProperties {
254 
255     /**
256      * Validation period.
257      */
258     private Duration validatePeriod = Duration.ofMinutes(30);
259 
260     /**
261      * Maximum length of time a connection validation should block.
262      */
263     private Duration validateTimeout = Duration.ofSeconds(5);
264 
265     /**
266      * The search request.
267      */
268     private SearchRequestProperties searchRequest = new SearchRequestProperties();
269 
270     /**
271      * Instantiates new connection validator properties.
272      */
273     public ConnectionValidatorProperties() {
274       super();
275     }
276 
277     /**
278      * The search request properties.
279      */
280     @Data
281     public static class SearchRequestProperties {
282 
283       /**
284        * The base dn (like {@code ou=peoples,dc=example,dc=org}).
285        */
286       private String baseDn;
287 
288       /**
289        * The search filter.
290        */
291       private SearchFilterProperties searchFilter = new SearchFilterProperties();
292 
293       /**
294        * The size limit.
295        */
296       private Integer sizeLimit;
297 
298       /**
299        * The search scope.
300        */
301       private SearchScope searchScope;
302 
303       /**
304        * The return attributes.
305        */
306       private List<String> returnAttributes = new ArrayList<>();
307 
308       /**
309        * Instantiates new search request properties.
310        */
311       public SearchRequestProperties() {
312         super();
313       }
314 
315       /**
316        * The search filter properties.
317        */
318       @Data
319       public static class SearchFilterProperties {
320 
321         /**
322          * The search filter (like {@code (&(objectClass=inetOrgPerson)(uid=administrator))}).
323          */
324         private String filter;
325 
326         /**
327          * Instantiates new search filter properties.
328          */
329         public SearchFilterProperties() {
330           super();
331         }
332       }
333     }
334   }
335 
336   /**
337    * The connection pool properties.
338    */
339   @Data
340   public static class ConnectionPoolProperties {
341 
342     /**
343      * Duration to wait for an available connection.
344      */
345     private Duration blockWaitTime = Duration.ofMinutes(1);
346 
347     /**
348      * Minimum pool size.
349      */
350     private int minPoolSize = 3;
351 
352     /**
353      * Maximum pool size.
354      */
355     private int maxPoolSize = 10;
356 
357     /**
358      * Whether to connect to the ldap on connection creation.
359      */
360     private boolean connectOnCreate = true;
361 
362     /**
363      * Whether initialize should throw if pooling configuration requirements are not met.
364      */
365     private boolean failFastInitialize = true;
366 
367     /**
368      * Whether the ldap object should be validated when returned to the pool.
369      */
370     private boolean validateOnCheckIn = false;
371 
372     /**
373      * Whether the ldap object should be validated when given from the pool.
374      */
375     private boolean validateOnCheckOut = false;
376 
377     /**
378      * Whether the pool should be validated periodically.
379      */
380     private boolean validatePeriodically = false;
381 
382     /**
383      * The validator for the connections in the pool.
384      */
385     private ConnectionValidatorProperties validator = new ConnectionValidatorProperties();
386 
387     /**
388      * Prune period.
389      */
390     private Duration prunePeriod = Duration.ofMinutes(5);
391 
392     /**
393      * Idle time.
394      */
395     private Duration idleTime = Duration.ofMinutes(10);
396 
397     /**
398      * Instantiates new connection pool properties.
399      */
400     public ConnectionPoolProperties() {
401       super();
402     }
403   }
404 
405   /**
406    * The enum Search scope.
407    */
408   public enum SearchScope {
409 
410     /**
411      * Base object search.
412      */
413     OBJECT,
414 
415     /**
416      * Single level search.
417      */
418     ONELEVEL,
419 
420     /**
421      * Whole subtree search.
422      */
423     SUBTREE,
424 
425     /**
426      * Subordinate subtree search. See draft-sermersheim-ldap-subordinate-scope.
427      */
428     SUBORDINATE
429   }
430 }