mirror of
https://github.com/h44z/wg-portal.git
synced 2025-09-15 07:11:15 +00:00
V2 alpha - initial version (#172)
Initial alpha codebase for version 2 of WireGuard Portal. This version is considered unstable and incomplete (for example, no public REST API)! Use with care! Fixes/Implements the following issues: - OAuth support #154, #1 - New Web UI with internationalisation support #98, #107, #89, #62 - Postgres Support #49 - Improved Email handling #47, #119 - DNS Search Domain support #46 - Bugfixes #94, #48 --------- Co-authored-by: Fabian Wechselberger <wechselbergerf@hotmail.com>
This commit is contained in:
138
internal/ldap_utils.go
Normal file
138
internal/ldap_utils.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/h44z/wg-portal/internal/config"
|
||||
)
|
||||
|
||||
type RawLdapUser map[string]any
|
||||
|
||||
func LdapFindAllUsers(conn *ldap.Conn, baseDn, filter string, fields *config.LdapFields) ([]RawLdapUser, error) {
|
||||
// Search all users
|
||||
attrs := LdapSearchAttributes(fields)
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
baseDn,
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
filter, attrs, nil,
|
||||
)
|
||||
|
||||
sr, err := conn.Search(searchRequest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to search: %w", err)
|
||||
}
|
||||
|
||||
results := LdapConvertEntries(sr, fields)
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func LdapConnect(cfg *config.LdapProvider) (*ldap.Conn, error) {
|
||||
tlsConfig := &tls.Config{InsecureSkipVerify: !cfg.CertValidation}
|
||||
if cfg.TlsCertificatePath != "" {
|
||||
certificate, err := os.ReadFile(cfg.TlsCertificatePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load TLS certificate: %w", err)
|
||||
|
||||
}
|
||||
|
||||
key, err := os.ReadFile(cfg.TlsKeyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load TLS key: %w", err)
|
||||
}
|
||||
|
||||
keyPair, err := tls.X509KeyPair(certificate, key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate X509 keypair: %w", err)
|
||||
|
||||
}
|
||||
tlsConfig = &tls.Config{Certificates: []tls.Certificate{keyPair}}
|
||||
}
|
||||
|
||||
conn, err := ldap.DialURL(cfg.URL, ldap.DialWithTLSConfig(tlsConfig))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dial error: %w", err)
|
||||
}
|
||||
|
||||
if cfg.StartTLS { // Reconnect with TLS
|
||||
if err = conn.StartTLS(tlsConfig); err != nil {
|
||||
return nil, fmt.Errorf("failed to start TLS on connection: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = conn.Bind(cfg.BindUser, cfg.BindPass); err != nil {
|
||||
return nil, fmt.Errorf("failed to bind to LDAP: %w", err)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func LdapDisconnect(conn *ldap.Conn) {
|
||||
if conn != nil {
|
||||
if err := conn.Close(); err != nil {
|
||||
logrus.Errorf("failed to close ldap connection: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func LdapConvertEntries(sr *ldap.SearchResult, fields *config.LdapFields) []RawLdapUser {
|
||||
users := make([]RawLdapUser, len(sr.Entries))
|
||||
|
||||
for i, entry := range sr.Entries {
|
||||
userData := make(RawLdapUser)
|
||||
userData[fields.UserIdentifier] = entry.DN
|
||||
userData[fields.Email] = entry.GetAttributeValue(fields.Email)
|
||||
userData[fields.Firstname] = entry.GetAttributeValue(fields.Firstname)
|
||||
userData[fields.Lastname] = entry.GetAttributeValue(fields.Lastname)
|
||||
userData[fields.Phone] = entry.GetAttributeValue(fields.Phone)
|
||||
userData[fields.Department] = entry.GetAttributeValue(fields.Department)
|
||||
userData[fields.GroupMembership] = entry.GetRawAttributeValues(fields.GroupMembership)
|
||||
|
||||
users[i] = userData
|
||||
}
|
||||
return users
|
||||
}
|
||||
|
||||
func LdapSearchAttributes(fields *config.LdapFields) []string {
|
||||
attrs := []string{"dn", fields.UserIdentifier}
|
||||
|
||||
if fields.Email != "" {
|
||||
attrs = append(attrs, fields.Email)
|
||||
}
|
||||
if fields.Firstname != "" {
|
||||
attrs = append(attrs, fields.Firstname)
|
||||
}
|
||||
if fields.Lastname != "" {
|
||||
attrs = append(attrs, fields.Lastname)
|
||||
}
|
||||
if fields.Phone != "" {
|
||||
attrs = append(attrs, fields.Phone)
|
||||
}
|
||||
if fields.Department != "" {
|
||||
attrs = append(attrs, fields.Department)
|
||||
}
|
||||
if fields.GroupMembership != "" {
|
||||
attrs = append(attrs, fields.GroupMembership)
|
||||
}
|
||||
|
||||
return UniqueStringSlice(attrs)
|
||||
}
|
||||
|
||||
// LdapIsMemberOf checks if the groupData array contains the group DN
|
||||
func LdapIsMemberOf(groupData [][]byte, groupDN *ldap.DN) (bool, error) {
|
||||
for _, group := range groupData {
|
||||
dn, err := ldap.ParseDN(string(group))
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to parse group DN: %w", err)
|
||||
}
|
||||
if groupDN.Equal(dn) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
Reference in New Issue
Block a user