public LdapRoleAuthenticationFilter(final LdapProperties ldapProperties) { this.whiteListedPaths = requireNonNull(ldapProperties.getWhitelistedPaths(), "white listed paths must not be null"); this.requiredRole = requireNonNull(ldapProperties.getRequiredRole(), "required role must not be null"); }
final EncryptionType encryptionType, final String... whitelistedPaths) { final LdapProperties ldap = new LdapProperties(); ldap.setEnabled(true); ldap.setHost(host); ldap.setPort(port); ldap.setBaseDn(baseDn); ldap.setRoleBaseDn(roleBaseDn); ldap.setRdnIdentifier(rdnIdentifier); ldap.setPrefixes(prefix); ldap.setEncryptionType(encryptionType); ldap.setWhitelistedPaths(asList(whitelistedPaths)); return ldap;
private LdapProperties mockLdapPropertiesWithProtecedAndWhiteListedPath(final String securedPath, final String whiteListedPath) { final LdapProperties ldapPropertiesMock = mock(LdapProperties.class); when(ldapPropertiesMock.getPrefixes()).thenReturn(singletonList(securedPath)); when(ldapPropertiesMock.getWhitelistedPaths()).thenReturn(singletonList(whiteListedPath)); when(ldapPropertiesMock.getRequiredRole()).thenReturn("someRole"); return ldapPropertiesMock; }
/** * Add an authentication filter that requires a certain LDAP role to access secured paths. * All routes starting with the value of the {@code edison.ldap.prefixes} property will be secured by LDAP. * If no property is set this will default to all routes starting with '/internal'. * * @param ldapProperties the properties used to configure LDAP */ @Bean @ConditionalOnProperty(prefix = "edison.ldap", name = "required-role") public FilterRegistrationBean<LdapRoleAuthenticationFilter> ldapRoleAuthenticationFilter(final LdapProperties ldapProperties) { FilterRegistrationBean<LdapRoleAuthenticationFilter> filterRegistration = new FilterRegistrationBean<>(); filterRegistration.setFilter(new LdapRoleAuthenticationFilter(ldapProperties)); filterRegistration.setOrder(Ordered.LOWEST_PRECEDENCE); ldapProperties.getPrefixes().forEach(prefix -> filterRegistration.addUrlPatterns(String.format("%s/*", prefix))); return filterRegistration; } }
@Override protected boolean shouldNotFilter(final HttpServletRequest request) throws ServletException { final String servletPath = request.getServletPath(); return ldapProperties.getWhitelistedPaths() .stream() .anyMatch(servletPath::startsWith); }
private LdapProperties mockLdapPropertiesWithRequiredRole(final String role) { final LdapProperties ldapPropertiesMock = mock(LdapProperties.class); when(ldapPropertiesMock.getRequiredRole()).thenReturn(role); return ldapPropertiesMock; }
private Optional<HttpServletRequest> tryToGetAuthenticatedRequest(final HttpServletRequest request, final Credentials credentials) { try (final LDAPConnection ldap = ldapConnectionFactory.buildLdapConnection()) { for (String baseDN : ldapProperties.getBaseDn()) { final String userDN = userDnFrom(credentials, baseDN); try { if (authenticate(ldap, userDN, credentials.getPassword())) { return ldapProperties.getRoleBaseDn() != null ? Optional.of(new LdapRoleCheckingRequest(request, ldap, userDN, ldapProperties)) : Optional.of(request); } } catch (LDAPBindException e) { LOG.debug("LDAPBindException for userDN: {}", userDN); } } LOG.warn("Could not bind to LDAP: {}", credentials.getUsername()); } catch (LDAPException | GeneralSecurityException e) { LOG.warn("Authentication error: ", e); } return Optional.empty(); }
String userDnFrom(final Credentials credentials, String baseDN) { return format("%s=%s,%s", ldapProperties.getRdnIdentifier(), credentials.getUsername(), baseDN); }
/** * Constructs a request object wrapping the given request. * * @param request The request to wrap * @throws IllegalArgumentException if the request is null */ public LdapRoleCheckingRequest(final HttpServletRequest request, final LDAPInterface ldapInterface, final String userDN, final LdapProperties ldapProperties) throws LDAPException { super(request); this.ldapInterface = ldapInterface; this.userDN = userDN; this.roleBaseDN = ldapProperties.getRoleBaseDn(); this.userRoles = getRoles(); }
/** * Add an authentication filter to the web application context if edison.ldap property is set to {@code enabled}'. * All routes starting with the value of the {@code edison.ldap.prefix} property will be secured by LDAP. If no * property is set this will default to all routes starting with '/internal'. * * @param ldapProperties the properties used to configure LDAP * @return FilterRegistrationBean */ @Bean @ConditionalOnMissingBean(LdapConnectionFactory.class) public LdapConnectionFactory ldapConnectionFactory(final LdapProperties ldapProperties) { if (ldapProperties.getEncryptionType() == EncryptionType.SSL) { return new SSLLdapConnectionFactory(ldapProperties); } return new StartTlsLdapConnectionFactory(ldapProperties); }
/** * Add an authentication filter to the web application context if edison.ldap property is set to {@code enabled}'. * All routes starting with the value of the {@code edison.ldap.prefix} property will be secured by LDAP. If no * property is set this will default to all routes starting with '/internal'. * * @param ldapProperties the properties used to configure LDAP * @param ldapConnectionFactory the connection factory used to build the LdapAuthenticationFilter * @return FilterRegistrationBean */ @Bean public FilterRegistrationBean<LdapAuthenticationFilter> ldapAuthenticationFilter(final LdapProperties ldapProperties, final LdapConnectionFactory ldapConnectionFactory) { FilterRegistrationBean<LdapAuthenticationFilter> filterRegistration = new FilterRegistrationBean<>(); filterRegistration.setFilter(new LdapAuthenticationFilter(ldapProperties, ldapConnectionFactory)); filterRegistration.setOrder(Ordered.LOWEST_PRECEDENCE - 1); ldapProperties.getPrefixes().forEach(prefix -> filterRegistration.addUrlPatterns(String.format("%s/*", prefix))); return filterRegistration; }
public LDAPConnection buildLdapConnection() throws GeneralSecurityException, LDAPException { final LDAPConnection ldapConnection = new LDAPConnection(ldapProperties.getHost(), ldapProperties.getPort()); ldapConnection.processExtendedOperation(new StartTLSExtendedRequest(SSL_UTIL.createSSLContext())); return ldapConnection; }
@Test public void shouldTryToBuildLdapConnection() { final LdapProperties properties = mock(LdapProperties.class); when(properties.getHost()).thenReturn("foo"); when(properties.getPort()).thenReturn(42); assertThrows(LDAPException.class, () -> { new StartTlsLdapConnectionFactory(properties).buildLdapConnection(); }); } }
@Test public void shouldTryToBuildLdapConnection() { final LdapProperties properties = mock(LdapProperties.class); when(properties.getHost()).thenReturn("foo"); when(properties.getPort()).thenReturn(42); assertThrows(LDAPException.class, () -> { new SSLLdapConnectionFactory(properties).buildLdapConnection(); }); } }