more work on ldap integration
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-01-04 20:45:34 +11:00
parent 44b92a8b08
commit ffa8778d2b
2 changed files with 96 additions and 14 deletions

View File

@@ -147,12 +147,10 @@ func main() {
models.ReceiveKey(keyString) models.ReceiveKey(keyString)
} }
// Load certificate for LDAP connectivy // If LDAP configuration is defined, prepare connection
models.LoadLdapCert()
ldapServer := os.Getenv("LDAP_BIND_ADDRESS") ldapServer := os.Getenv("LDAP_BIND_ADDRESS")
if ldapServer != "" { if ldapServer != "" {
models.LdapEnabled = true models.LdapSetup()
} }
// Create context that listens for the interrupt signal from the OS. // Create context that listens for the interrupt signal from the OS.

View File

@@ -22,8 +22,10 @@ type LdapConfig struct {
} }
var systemCA *x509.CertPool var systemCA *x509.CertPool
var ldaps *ldap.Conn
var CertLoaded bool var CertLoaded bool
var LdapEnabled bool var LdapEnabled bool
var LdapBaseDn string
func GetFilePath(path string) string { func GetFilePath(path string) string {
// Check for empty filename // Check for empty filename
@@ -46,7 +48,7 @@ func GetFilePath(path string) string {
return path return path
} }
func LoadLdapCert() { func loadLdapCert() {
var err error var err error
// Get a copy of the system defined CA's // Get a copy of the system defined CA's
systemCA, err = x509.SystemCertPool() systemCA, err = x509.SystemCertPool()
@@ -85,9 +87,12 @@ func LoadLdapCert() {
} }
} }
func VerifyLdapCreds(username string, password string) bool { func LdapSetup() bool {
var ldaps *ldap.Conn
var err error var err error
// Load LDAP certificate if necessary
loadLdapCert()
ldapServer := os.Getenv("LDAP_BIND_ADDRESS") ldapServer := os.Getenv("LDAP_BIND_ADDRESS")
if ldapServer == "" { if ldapServer == "" {
log.Printf("VerifyLdapCreds no LDAP bind address supplied\n") log.Printf("VerifyLdapCreds no LDAP bind address supplied\n")
@@ -96,8 +101,8 @@ func VerifyLdapCreds(username string, password string) bool {
LdapEnabled = true LdapEnabled = true
} }
ldapBaseDn := os.Getenv("LDAP_BASE_DN") LdapBaseDn = os.Getenv("LDAP_BASE_DN")
if ldapBaseDn == "" { if LdapBaseDn == "" {
log.Printf("VerifyLdapCreds no LDAP base DN supplied\n") log.Printf("VerifyLdapCreds no LDAP base DN supplied\n")
return false return false
} }
@@ -123,10 +128,48 @@ func VerifyLdapCreds(username string, password string) bool {
defer ldaps.Close() defer ldaps.Close()
//ldaps.Debug = true LdapEnabled = true
// try to bind to AD LookupNamingContext()
log.Printf("Attempting LDAP bind with user '%s' and password '%s'\n", username, password)
return true
}
func LookupNamingContext() {
// Retrieve the defaultNamingContext
searchRequest := ldap.NewSearchRequest(
"",
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
"(objectClass=*)",
[]string{"defaultNamingContext"},
nil,
)
searchResult, err := ldaps.Search(searchRequest)
if err != nil {
log.Printf("LookupNamingContext unable to perform unauthenticated search : '%s'\n", err)
return
}
if len(searchResult.Entries) != 1 {
log.Printf("LookupNamingContext unable to retrieve defaultNamingContext\n")
return
}
defaultNamingContext := searchResult.Entries[0].GetAttributeValue("defaultNamingContext")
if defaultNamingContext == "" {
log.Printf("LookupNamingContext defaultNamingContext attribute not found\n")
return
}
log.Printf("Default Naming Context: '%s'\n", defaultNamingContext)
}
func VerifyLdapCreds(username string, password string) bool {
var err error
// try an authenticated bind to AD to verify credentials
log.Printf("Attempting LDAP bind with user '%s' and password length '%d'\n", username, len(password))
err = ldaps.Bind(username, password) err = ldaps.Bind(username, password)
if err != nil { if err != nil {
if ldapErr, ok := err.(*ldap.Error); ok && ldapErr.ResultCode == ldap.LDAPResultInvalidCredentials { if ldapErr, ok := err.(*ldap.Error); ok && ldapErr.ResultCode == ldap.LDAPResultInvalidCredentials {
@@ -140,9 +183,9 @@ func VerifyLdapCreds(username string, password string) bool {
log.Printf("VerifyLdapCreds successfully bound to LDAP\n") log.Printf("VerifyLdapCreds successfully bound to LDAP\n")
} }
log.Printf("Attempting LDAP search request from base DN '%s'\n", ldapBaseDn) log.Printf("Attempting LDAP search request from base DN '%s'\n", LdapBaseDn)
searchReq := ldap.NewSearchRequest( searchReq := ldap.NewSearchRequest(
ldapBaseDn, LdapBaseDn,
ldap.ScopeWholeSubtree, // you can also use ldap.ScopeWholeSubtree ldap.ScopeWholeSubtree, // you can also use ldap.ScopeWholeSubtree
ldap.NeverDerefAliases, ldap.NeverDerefAliases,
0, 0,
@@ -162,3 +205,44 @@ func VerifyLdapCreds(username string, password string) bool {
return true return true
} }
// GetGroupsOfUser returns the group for a user.
// Taken from https://github.com/jtblin/go-ldap-client/issues/13#issuecomment-456090979
func GetGroupsOfUser(username string, baseDN string, conn *ldap.Conn) ([]string, error) {
var samAccountName string
var groups []string
if strings.Contains(username, "@") {
s := strings.Split(username, "@")
samAccountName = s[0]
} else if strings.Contains(username, "\\") {
s := strings.Split(username, "\\")
samAccountName = s[len(s)-1]
} else {
samAccountName = username
}
// Get the users DN
// Search for the given username
searchRequest := ldap.NewSearchRequest(
baseDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(CN=%s)", ldap.EscapeFilter(samAccountName)),
[]string{},
nil,
)
sr, err := conn.Search(searchRequest)
if err != nil {
return nil, err
}
if len(sr.Entries) != 1 {
return nil, fmt.Errorf("user '%s' does not exist", samAccountName)
} else {
// Get the groups of the first result
groups = sr.Entries[0].GetAttributeValues("memberOf")
}
return groups, nil
}