View Javadoc
1   /*
2    * Copyright 2019 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.data.ldaptive;
18  
19  import java.time.Duration;
20  import java.util.ArrayList;
21  import java.util.LinkedHashMap;
22  import java.util.LinkedList;
23  import java.util.List;
24  import java.util.Map;
25  import javax.validation.constraints.Min;
26  import javax.validation.constraints.NotNull;
27  import lombok.EqualsAndHashCode;
28  import lombok.Getter;
29  import lombok.NoArgsConstructor;
30  import lombok.Setter;
31  import lombok.ToString;
32  import org.bremersee.data.ldaptive.transcoder.UserAccountControlValueTranscoder;
33  import org.ldaptive.ReturnAttributes;
34  import org.ldaptive.SearchConnectionValidator;
35  import org.ldaptive.SearchRequest;
36  import org.ldaptive.SearchScope;
37  import org.springframework.boot.context.properties.ConfigurationProperties;
38  import org.springframework.util.StringUtils;
39  import org.springframework.validation.annotation.Validated;
40  
41  /**
42   * The ldap properties.
43   *
44   * @author Christian Bremer
45   */
46  @SuppressWarnings({"WeakerAccess"})
47  @ConfigurationProperties(prefix = "bremersee.ldaptive")
48  @Validated
49  @Getter
50  @Setter
51  @ToString(exclude = {"bindCredentials"})
52  @EqualsAndHashCode(exclude = {"bindCredentials"})
53  @NoArgsConstructor
54  public class LdaptiveProperties {
55  
56    /**
57     * Specifies whether ldap connection should be configured or not.
58     */
59    private boolean enabled = true;
60  
61    /**
62     * Specifies whether an ldap user details service should be configured or not.
63     */
64    private boolean authenticationEnabled = false;
65  
66    /**
67     * URL to the LDAP(s).
68     */
69    private String ldapUrl = "ldap://localhost:12389";
70  
71    /**
72     * Duration of time that connects will block.
73     */
74    @NotNull
75    private Duration connectTimeout = Duration.ofMinutes(1);
76  
77    /**
78     * Duration of time to wait for responses.
79     */
80    @NotNull
81    private Duration responseTimeout = Duration.ofMinutes(1);
82  
83    /**
84     * Duration of time that operations will block on reconnects, should generally be longer than connect timeout.
85     */
86    @NotNull
87    private Duration reconnectTimeout = Duration.ofMinutes(2);
88  
89    /**
90     * Whether to automatically reconnect to the server when a connection is lost. Default is true.
91     */
92    private boolean autoReconnect = true;
93  
94    @Min(0)
95    private int reconnectAttempts = 5;
96  
97    @NotNull
98    private Duration reconnectBackoffDelay = Duration.ofSeconds(2);
99  
100   private double reconnectBackoffMultiplier = 1.;
101 
102   /**
103    * Whether pending operations should be replayed after a reconnect. Default is true.
104    */
105   private boolean autoReplay = true;
106 
107   /**
108    * Connect to LDAP using startTLS.
109    */
110   private boolean useStartTls;
111 
112   /**
113    * Name of the trust certificates to use for the SSL connection.
114    */
115   private String trustCertificates;
116 
117   /**
118    * Name of the authentication certificate to use for the SSL connection.
119    */
120   private String authenticationCertificate;
121 
122   /**
123    * Name of the key to use for the SSL connection.
124    */
125   private String authenticationKey;
126 
127   /**
128    * DN to bind as before performing operations.
129    */
130   private String bindDn;
131 
132   /**
133    * Credential for the bind DN.
134    */
135   private String bindCredentials;
136 
137   /**
138    * Specifies whether the connection should be pooled or not. Default is {@code false}.
139    */
140   private boolean pooled = false;
141 
142   /**
143    * Duration to wait for an available connection.
144    */
145   @NotNull
146   private Duration blockWaitTime = Duration.ofMinutes(1);
147 
148   /**
149    * Minimum pool size.
150    */
151   private int minPoolSize = 3;
152 
153   /**
154    * Maximum pool size.
155    */
156   private int maxPoolSize = 10;
157 
158   /**
159    * Whether to connect to the ldap on connection creation.
160    */
161   private boolean connectOnCreate = true;
162 
163   /**
164    * Whether initialize should throw if pooling configuration requirements are not met.
165    */
166   private boolean failFastInitialize = true;
167 
168   /**
169    * Whether the ldap object should be validated when returned to the pool.
170    */
171   private boolean validateOnCheckIn = false;
172 
173   /**
174    * Whether the ldap object should be validated when given from the pool.
175    */
176   private boolean validateOnCheckOut = false;
177 
178   /**
179    * Whether the pool should be validated periodically.
180    */
181   private boolean validatePeriodically = false;
182 
183   /**
184    * Validation period.
185    */
186   @NotNull
187   private Duration validatePeriod = Duration.ofMinutes(30);
188 
189   /**
190    * Maximum length of time a connection validation should block.
191    */
192   @NotNull
193   private Duration validateTimeout = Duration.ofSeconds(5);
194 
195   @NotNull
196   private SearchValidatorProperties searchValidator = new SearchValidatorProperties();
197 
198   /**
199    * Prune period.
200    */
201   @NotNull
202   private Duration prunePeriod = Duration.ofMinutes(5);
203 
204   /**
205    * Idle time.
206    */
207   @NotNull
208   private Duration idleTime = Duration.ofMinutes(10);
209 
210   @NotNull
211   private UserDetailsProperties userDetails = new UserDetailsProperties();
212 
213   /**
214    * Create search connection validator search connection validator.
215    *
216    * @return the search connection validator
217    */
218   @NotNull
219   public SearchConnectionValidator createSearchConnectionValidator() {
220     return new SearchConnectionValidator(
221         validatePeriod,
222         validateTimeout,
223         searchValidator.getSearchRequest().createSearchRequest());
224   }
225 
226   /**
227    * The search validator properties.
228    */
229   @Getter
230   @Setter
231   @ToString
232   @EqualsAndHashCode
233   @NoArgsConstructor
234   public static class SearchValidatorProperties {
235 
236     @NotNull
237     private SearchRequestProperties searchRequest = new SearchRequestProperties();
238 
239     /**
240      * The search request properties.
241      */
242     @Getter
243     @Setter
244     @ToString
245     @EqualsAndHashCode
246     @NoArgsConstructor
247     public static class SearchRequestProperties {
248 
249       private String baseDn;
250 
251       @NotNull
252       private SearchFilterProperties searchFilter = new SearchFilterProperties();
253 
254       private Integer sizeLimit;
255 
256       private SearchScope searchScope; // = SearchScope.ONELEVEL;
257 
258       @NotNull
259       private List<String> returnAttributes = new ArrayList<>();
260 
261       /**
262        * Gets the return attributes as array.
263        *
264        * @return the return attributes as array
265        */
266       @NotNull
267       public String[] returnAttributesAsArray() {
268         if (returnAttributes.isEmpty()) {
269           return ReturnAttributes.NONE.value();
270         }
271         return returnAttributes.toArray(new String[0]);
272       }
273 
274       /**
275        * Create search request.
276        *
277        * @return the search request
278        */
279       @NotNull
280       public SearchRequest createSearchRequest() {
281         SearchRequest searchRequest = new SearchRequest();
282         searchRequest.setBaseDn(StringUtils.hasText(getBaseDn()) ? getBaseDn() : "");
283         if (StringUtils.hasText(getSearchFilter().getFilter())) {
284           searchRequest.setFilter(getSearchFilter().getFilter());
285         }
286         searchRequest.setReturnAttributes(returnAttributesAsArray());
287         if (getSearchScope() != null) {
288           searchRequest.setSearchScope(getSearchScope());
289         }
290         if (getSizeLimit() != null) {
291           searchRequest.setSizeLimit(getSizeLimit());
292         }
293         return searchRequest;
294       }
295 
296       /**
297        * The search filter properties.
298        */
299       @Getter
300       @Setter
301       @ToString
302       @EqualsAndHashCode
303       @NoArgsConstructor
304       public static class SearchFilterProperties {
305 
306         private String filter;
307 
308       }
309     }
310   }
311 
312   /**
313    * The user details properties.
314    */
315   @Getter
316   @Setter
317   @ToString
318   @EqualsAndHashCode
319   @NoArgsConstructor
320   public static class UserDetailsProperties {
321 
322     private String userBaseDn;
323 
324     private String userFindOneFilter = "(&(objectClass=group)(sAMAccountName={0}))";
325 
326     private SearchScope userFindOneSearchScope = SearchScope.ONELEVEL;
327 
328     private String userAccountControlAttributeName = UserAccountControlValueTranscoder.ATTRIBUTE_NAME;
329 
330     private String authorityAttributeName = "memberOf";
331 
332     private boolean authorityDn = true;
333 
334     private List<String> authorities = new LinkedList<>();
335 
336     private Map<String, String> authorityMap = new LinkedHashMap<>();
337 
338     private String authorityPrefix = "ROLE_";
339 
340     private String userPasswordAttributeName = "userPassword";
341 
342     private String userPasswordLabel = "SHA";
343 
344     private String userPasswordAlgorithm = "SHA";
345 
346   }
347 }