View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.wa.bootstrap.mapping;
20  
21  import java.util.Map;
22  import java.util.Optional;
23  import java.util.concurrent.TimeUnit;
24  import java.util.stream.Collectors;
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.syncope.client.lib.SyncopeClient;
27  import org.apache.syncope.common.lib.auth.AbstractOIDCAuthModuleConf;
28  import org.apache.syncope.common.lib.auth.AppleOIDCAuthModuleConf;
29  import org.apache.syncope.common.lib.auth.AuthModuleConf;
30  import org.apache.syncope.common.lib.auth.AzureOIDCAuthModuleConf;
31  import org.apache.syncope.common.lib.auth.DuoMfaAuthModuleConf;
32  import org.apache.syncope.common.lib.auth.GoogleMfaAuthModuleConf;
33  import org.apache.syncope.common.lib.auth.GoogleOIDCAuthModuleConf;
34  import org.apache.syncope.common.lib.auth.JDBCAuthModuleConf;
35  import org.apache.syncope.common.lib.auth.JaasAuthModuleConf;
36  import org.apache.syncope.common.lib.auth.KeycloakOIDCAuthModuleConf;
37  import org.apache.syncope.common.lib.auth.LDAPAuthModuleConf;
38  import org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf;
39  import org.apache.syncope.common.lib.auth.OIDCAuthModuleConf;
40  import org.apache.syncope.common.lib.auth.SAML2IdPAuthModuleConf;
41  import org.apache.syncope.common.lib.auth.SimpleMfaAuthModuleConf;
42  import org.apache.syncope.common.lib.auth.StaticAuthModuleConf;
43  import org.apache.syncope.common.lib.auth.SyncopeAuthModuleConf;
44  import org.apache.syncope.common.lib.auth.U2FAuthModuleConf;
45  import org.apache.syncope.common.lib.auth.X509AuthModuleConf;
46  import org.apache.syncope.common.lib.to.AuthModuleTO;
47  import org.apache.syncope.common.lib.to.Item;
48  import org.apache.syncope.common.lib.types.AuthModuleState;
49  import org.apache.syncope.wa.bootstrap.WARestClient;
50  import org.apereo.cas.configuration.CasCoreConfigurationUtils;
51  import org.apereo.cas.configuration.model.core.authentication.AuthenticationHandlerStates;
52  import org.apereo.cas.configuration.model.support.generic.AcceptAuthenticationProperties;
53  import org.apereo.cas.configuration.model.support.jaas.JaasAuthenticationProperties;
54  import org.apereo.cas.configuration.model.support.jdbc.authn.QueryJdbcAuthenticationProperties;
55  import org.apereo.cas.configuration.model.support.ldap.AbstractLdapAuthenticationProperties.AuthenticationTypes;
56  import org.apereo.cas.configuration.model.support.ldap.AbstractLdapProperties;
57  import org.apereo.cas.configuration.model.support.ldap.LdapAuthenticationProperties;
58  import org.apereo.cas.configuration.model.support.mfa.DuoSecurityMultifactorAuthenticationProperties;
59  import org.apereo.cas.configuration.model.support.mfa.gauth.GoogleAuthenticatorMultifactorProperties;
60  import org.apereo.cas.configuration.model.support.mfa.gauth.LdapGoogleAuthenticatorMultifactorProperties;
61  import org.apereo.cas.configuration.model.support.mfa.simple.CasSimpleMultifactorAuthenticationProperties;
62  import org.apereo.cas.configuration.model.support.mfa.u2f.U2FMultifactorAuthenticationProperties;
63  import org.apereo.cas.configuration.model.support.pac4j.oauth.Pac4jOAuth20ClientProperties;
64  import org.apereo.cas.configuration.model.support.pac4j.oidc.BasePac4jOidcClientProperties;
65  import org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jAppleOidcClientProperties;
66  import org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jAzureOidcClientProperties;
67  import org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jGenericOidcClientProperties;
68  import org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jGoogleOidcClientProperties;
69  import org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jKeyCloakOidcClientProperties;
70  import org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jOidcClientProperties;
71  import org.apereo.cas.configuration.model.support.pac4j.saml.Pac4jSamlClientProperties;
72  import org.apereo.cas.configuration.model.support.syncope.SyncopeAuthenticationProperties;
73  import org.apereo.cas.configuration.model.support.x509.SubjectDnPrincipalResolverProperties.SubjectDnFormat;
74  import org.apereo.cas.configuration.model.support.x509.X509LdapProperties;
75  import org.apereo.cas.configuration.model.support.x509.X509Properties;
76  import org.apereo.cas.configuration.model.support.x509.X509Properties.PrincipalTypes;
77  import org.apereo.cas.util.ResourceUtils;
78  import org.apereo.cas.util.model.TriStateBoolean;
79  
80  public class AuthModulePropertySourceMapper extends PropertySourceMapper implements AuthModuleConf.Mapper {
81  
82      protected final WARestClient waRestClient;
83  
84      public AuthModulePropertySourceMapper(final WARestClient waRestClient) {
85          this.waRestClient = waRestClient;
86      }
87  
88      @Override
89      public Map<String, Object> map(final AuthModuleTO authModuleTO, final StaticAuthModuleConf conf) {
90          AcceptAuthenticationProperties props = new AcceptAuthenticationProperties();
91          props.setName(authModuleTO.getKey());
92          props.setState(AuthenticationHandlerStates.valueOf(authModuleTO.getState().name()));
93          props.setOrder(authModuleTO.getOrder());
94          String users = conf.getUsers().entrySet().stream().
95                  map(entry -> entry.getKey() + "::" + entry.getValue()).
96                  collect(Collectors.joining(","));
97          props.setUsers(users);
98  
99          return prefix("cas.authn.accept.", CasCoreConfigurationUtils.asMap(props));
100     }
101 
102     @Override
103     public Map<String, Object> map(final AuthModuleTO authModuleTO, final LDAPAuthModuleConf conf) {
104         LdapAuthenticationProperties props = new LdapAuthenticationProperties();
105         props.setName(authModuleTO.getKey());
106         props.setState(AuthenticationHandlerStates.valueOf(authModuleTO.getState().name()));
107         props.setOrder(authModuleTO.getOrder());
108 
109         props.setType(AuthenticationTypes.valueOf(conf.getAuthenticationType().name()));
110         props.setDnFormat(conf.getDnFormat());
111         props.setEnhanceWithEntryResolver(conf.isEnhanceWithEntryResolver());
112         props.setDerefAliases(Optional.ofNullable(conf.getDerefAliases()).
113                 map(LDAPAuthModuleConf.DerefAliasesType::name).orElse(null));
114         props.setResolveFromAttribute(conf.getResolveFromAttribute());
115 
116         props.setPrincipalAttributeId(conf.getPrincipalAttributeId());
117         props.setPrincipalDnAttributeName(conf.getPrincipalDnAttributeName());
118         props.setPrincipalAttributeList(authModuleTO.getItems().stream().
119                 map(item -> item.getIntAttrName() + ":" + item.getExtAttrName()).collect(Collectors.toList()));
120         props.setAllowMultiplePrincipalAttributeValues(conf.isAllowMultiplePrincipalAttributeValues());
121         props.setAdditionalAttributes(conf.getAdditionalAttributes());
122         props.setAllowMissingPrincipalAttributeValue(conf.isAllowMissingPrincipalAttributeValue());
123         props.setCollectDnAttribute(props.isCollectDnAttribute());
124 
125         props.getPasswordPolicy().setType(AbstractLdapProperties.LdapType.valueOf(conf.getLdapType().name()));
126 
127         fill(props, conf);
128 
129         return prefix("cas.authn.ldap[].", CasCoreConfigurationUtils.asMap(props));
130     }
131 
132     @Override
133     public Map<String, Object> map(final AuthModuleTO authModuleTO, final JDBCAuthModuleConf conf) {
134         QueryJdbcAuthenticationProperties props = new QueryJdbcAuthenticationProperties();
135         props.setName(authModuleTO.getKey());
136         props.setState(AuthenticationHandlerStates.valueOf(authModuleTO.getState().name()));
137         props.setOrder(authModuleTO.getOrder());
138         props.setSql(conf.getSql());
139         props.setFieldDisabled(conf.getFieldDisabled());
140         props.setFieldExpired(conf.getFieldExpired());
141         props.setFieldPassword(conf.getFieldPassword());
142         props.setPrincipalAttributeList(authModuleTO.getItems().stream().
143                 map(item -> item.getIntAttrName() + ":" + item.getExtAttrName()).collect(Collectors.toList()));
144         fill(props, conf);
145 
146         return prefix("cas.authn.jdbc.query[].", CasCoreConfigurationUtils.asMap(props));
147     }
148 
149     @Override
150     public Map<String, Object> map(final AuthModuleTO authModuleTO, final JaasAuthModuleConf conf) {
151         JaasAuthenticationProperties props = new JaasAuthenticationProperties();
152         props.setName(authModuleTO.getKey());
153         props.setState(AuthenticationHandlerStates.valueOf(authModuleTO.getState().name()));
154         props.setOrder(authModuleTO.getOrder());
155         props.setLoginConfigType(conf.getLoginConfigType());
156         props.setKerberosKdcSystemProperty(conf.getKerberosKdcSystemProperty());
157         props.setKerberosRealmSystemProperty(conf.getKerberosRealmSystemProperty());
158         props.setLoginConfigType(conf.getLoginConfigurationFile());
159         props.setRealm(conf.getRealm());
160 
161         return prefix("cas.authn.jaas[].", CasCoreConfigurationUtils.asMap(props));
162     }
163 
164     @Override
165     public Map<String, Object> map(final AuthModuleTO authModuleTO, final OAuth20AuthModuleConf conf) {
166         Pac4jOAuth20ClientProperties props = new Pac4jOAuth20ClientProperties();
167         props.setId(conf.getClientId());
168         props.setSecret(conf.getClientSecret());
169         props.setClientName(Optional.ofNullable(conf.getClientName()).orElse(authModuleTO.getKey()));
170         props.setEnabled(authModuleTO.getState() == AuthModuleState.ACTIVE);
171         props.setCustomParams(conf.getCustomParams());
172         props.setAuthUrl(conf.getAuthUrl());
173         props.setProfilePath(conf.getProfilePath());
174         props.setProfileVerb(conf.getProfileVerb());
175         props.setProfileUrl(conf.getProfileUrl());
176         props.setTokenUrl(conf.getTokenUrl());
177         props.setResponseType(conf.getResponseType());
178         props.setScope(conf.getScope());
179         props.setPrincipalAttributeId(conf.getUserIdAttribute());
180         props.setWithState(conf.isWithState());
181         props.setProfileAttrs(authModuleTO.getItems().stream().
182                 collect(Collectors.toMap(Item::getIntAttrName, Item::getExtAttrName)));
183 
184         return prefix("cas.authn.pac4j.oauth2[].", CasCoreConfigurationUtils.asMap(props));
185     }
186 
187     protected void map(
188             final AuthModuleTO authModuleTO,
189             final BasePac4jOidcClientProperties props,
190             final AbstractOIDCAuthModuleConf conf) {
191 
192         props.setId(conf.getClientId());
193         props.setSecret(conf.getClientSecret());
194         props.setClientName(Optional.ofNullable(conf.getClientName()).orElse(authModuleTO.getKey()));
195         props.setEnabled(authModuleTO.getState() == AuthModuleState.ACTIVE);
196         props.setCustomParams(conf.getCustomParams());
197         props.setDiscoveryUri(conf.getDiscoveryUri());
198         props.setMaxClockSkew(conf.getMaxClockSkew());
199         props.setPreferredJwsAlgorithm(conf.getPreferredJwsAlgorithm());
200         props.setResponseMode(conf.getResponseMode());
201         props.setResponseType(conf.getResponseType());
202         props.setScope(conf.getScope());
203         props.setPrincipalAttributeId(conf.getUserIdAttribute());
204         props.setExpireSessionWithToken(conf.isExpireSessionWithToken());
205         props.setTokenExpirationAdvance(conf.getTokenExpirationAdvance());
206     }
207 
208     @Override
209     public Map<String, Object> map(final AuthModuleTO authModuleTO, final OIDCAuthModuleConf conf) {
210         Pac4jGenericOidcClientProperties props = new Pac4jGenericOidcClientProperties();
211         map(authModuleTO, props, conf);
212 
213         Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
214         client.setGeneric(props);
215 
216         return prefix("cas.authn.pac4j.oidc[].generic.", CasCoreConfigurationUtils.asMap(props));
217     }
218 
219     @Override
220     public Map<String, Object> map(final AuthModuleTO authModuleTO, final AzureOIDCAuthModuleConf conf) {
221         Pac4jAzureOidcClientProperties props = new Pac4jAzureOidcClientProperties();
222         map(authModuleTO, props, conf);
223         props.setTenant(conf.getTenant());
224 
225         Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
226         client.setAzure(props);
227 
228         return prefix("cas.authn.pac4j.oidc[].azure.", CasCoreConfigurationUtils.asMap(props));
229     }
230 
231     @Override
232     public Map<String, Object> map(final AuthModuleTO authModuleTO, final GoogleOIDCAuthModuleConf conf) {
233         Pac4jGoogleOidcClientProperties props = new Pac4jGoogleOidcClientProperties();
234         map(authModuleTO, props, conf);
235 
236         Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
237         client.setGoogle(props);
238 
239         return prefix("cas.authn.pac4j.oidc[].google.", CasCoreConfigurationUtils.asMap(props));
240     }
241 
242     @Override
243     public Map<String, Object> map(final AuthModuleTO authModuleTO, final KeycloakOIDCAuthModuleConf conf) {
244         Pac4jKeyCloakOidcClientProperties props = new Pac4jKeyCloakOidcClientProperties();
245         map(authModuleTO, props, conf);
246         props.setRealm(conf.getRealm());
247         props.setBaseUri(conf.getBaseUri());
248 
249         Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
250         client.setKeycloak(props);
251 
252         return prefix("cas.authn.pac4j.oidc[].keycloak.", CasCoreConfigurationUtils.asMap(props));
253     }
254 
255     @Override
256     public Map<String, Object> map(final AuthModuleTO authModuleTO, final AppleOIDCAuthModuleConf conf) {
257         Pac4jAppleOidcClientProperties props = new Pac4jAppleOidcClientProperties();
258         map(authModuleTO, props, conf);
259         props.setTimeout(conf.getTimeout());
260         props.setPrivateKey(conf.getPrivateKey());
261         props.setPrivateKeyId(conf.getPrivateKeyId());
262         props.setTeamId(conf.getTeamId());
263 
264         Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
265         client.setApple(props);
266 
267         return prefix("cas.authn.pac4j.oidc[].apple.", CasCoreConfigurationUtils.asMap(props));
268     }
269 
270     @Override
271     public Map<String, Object> map(final AuthModuleTO authModuleTO, final SAML2IdPAuthModuleConf conf) {
272         Pac4jSamlClientProperties props = new Pac4jSamlClientProperties();
273         props.setClientName(Optional.ofNullable(conf.getClientName()).orElse(authModuleTO.getKey()));
274         props.setEnabled(authModuleTO.getState() == AuthModuleState.ACTIVE);
275         props.setAcceptedSkew(conf.getAcceptedSkew());
276         props.setAssertionConsumerServiceIndex(conf.getAssertionConsumerServiceIndex());
277         props.setAttributeConsumingServiceIndex(conf.getAttributeConsumingServiceIndex());
278         props.setAuthnContextClassRef(conf.getAuthnContextClassRefs());
279         props.setAuthnContextComparisonType(conf.getAuthnContextComparisonType());
280         props.setBlockedSignatureSigningAlgorithms(conf.getBlockedSignatureSigningAlgorithms());
281         props.setDestinationBinding(conf.getDestinationBinding().getUri());
282         props.setIdentityProviderMetadataPath(conf.getIdentityProviderMetadataPath());
283         props.setKeystoreAlias(conf.getKeystoreAlias());
284         props.setKeystorePassword(conf.getKeystorePassword());
285         props.setMaximumAuthenticationLifetime(conf.getMaximumAuthenticationLifetime());
286         props.setNameIdPolicyFormat(conf.getNameIdPolicyFormat());
287         props.setPrivateKeyPassword(conf.getPrivateKeyPassword());
288         props.setProviderName(conf.getProviderName());
289         props.setServiceProviderEntityId(conf.getServiceProviderEntityId());
290         props.setSignatureAlgorithms(conf.getSignatureAlgorithms());
291         props.setSignatureCanonicalizationAlgorithm(conf.getSignatureCanonicalizationAlgorithm());
292         props.setSignatureReferenceDigestMethods(conf.getSignatureReferenceDigestMethods());
293         props.setPrincipalAttributeId(conf.getUserIdAttribute());
294         props.setNameIdPolicyAllowCreate(StringUtils.isBlank(conf.getNameIdPolicyAllowCreate())
295                 ? TriStateBoolean.UNDEFINED
296                 : TriStateBoolean.valueOf(conf.getNameIdPolicyAllowCreate().toUpperCase()));
297 
298         return prefix("cas.authn.pac4j.saml[].", CasCoreConfigurationUtils.asMap(props));
299     }
300 
301     @Override
302     public Map<String, Object> map(final AuthModuleTO authModuleTO, final X509AuthModuleConf conf) {
303         X509Properties props = new X509Properties();
304         props.setName(conf.getName());
305         props.setOrder(conf.getOrder());
306         props.setCacheDiskOverflow(conf.isCacheDiskOverflow());
307         props.setCacheDiskSize(conf.getCacheDiskSize());
308         props.setCacheEternal(conf.isCacheEternal());
309         props.setCacheMaxElementsInMemory(conf.getCacheMaxElementsInMemory());
310         props.setCacheTimeToLiveSeconds(conf.getCacheTimeToLiveSeconds());
311         props.setCheckAll(conf.isCheckAll());
312         props.setCheckKeyUsage(conf.isCheckKeyUsage());
313         props.setCrlExpiredPolicy(conf.getCrlExpiredPolicy().name());
314         props.setCrlFetcher(conf.getCrlFetcher().name());
315         props.setCrlResourceExpiredPolicy(conf.getCrlResourceExpiredPolicy().name());
316         props.setCrlResourceUnavailablePolicy(conf.getCrlResourceUnavailablePolicy().name());
317         props.setCrlResources(conf.getCrlResources());
318         props.setCrlUnavailablePolicy(conf.getCrlUnavailablePolicy().name());
319         props.setExtractCert(conf.isExtractCert());
320         props.setMaxPathLength(conf.getMaxPathLength());
321         props.setMaxPathLengthAllowUnspecified(conf.isMaxPathLengthAllowUnspecified());
322         props.setMixedMode(conf.isMixedMode());
323         props.setRefreshIntervalSeconds(conf.getRefreshIntervalSeconds());
324         props.setRegExSubjectDnPattern(conf.getRegExSubjectDnPattern());
325         props.setRegExTrustedIssuerDnPattern(conf.getRegExTrustedIssuerDnPattern());
326         props.setRequireKeyUsage(conf.isRequireKeyUsage());
327         props.setRevocationChecker(conf.getRevocationChecker().name());
328         props.setRevocationPolicyThreshold(conf.getRevocationPolicyThreshold());
329         props.setSslHeaderName(conf.getSslHeaderName());
330         props.setThrowOnFetchFailure(conf.isThrowOnFetchFailure());
331 
332         props.setPrincipalType(PrincipalTypes.valueOf(conf.getPrincipalType().name()));
333         if (StringUtils.isNotBlank(conf.getPrincipalAlternateAttribute())) {
334             switch (props.getPrincipalType()) {
335                 case CN_EDIPI:
336                     props.getCnEdipi().setAlternatePrincipalAttribute(conf.getPrincipalAlternateAttribute());
337                     break;
338 
339                 case RFC822_EMAIL:
340                     props.getRfc822Email().setAlternatePrincipalAttribute(conf.getPrincipalAlternateAttribute());
341                     break;
342 
343                 case SUBJECT:
344                     props.setPrincipalDescriptor(conf.getPrincipalAlternateAttribute());
345                     break;
346 
347                 case SUBJECT_ALT_NAME:
348                     props.getSubjectAltName().setAlternatePrincipalAttribute(conf.getPrincipalAlternateAttribute());
349                     break;
350 
351                 case SUBJECT_DN:
352                 case SERIAL_NO_DN:
353                 case SERIAL_NO:
354                 default:
355             }
356         }
357         props.getSubjectDn().setFormat(SubjectDnFormat.valueOf(conf.getPrincipalTypeSubjectDnFormat().name()));
358         props.getSerialNoDn().setSerialNumberPrefix(conf.getPrincipalTypeSerialNoDnSerialNumberPrefix());
359         props.getSerialNoDn().setValueDelimiter(conf.getPrincipalTypeSerialNoDnValueDelimiter());
360         props.getSerialNo().setPrincipalHexSNZeroPadding(conf.isPrincipalTypeSerialNoHexSNZeroPadding());
361         props.getSerialNo().setPrincipalSNRadix(conf.getPrincipalTypeSerialNoSNRadix());
362 
363         if (conf.getLdap() != null) {
364             X509LdapProperties ldapProps = new X509LdapProperties();
365             ldapProps.setCertificateAttribute(conf.getLdap().getCertificateAttribute());
366             fill(ldapProps, conf.getLdap());
367             props.setLdap(ldapProps);
368         }
369 
370         return prefix("cas.authn.x509.", CasCoreConfigurationUtils.asMap(props));
371     }
372 
373     @Override
374     public Map<String, Object> map(final AuthModuleTO authModuleTO, final SyncopeAuthModuleConf conf) {
375         SyncopeClient syncopeClient = waRestClient.getSyncopeClient();
376         if (syncopeClient == null) {
377             LOG.warn("Application context is not ready to bootstrap WA configuration");
378             return Map.of();
379         }
380 
381         SyncopeAuthenticationProperties props = new SyncopeAuthenticationProperties();
382         props.setName(authModuleTO.getKey());
383         props.setState(AuthenticationHandlerStates.valueOf(authModuleTO.getState().name()));
384         props.setDomain(conf.getDomain());
385         props.setUrl(StringUtils.substringBefore(syncopeClient.getAddress(), "/rest"));
386         props.setAttributeMappings(authModuleTO.getItems().stream().
387                 collect(Collectors.toMap(Item::getIntAttrName, Item::getExtAttrName)));
388 
389         return prefix("cas.authn.syncope.", CasCoreConfigurationUtils.asMap(props));
390     }
391 
392     @Override
393     public Map<String, Object> map(final AuthModuleTO authModuleTO, final GoogleMfaAuthModuleConf conf) {
394         GoogleAuthenticatorMultifactorProperties props = new GoogleAuthenticatorMultifactorProperties();
395         props.setName(authModuleTO.getKey());
396         props.setOrder(authModuleTO.getOrder());
397         props.getCore().setIssuer(conf.getIssuer());
398         props.getCore().setCodeDigits(conf.getCodeDigits());
399         props.getCore().setLabel(conf.getLabel());
400         props.getCore().setTimeStepSize(conf.getTimeStepSize());
401         props.getCore().setWindowSize(conf.getWindowSize());
402 
403         if (conf.getLdap() != null) {
404             LdapGoogleAuthenticatorMultifactorProperties ldapProps = new LdapGoogleAuthenticatorMultifactorProperties();
405             ldapProps.setAccountAttributeName(conf.getLdap().getAccountAttributeName());
406             fill(ldapProps, conf.getLdap());
407             props.setLdap(ldapProps);
408         }
409 
410         return prefix("cas.authn.mfa.gauth.", CasCoreConfigurationUtils.asMap(props));
411     }
412 
413     @SuppressWarnings("deprecation")
414     @Override
415     public Map<String, Object> map(final AuthModuleTO authModuleTO, final DuoMfaAuthModuleConf conf) {
416         DuoSecurityMultifactorAuthenticationProperties props = new DuoSecurityMultifactorAuthenticationProperties();
417         props.setName(authModuleTO.getKey());
418         props.setOrder(authModuleTO.getOrder());
419         props.setDuoApiHost(conf.getApiHost());
420         props.setDuoApplicationKey(conf.getApplicationKey());
421         props.setDuoIntegrationKey(conf.getIntegrationKey());
422         props.setDuoSecretKey(conf.getSecretKey());
423 
424         return prefix("cas.authn.mfa.duo.", CasCoreConfigurationUtils.asMap(props));
425     }
426 
427     @Override
428     public Map<String, Object> map(final AuthModuleTO authModuleTO, final U2FAuthModuleConf conf) {
429         U2FMultifactorAuthenticationProperties props = new U2FMultifactorAuthenticationProperties();
430         props.setName(authModuleTO.getKey());
431         props.setOrder(authModuleTO.getOrder());
432         props.getCore().setExpireDevices(conf.getExpireDevices());
433         props.getCore().setExpireDevicesTimeUnit(TimeUnit.valueOf(conf.getExpireDevicesTimeUnit()));
434         props.getCore().setExpireRegistrations(conf.getExpireRegistrations());
435         props.getCore().setExpireRegistrationsTimeUnit(TimeUnit.valueOf(conf.getExpireRegistrationsTimeUnit()));
436 
437         return prefix("cas.authn.mfa.u2f.", CasCoreConfigurationUtils.asMap(props));
438     }
439 
440     @Override
441     public Map<String, Object> map(final AuthModuleTO authModuleTO, final SimpleMfaAuthModuleConf conf) {
442         CasSimpleMultifactorAuthenticationProperties props = new CasSimpleMultifactorAuthenticationProperties();
443         props.setName(authModuleTO.getKey());
444         props.setOrder(authModuleTO.getOrder());
445 
446         props.getMail().setAttributeName(conf.getEmailAttribute());
447         props.getMail().setFrom(conf.getEmailFrom());
448         props.getMail().setSubject(conf.getEmailSubject());
449         props.getMail().setText(conf.getEmailText());
450 
451         props.getToken().getCore().setTokenLength(conf.getTokenLength());
452         props.getToken().getCore().setTimeToKillInSeconds(conf.getTimeToKillInSeconds());
453 
454         if (StringUtils.isNotBlank(conf.getBypassGroovyScript())) {
455             try {
456                 props.getBypass().getGroovy().setLocation(ResourceUtils.getResourceFrom(conf.getBypassGroovyScript()));
457             } catch (Exception e) {
458                 LOG.error("Unable to load groovy script for bypass", e);
459                 throw new IllegalArgumentException(e);
460             }
461         }
462 
463         return prefix("cas.authn.mfa.simple.", CasCoreConfigurationUtils.asMap(props));
464     }
465 }