diff --git a/go.mod b/go.mod index 1930c6f..a97d814 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/netresearch/simple-ldap-go v0.0.0-20230628081923-f17d668afd54 // indirect github.com/philhofer/fwd v1.1.2 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect diff --git a/go.sum b/go.sum index 3bc2ed1..ffaa9c9 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,8 @@ github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp9 github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/netresearch/simple-ldap-go v0.0.0-20230628081923-f17d668afd54 h1:mOw2DDPlmutvBDeGptyu4fp76nP4ctGIrqz/dp2/gls= +github.com/netresearch/simple-ldap-go v0.0.0-20230628081923-f17d668afd54/go.mod h1:l2QlOx+RzW/lx/3OfCJX3JE1leMKN0YQLtz1n2sngSM= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= diff --git a/internal/server/auth_middleware.go b/internal/server/auth_middleware.go index 3e84eae..ded46e3 100644 --- a/internal/server/auth_middleware.go +++ b/internal/server/auth_middleware.go @@ -3,10 +3,10 @@ package server import ( "encoding/base64" "errors" - "raybeam/pkg/ldap" "strings" ldap2 "github.com/go-ldap/ldap/v3" + ldap "github.com/netresearch/simple-ldap-go" "github.com/gofiber/fiber/v2" ) diff --git a/internal/server/auth_middleware_test.go b/internal/server/auth_middleware_test.go index 4341773..a5c9563 100644 --- a/internal/server/auth_middleware_test.go +++ b/internal/server/auth_middleware_test.go @@ -6,9 +6,10 @@ import ( "fmt" "net/url" "os" - "raybeam/pkg/ldap" "strings" "testing" + + ldap "github.com/netresearch/simple-ldap-go" ) func TestBasicAuthWithNonBasicAuthHeader(t *testing.T) { diff --git a/internal/server/route_ssh_key.go b/internal/server/route_ssh_key.go index 7d206e8..cc80bbc 100644 --- a/internal/server/route_ssh_key.go +++ b/internal/server/route_ssh_key.go @@ -4,10 +4,10 @@ import ( "errors" "fmt" "raybeam/internal/models" - "raybeam/pkg/ldap" "strings" "github.com/gofiber/fiber/v2" + ldap "github.com/netresearch/simple-ldap-go" "go.etcd.io/bbolt" "golang.org/x/crypto/ssh" ) diff --git a/internal/server/service.go b/internal/server/service.go index 25e90b5..754cff8 100644 --- a/internal/server/service.go +++ b/internal/server/service.go @@ -1,10 +1,9 @@ package server import ( - "raybeam/pkg/ldap" - "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" + ldap "github.com/netresearch/simple-ldap-go" "go.etcd.io/bbolt" ) diff --git a/pkg/ldap/auth.go b/pkg/ldap/auth.go deleted file mode 100644 index 6563379..0000000 --- a/pkg/ldap/auth.go +++ /dev/null @@ -1,21 +0,0 @@ -package ldap - -func (l LDAP) CheckPasswordForSAMAccountName(sAMAccountName, password string) (*User, error) { - c, err := l.getConnection() - if err != nil { - return nil, err - } - defer c.Close() - - user, err := l.FindUserBySAMAccountName(sAMAccountName) - if err != nil { - return nil, err - } - - err = c.Bind(user.DN, password) - if err != nil { - return nil, err - } - - return user, nil -} diff --git a/pkg/ldap/auth_test.go b/pkg/ldap/auth_test.go deleted file mode 100644 index f2fd6d8..0000000 --- a/pkg/ldap/auth_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package ldap - -import ( - "errors" - "os" - "strings" - "testing" -) - -func TestAuthWithReaduser(t *testing.T) { - wantSAMAccountName := "testuser" - wantCN := "Test User" - - l, err := getWorkingLdap() - if err != nil { - t.Error(err) - return - } - - user, err := l.CheckPasswordForSAMAccountName(wantSAMAccountName, "testuser") - if err != nil { - t.Error(err) - return - } - - if strings.ToLower(user.CN) != strings.ToLower(wantCN) { - t.Errorf("expected CN %q, got %q", wantCN, user.CN) - } - - if strings.ToLower(user.SAMAccountName) != strings.ToLower(wantSAMAccountName) { - t.Errorf("expected CN %q, got %q", wantSAMAccountName, user.SAMAccountName) - } -} - -func TestAuthWithNonexistantUser(t *testing.T) { - l, err := getWorkingLdap() - if err != nil { - t.Error(err) - return - } - - _, err = l.CheckPasswordForSAMAccountName("invalidtestuser", "thisshouldfail") - if err != ErrUserNotFound { - t.Errorf("expected error %q, got %q", ErrUserNotFound, err) - } -} - -func TestAuthWithInvalidCredentials(t *testing.T) { - l, err := getWorkingLdap() - if err != nil { - t.Error(err) - return - } - - _, err = l.CheckPasswordForSAMAccountName("testuser", "thisshouldfail") - if err == nil { - t.Errorf("expected error, got %q", err) - } -} - -func getWorkingLdap() (LDAP, error) { - server, found := os.LookupEnv("LDAP_SERVER") - if !found { - return LDAP{}, errors.New("LDAP_SERVER not set") - } - - baseDN, found := os.LookupEnv("LDAP_BASE_DN") - if !found { - return LDAP{}, errors.New("LDAP_BASE_DN not set") - } - - readUser, found := os.LookupEnv("LDAP_READ_USER") - if !found { - return LDAP{}, errors.New("LDAP_READ_USER not set") - } - - readPassword, found := os.LookupEnv("LDAP_READ_PASSWORD") - if !found { - return LDAP{}, errors.New("LDAP_READ_PASSWORD not set") - } - - return New(server, baseDN, readUser, readPassword), nil -} diff --git a/pkg/ldap/client.go b/pkg/ldap/client.go deleted file mode 100644 index 77eb31e..0000000 --- a/pkg/ldap/client.go +++ /dev/null @@ -1,34 +0,0 @@ -package ldap - -import "github.com/go-ldap/ldap/v3" - -type LDAP struct { - server string - - baseDN string - - user string - password string -} - -func New(server, baseDN, user, password string) LDAP { - return LDAP{ - server, - baseDN, - user, - password, - } -} - -func (l LDAP) getConnection() (*ldap.Conn, error) { - c, err := ldap.DialURL(l.server) - if err != nil { - return nil, err - } - - if err = c.Bind(l.user, l.password); err != nil { - return nil, err - } - - return c, nil -} diff --git a/pkg/ldap/search.go b/pkg/ldap/search.go deleted file mode 100644 index e784b99..0000000 --- a/pkg/ldap/search.go +++ /dev/null @@ -1,59 +0,0 @@ -package ldap - -import ( - "errors" - "fmt" - - "github.com/go-ldap/ldap/v3" -) - -var ( - ErrUserNotFound = errors.New("user not found") - ErrSAMAccountNameDuplicated = errors.New("sAMAccountName is not unique") -) - -type User struct { - CN string - DN string - SAMAccountName string - Groups []string -} - -func (l LDAP) FindUserBySAMAccountName(sAMAccountName string) (user *User, err error) { - c, err := l.getConnection() - if err != nil { - return nil, err - } - defer c.Close() - - r, err := c.Search(&ldap.SearchRequest{ - BaseDN: l.baseDN, - Scope: ldap.ScopeWholeSubtree, - DerefAliases: ldap.NeverDerefAliases, - Filter: fmt.Sprintf("(sAMAccountName=%s)", sAMAccountName), - Attributes: []string{"memberOf", "cn", "sAMAccountName"}, - }) - if err != nil { - return nil, err - } - - if len(r.Entries) == 0 { - return nil, ErrUserNotFound - } - - if len(r.Entries) > 1 { - return nil, ErrSAMAccountNameDuplicated - } - - user = &User{ - CN: r.Entries[0].GetAttributeValue("cn"), - DN: r.Entries[0].DN, - SAMAccountName: r.Entries[0].GetAttributeValue("sAMAccountName"), - } - - for _, group := range r.Entries[0].GetAttributeValues("memberOf") { - user.Groups = append(user.Groups, group) - } - - return -}