ldapmdl.go 4.8 KiB
Newer Older
Rahul A. Sutar's avatar
Rahul A. Sutar committed
package ldapmdl

import (
	"crypto/tls"
	"errors"
	"strings"

Rahul A. Sutar's avatar
Rahul A. Sutar committed
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/configmdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
Akshay Bharambe's avatar
Akshay Bharambe committed
	ldap "github.com/go-ldap/ldap/v3"
Rahul A. Sutar's avatar
Rahul A. Sutar committed
Author : RahulS
Rahul A. Sutar's avatar
Rahul A. Sutar committed
LDAP authentication module - Authenticates the user with given LDAP server
Requires 	: loginID (string), password (string)
Rahul A. Sutar's avatar
Rahul A. Sutar committed
Returns		: 0 - If any error occurs, error - respective error object. Will occur if in following conditions
					a. Blank loginID
					b. Blank password
					c. Error connecting to LDAP server
					d. Error reconnecting to LDAP using TSL
					e. Error binding admin username and password with LDAP
					f. Error searhin user on LDAP server
Rahul A. Sutar's avatar
Rahul A. Sutar committed
			  1 - If user does not exist on LDAP server, error - nil
			  2 - If multiple entries found against loginID, error - nil
			  3 - If user enters wrong password, error - nil
			  4 - Successful authentication, error - nil
*/

Rahul A. Sutar's avatar
Rahul A. Sutar committed
//LDAPConfig to get read and store LDAP server configuration
type LDAPConfig struct {
	BaseDN               string
	LDAPServerIPWithPort string
	FilterDN             string
	LDAPUsername         string
	LDAPPassword         string
}

var ldapConfig LDAPConfig

//InitLDAP get LDAP server configuration
func InitLDAP(configFilePath string) error {
	_, configError := configmdl.InitConfig(configFilePath, &ldapConfig)
	if errormdl.CheckErr(configError) != nil {
		return configError
	}
	return nil
}

Rahul A. Sutar's avatar
Rahul A. Sutar committed
//AuthenticateOnLDAP authenticates user with LDAP server
func AuthenticateOnLDAP(loginID, password string) (int, error) {

	if strings.TrimSpace(loginID) == "" {

Rahul A. Sutar's avatar
Rahul A. Sutar committed
		loggermdl.LogError("ldapmdl : loginID required")
		return 0, errors.New("ldapmdl : loginID required")
Rahul A. Sutar's avatar
Rahul A. Sutar committed

	} else if strings.TrimSpace(password) == "" {

Rahul A. Sutar's avatar
Rahul A. Sutar committed
		loggermdl.LogError("ldapmdl : password required")
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		return 0, errors.New("ldapmdl : password required")

	}

Rahul A. Sutar's avatar
Rahul A. Sutar committed
	//Check if LDAP configuration is properly set through config file. (Call InitLDAP() to set configuration)
	ldapInitConfigError := CheckLDAPConfig()
	if ldapInitConfigError != nil {
		return 0, ldapInitConfigError
	}
Rahul A. Sutar's avatar
Rahul A. Sutar committed

	//Create connection to LDAP server
Rahul A. Sutar's avatar
Rahul A. Sutar committed
	ldapConnection, ldapConnectionError := ldap.Dial("tcp", ldapConfig.LDAPServerIPWithPort)
	if errormdl.CheckErr(ldapConnectionError) != nil {
		loggermdl.LogError("ldapmdl connectionError : ", ldapConnectionError)
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		return 0, ldapConnectionError
	}

	defer ldapConnection.Close()

	//Reconnect with TLS(Transport Layer Security Protocol)
	startTLSError := ldapConnection.StartTLS(&tls.Config{InsecureSkipVerify: true})
Rahul A. Sutar's avatar
Rahul A. Sutar committed
	if errormdl.CheckErr1(startTLSError) != nil {
		loggermdl.LogError("ldapmdl startTLSError : ", startTLSError)
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		return 0, startTLSError
	}

	//Bind with administrator user who has credentials to operation like 'search'
Rahul A. Sutar's avatar
Rahul A. Sutar committed
	ldapBindError := ldapConnection.Bind(ldapConfig.LDAPUsername, ldapConfig.LDAPPassword)
	if errormdl.CheckErr2(ldapBindError) != nil {
		loggermdl.LogInfo("ldapmdl ldapBindError: ", ldapBindError)
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		return 0, ldapBindError
	}

	//Search for required username which is to be authenticated
	result, searchError := ldapConnection.Search(ldap.NewSearchRequest(
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		ldapConfig.BaseDN,
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		ldap.ScopeWholeSubtree,
		ldap.NeverDerefAliases,
		0,
		0,
		false,
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		filter(loginID, ldapConfig.FilterDN),
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		[]string{"dn"},
		nil,
	))

	//Hand search error
Rahul A. Sutar's avatar
Rahul A. Sutar committed
	if errormdl.CheckErr3(searchError) != nil {
		loggermdl.LogError("ldapmdl searchError : ", searchError)
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		return 0, searchError
	}

	//Return 1 if user does not exist on LDAP server
	if len(result.Entries) < 1 {
		return 1, nil
	}

	//Return 2 if multiple entries found against one userId
Rahul A. Sutar's avatar
Rahul A. Sutar committed
	if errormdl.CheckBool(len(result.Entries) > 1) {
Rahul A. Sutar's avatar
Rahul A. Sutar committed
		return 2, nil
	}

	//Bind the password with given userId if errors occurs while binding, user has entered wrong password
	if userCredentialsBindError := ldapConnection.Bind(result.Entries[0].DN, password); userCredentialsBindError != nil {
		return 3, nil
	}

	//return 4 if authentication is successful
Rahul A. Sutar's avatar
Rahul A. Sutar committed
	loggermdl.LogDebug("ldapmdl : Authentication successful")
Rahul A. Sutar's avatar
Rahul A. Sutar committed
	return 4, nil
}

func filter(needle string, filterDN string) string {
	res := strings.Replace(filterDN, "{username}", needle, -1)
	return res
}
Rahul A. Sutar's avatar
Rahul A. Sutar committed

//CheckLDAPConfig checks of LDAP configuration is initialized or not
func CheckLDAPConfig() error {

	if strings.TrimSpace(ldapConfig.BaseDN) == "" {
		return errors.New("LDAP baseDN not found")
	} else if strings.TrimSpace(ldapConfig.FilterDN) == "" {
		return errors.New("LDAP filterDN not found")
	} else if strings.TrimSpace(ldapConfig.LDAPPassword) == "" {
		return errors.New("LDAP password not found")
	} else if strings.TrimSpace(ldapConfig.LDAPServerIPWithPort) == "" {
		return errors.New("LDAP IPAddress not found IPAdress should be with port")
	} else if strings.TrimSpace(ldapConfig.LDAPUsername) == "" {
		return errors.New("LDAP username not found")
	}
	return nil
}