blob: 085582646df184d30443117e6f70456714ff94e1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.kalumet.console.utils;
import org.apache.kalumet.console.configuration.ConfigurationManager;
import org.apache.kalumet.model.Kalumet;
import org.apache.kalumet.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import java.util.Hashtable;
/**
* LDAP utility class.
*/
public class LdapUtils
{
private final static transient Logger LOGGER = LoggerFactory.getLogger( LdapUtils.class );
/**
* Try to bind a user id and password in a given LDAP directory.
*
* @param user the user to bind.
* @param password the password to bind.
* @return true if the user is identified.
*/
public static boolean bind( String user, String password )
throws Exception
{
LOGGER.debug( "Try to bind the user {}", user );
// load Kalumet store
Kalumet kalumet;
kalumet = ConfigurationManager.loadStore();
if ( kalumet.getProperty( "LdapAuthentication" ) == null || kalumet.getProperty( "LdapServer" ) == null
|| kalumet.getProperty( "LdapBaseDN" ) == null || kalumet.getProperty( "LdapUidAttribute" ) == null
|| kalumet.getProperty( "LdapMailAttribute" ) == null || kalumet.getProperty( "LdapCnAttribute" ) == null )
{
LOGGER.error(
"All LDAP required properties are not present in Apache Kalumet configuration. Check if the properties LdapAuthentication, LdapServer, LdapBaseDN, LdapUidAttribute, LdapMailAttribute, LdapCnAttribute are presents in Apache Kalumet configuration." );
throw new IllegalStateException(
"All LDAP required properties are not present in Apache Kalumet configuration. Check if the properties LdapAuthentication, LdapServer, LdapBaseDN, LdapUidAttribute, LdapMailAttribute, LdapCnAttribute are presents in Apache Kalumet configuration." );
}
if ( kalumet.getProperty( "LdapAuthentication" ).getValue().equals( "false" ) )
{
LOGGER.error(
"The LDAP authentication is not active in Apache Kalumet configuration. Can't bind on LDAP." );
throw new IllegalStateException(
"The LDAP authentication is not active in Apache Kalumet. Can't bind on LDAP." );
}
// step 1 : connect to the LDAP server (anonymous) to get the user DN
LOGGER.debug( "LDAP Authentification Backend Step 1: grab the user DN" );
LOGGER.debug( "Create the LDAP initial context" );
Hashtable env = new Hashtable();
// TODO use a generic LDAP Context Factory compliant with IBM JDK
env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
LOGGER.debug( "Connect to the LDAP server ldap://{}", kalumet.getProperty( "LdapServer" ).getValue() );
env.put( Context.PROVIDER_URL, "ldap://" + kalumet.getProperty( "LdapServer" ).getValue() );
String userDN;
String userName;
String userEmail;
try
{
LOGGER.debug( "Init the JNDI LDAP Dir context ..." );
DirContext context = new InitialDirContext( env );
LOGGER.debug( "Define the subtree scope search control. " );
SearchControls controls = new SearchControls();
controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
LOGGER.debug( "Looking for the user in LDAP ..." );
LOGGER.debug( " Base DN: {}", kalumet.getProperty( "LdapBaseDN" ).getValue() );
LOGGER.debug( " Filter: ({}={})", kalumet.getProperty( "LdapUidAttribute" ).getValue(), user );
NamingEnumeration namingEnumeration = context.search( kalumet.getProperty( "LdapBaseDN" ).getValue(),
"(" + kalumet.getProperty(
"LdapUidAttribute" ).getValue() + "=" + user
+ ")", controls );
if ( !namingEnumeration.hasMore() )
{
LOGGER.warn( "User {} not found in LDAP", user );
return false;
}
LOGGER.debug( "Get the user object" );
SearchResult result = (SearchResult) namingEnumeration.next();
LOGGER.debug( "Get the attributes set" );
Attributes attributes = result.getAttributes();
LOGGER.debug( "Trying to get the DN attribute" );
userDN = (String) result.getName();
LOGGER.debug( "Get the LDAP user DN: {}", userDN );
userName = (String) attributes.get( kalumet.getProperty( "LdapCnAttribute" ).getValue() ).get();
LOGGER.debug( "Get the LDAP user name: {}", userName );
userEmail = (String) attributes.get( kalumet.getProperty( "LdapMailAttribute" ).getValue() ).get();
LOGGER.debug( "Get the LDAP user e-mail: {}", userEmail );
context.close();
}
catch ( Exception e )
{
LOGGER.error( "Can't connect to the LDAP server", e );
throw new IllegalStateException( "Can't connect to the LDAP server", e );
}
// step 2 : I have the DN, try to bind the user
LOGGER.debug( "LDAP Authentification Backend Step 2: bind the user with the DN/password" );
env = new Hashtable();
env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
LOGGER.debug( "Connect to the LDAP server ldap://{}", kalumet.getProperty( "LdapServer" ).getValue() );
env.put( Context.PROVIDER_URL, "ldap://" + kalumet.getProperty( "LdapServer" ).getValue() );
LOGGER.debug( "Define a simple authentication" );
env.put( Context.SECURITY_AUTHENTICATION, "simple" );
LOGGER.debug( "Define the security principal to {},{}", userDN,
kalumet.getProperty( "LdapBaseDN" ).getValue() );
env.put( Context.SECURITY_PRINCIPAL, userDN + "," + kalumet.getProperty( "LdapBaseDN" ).getValue() );
env.put( Context.SECURITY_CREDENTIALS, password );
LOGGER.debug( "Init the JNDI context ..." );
try
{
LOGGER.debug( "Directory context init" );
DirContext context = new InitialDirContext( env );
LOGGER.debug( "LDAP user bind successful" );
context.close();
if ( kalumet.getSecurity().getUser( user ) == null )
{
User securityUser = new User();
securityUser.setId( user );
securityUser.setName( userName );
securityUser.setEmail( userEmail );
kalumet.getSecurity().addUser( securityUser );
try
{
ConfigurationManager.writeStore( kalumet );
}
catch ( Exception e )
{
LOGGER.error( "Can't write the LDAP user in Apache Kalumet configuration store", e );
}
}
}
catch ( Exception e )
{
LOGGER.error( "User authentication failure using LDAP server", e );
return false;
}
return true;
}
}