-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #77 from doncicuto/feat-54
Feat 54
- Loading branch information
Showing
7 changed files
with
363 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package ldap | ||
|
||
import ( | ||
"net" | ||
"testing" | ||
"time" | ||
|
||
ldapClient "github.com/go-ldap/ldap" | ||
"github.com/google/uuid" | ||
) | ||
|
||
func TestBindOperation(t *testing.T) { | ||
dbPath := uuid.New() | ||
l, settings := testSetup(t, dbPath.String(), false, "127.0.0.1:60000") | ||
defer testCleanUp(dbPath.String()) | ||
|
||
// Launch testing servers | ||
go func() { | ||
for { | ||
// Accept new connections | ||
c, err := l.Accept() | ||
if err != nil { | ||
return | ||
} | ||
// Handle our server connection | ||
go handleConnection(c, settings) | ||
} | ||
}() | ||
|
||
waitForTestServer(t, "127.0.0.1:60000") | ||
|
||
// Create an Ldap connection | ||
c, err := net.Dial("tcp", "127.0.0.1:60000") | ||
if err != nil { | ||
t.Fatalf("error connecting to localhost tcp: %v", err) | ||
} | ||
conn := ldapClient.NewConn(c, false) | ||
conn.SetTimeout(3000 * time.Millisecond) | ||
conn.Start() | ||
defer conn.Close() | ||
|
||
// Test cases | ||
testCases := []BindTestCase{ | ||
{ | ||
name: "Bind successful", | ||
username: "uid=saul,ou=Users,dc=example,dc=org", | ||
password: "test", | ||
conn: conn, | ||
}, | ||
{ | ||
name: "Wrong password", | ||
username: "uid=saul,ou=Users,dc=example,dc=org", | ||
password: "test1", | ||
conn: conn, | ||
errorMessage: `LDAP Result Code 49 "Invalid Credentials": `, | ||
}, | ||
{ | ||
name: "Wrong user", | ||
username: "uid=test,ou=Users,dc=example,dc=org", | ||
password: "test1", | ||
conn: conn, | ||
errorMessage: `LDAP Result Code 50 "Insufficient Access Rights": `, | ||
}, | ||
{ | ||
name: "Empty password not allowed", | ||
username: "uid=saul,ou=Users,dc=example,dc=org", | ||
password: "", | ||
conn: conn, | ||
errorMessage: `LDAP Result Code 206 "Empty password not allowed by the client": ldap: empty password not allowed by the client`, | ||
}, | ||
{ | ||
name: "Wrong domain", | ||
username: "uid=saul,ou=Users,dc=example,dc=com", | ||
password: "test1", | ||
conn: conn, | ||
errorMessage: `LDAP Result Code 49 "Invalid Credentials": `, | ||
}, | ||
{ | ||
name: "Anonymous bind not allowed", | ||
username: "", | ||
password: "", | ||
conn: conn, | ||
errorMessage: `LDAP Result Code 206 "Empty password not allowed by the client": ldap: empty password not allowed by the client`, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
runBindTests(t, tc) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
package ldap | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"os" | ||
"strings" | ||
"testing" | ||
"time" | ||
|
||
"github.com/antelman107/net-wait-go/wait" | ||
"github.com/doncicuto/glim/models" | ||
"github.com/doncicuto/glim/server/db" | ||
"github.com/doncicuto/glim/types" | ||
ldapClient "github.com/go-ldap/ldap" | ||
"github.com/stretchr/testify/assert" | ||
"gorm.io/gorm" | ||
) | ||
|
||
func addMembers(db *gorm.DB, group *models.Group, members string) error { | ||
for _, member := range strings.Split(members, ",") { | ||
user := new(models.User) | ||
err := db.Model(&models.User{}).Where("username = ?", member).Take(&user).Error | ||
if err == nil { | ||
// Append association | ||
err = db.Model(&group).Association("Members").Append(user) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func addGroup(db *gorm.DB, name string, description string, members string) error { | ||
g := models.Group{} | ||
g.Name = &name | ||
g.Description = &description | ||
err := db.Create(&g).Error | ||
if err != nil { | ||
return err | ||
} | ||
addMembers(db, &g, members) | ||
return nil | ||
} | ||
|
||
func newTestDatabase(dbPath string) (*gorm.DB, error) { | ||
var dbInit = types.DBInit{ | ||
AdminPasswd: "test", | ||
SearchPasswd: "test", | ||
Users: "saul,kim,mike", | ||
DefaultPasswd: "test", | ||
UseSqlite: true, | ||
} | ||
sqlLog := false | ||
newDb, err := db.Initialize(fmt.Sprintf("/tmp/%s.db", dbPath), sqlLog, dbInit) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Create group test | ||
err = addGroup(newDb, "test", "Test", "saul,kim") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Create group test2 | ||
err = addGroup(newDb, "test2", "Test2", "kim") | ||
if err != nil { | ||
return nil, err | ||
} | ||
return newDb, nil | ||
} | ||
|
||
func testSettings(db *gorm.DB, addr string) types.LDAPSettings { | ||
return types.LDAPSettings{ | ||
DB: db, | ||
TLSDisabled: true, | ||
Address: addr, | ||
Domain: "dc=example,dc=org", | ||
} | ||
} | ||
|
||
func testSetup(t *testing.T, dbPath string, guacamole bool, addr string) (net.Listener, types.LDAPSettings) { | ||
// New SQLite test database | ||
db, err := newTestDatabase(dbPath) | ||
if err != nil { | ||
t.Fatalf("could not initialize db - %v", err) | ||
} | ||
|
||
settings := testSettings(db, addr) | ||
settings.Guacamole = guacamole | ||
|
||
var l net.Listener | ||
l, err = net.Listen("tcp", addr) | ||
if err != nil { | ||
t.Fatalf("could not initialize socket - %v", err) | ||
} | ||
return l, settings | ||
} | ||
|
||
func testCleanUp(dbPath string) { | ||
removeDatabase(dbPath) | ||
} | ||
|
||
func removeDatabase(dbPath string) { | ||
os.Remove(fmt.Sprintf("/tmp/%s.db", dbPath)) | ||
} | ||
|
||
type BindTestCase struct { | ||
conn *ldapClient.Conn | ||
name string | ||
username string | ||
password string | ||
errorMessage string | ||
} | ||
|
||
type SearchTestCase struct { | ||
conn *ldapClient.Conn | ||
name string | ||
baseDN string | ||
scope int | ||
sizeLimit int | ||
timeLimit int | ||
filter string | ||
attributes []string | ||
controls []ldapClient.Control | ||
numEntries int | ||
errorMessage string | ||
} | ||
|
||
func waitForTestServer(t *testing.T, address string) { | ||
if !wait.New( | ||
wait.WithProto("tcp"), | ||
wait.WithWait(200*time.Millisecond), | ||
wait.WithBreak(50*time.Millisecond), | ||
wait.WithDeadline(5*time.Second), | ||
wait.WithDebug(true), | ||
).Do([]string{address}) { | ||
t.Fatal("test server is not available") | ||
return | ||
} | ||
} | ||
|
||
func runBindTests(t *testing.T, tc BindTestCase) { | ||
t.Run(tc.name, func(t *testing.T) { | ||
err := tc.conn.Bind(tc.username, tc.password) | ||
if err != nil { | ||
assert.Equal(t, tc.errorMessage, fmt.Sprintf("%v", err.Error())) | ||
} else { | ||
if tc.errorMessage != "" { | ||
t.Fatal(fmt.Errorf("error was expected")) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
func runSearchTests(t *testing.T, tc SearchTestCase) { | ||
t.Run(tc.name, func(t *testing.T) { | ||
searchRequest := ldapClient.NewSearchRequest(tc.baseDN, tc.scope, ldapClient.DerefAlways, tc.sizeLimit, tc.timeLimit, false, tc.filter, tc.attributes, tc.controls) | ||
sr, err := tc.conn.Search(searchRequest) | ||
if err != nil { | ||
assert.Equal(t, tc.errorMessage, fmt.Sprintf("%v", err.Error())) | ||
} else { | ||
if tc.errorMessage != "" { | ||
t.Fatal(fmt.Errorf("error was expected")) | ||
} else { | ||
assert.Equal(t, tc.numEntries, len(sr.Entries)) | ||
} | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package ldap | ||
|
||
import ( | ||
"net" | ||
"testing" | ||
"time" | ||
|
||
ldapClient "github.com/go-ldap/ldap" | ||
"github.com/google/uuid" | ||
) | ||
|
||
func TestSearchOperation(t *testing.T) { | ||
dbPath := uuid.New() | ||
l, settings := testSetup(t, dbPath.String(), false, "127.0.0.1:60001") | ||
defer testCleanUp(dbPath.String()) | ||
|
||
// Launch testing servers | ||
go func() { | ||
for { | ||
// Accept new connections | ||
c, err := l.Accept() | ||
if err != nil { | ||
return | ||
} | ||
// Handle our server connection | ||
go handleConnection(c, settings) | ||
} | ||
}() | ||
|
||
waitForTestServer(t, "127.0.0.1:60001") | ||
|
||
// Create an Ldap connection | ||
c, err := net.Dial("tcp", "127.0.0.1:60001") | ||
if err != nil { | ||
t.Fatalf("error connecting to localhost tcp: %v", err) | ||
} | ||
conn := ldapClient.NewConn(c, false) | ||
conn.SetTimeout(3000 * time.Millisecond) | ||
conn.Start() | ||
defer conn.Close() | ||
|
||
// Bind | ||
err = conn.Bind("cn=admin,dc=example,dc=org", "test") | ||
if err != nil { | ||
t.Fatalf("error in bind operation: %v", err) | ||
} | ||
|
||
// Test cases | ||
testCases := []SearchTestCase{ | ||
{ | ||
name: "Search users successful", | ||
conn: conn, | ||
baseDN: "ou=Users,dc=example,dc=org", | ||
scope: ldapClient.ScopeWholeSubtree, | ||
filter: "(objectclass=*)", | ||
attributes: []string{}, | ||
controls: nil, | ||
numEntries: 4, | ||
}, | ||
{ | ||
name: "Search groups successful", | ||
conn: conn, | ||
baseDN: "ou=Groups,dc=example,dc=org", | ||
scope: ldapClient.ScopeWholeSubtree, | ||
filter: "(objectclass=*)", | ||
attributes: []string{}, | ||
controls: nil, | ||
numEntries: 3, | ||
}, | ||
{ | ||
name: "Wrong base", | ||
conn: conn, | ||
baseDN: "ou=Users,dc=example,dc=com", | ||
scope: ldapClient.ScopeWholeSubtree, | ||
filter: "(objectclass=*)", | ||
attributes: []string{}, | ||
controls: nil, | ||
numEntries: 0, | ||
errorMessage: `LDAP Result Code 32 "No Such Object": `, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
runSearchTests(t, tc) | ||
} | ||
} |
Oops, something went wrong.