@@ -1,20 +1,22 @@
|
||||
package ldap
|
||||
|
||||
import "kubesphere.io/kubesphere/pkg/api/iam"
|
||||
import (
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
)
|
||||
|
||||
// Interface defines CRUD behaviors of manipulating users
|
||||
type Interface interface {
|
||||
// Create create a new user in ldap
|
||||
Create(user *iam.User) error
|
||||
Create(user *iamv1alpha2.User) error
|
||||
|
||||
// Update updates a user information, return error if user not exists
|
||||
Update(user *iam.User) error
|
||||
Update(user *iamv1alpha2.User) error
|
||||
|
||||
// Delete deletes a user from ldap, return nil if user not exists
|
||||
Delete(name string) error
|
||||
|
||||
// Get gets a user by its username from ldap, return ErrUserNotExists if user not exists
|
||||
Get(name string) (*iam.User, error)
|
||||
Get(name string) (*iamv1alpha2.User, error)
|
||||
|
||||
// Authenticate checks if (name, password) is valid, return ErrInvalidCredentials if not
|
||||
Authenticate(name string, password string) error
|
||||
|
||||
@@ -21,7 +21,8 @@ import (
|
||||
"fmt"
|
||||
"github.com/go-ldap/ldap"
|
||||
"github.com/google/uuid"
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -181,7 +182,7 @@ func (l *ldapInterfaceImpl) filterForUsername(username string) string {
|
||||
return fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", username, username)
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) Get(name string) (*iam.User, error) {
|
||||
func (l *ldapInterfaceImpl) Get(name string) (*iamv1alpha2.User, error) {
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -215,20 +216,24 @@ func (l *ldapInterfaceImpl) Get(name string) (*iam.User, error) {
|
||||
|
||||
userEntry := searchResults.Entries[0]
|
||||
|
||||
user := &iam.User{
|
||||
Name: userEntry.GetAttributeValue(ldapAttributeUserID),
|
||||
Email: userEntry.GetAttributeValue(ldapAttributeMail),
|
||||
Lang: userEntry.GetAttributeValue(ldapAttributePreferredLanguage),
|
||||
Description: userEntry.GetAttributeValue(ldapAttributeDescription),
|
||||
user := &iamv1alpha2.User{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: userEntry.GetAttributeValue(ldapAttributeUserID),
|
||||
},
|
||||
Spec: iamv1alpha2.UserSpec{
|
||||
Email: userEntry.GetAttributeValue(ldapAttributeMail),
|
||||
Lang: userEntry.GetAttributeValue(ldapAttributePreferredLanguage),
|
||||
Description: userEntry.GetAttributeValue(ldapAttributeDescription),
|
||||
},
|
||||
}
|
||||
|
||||
createTimestamp, _ := time.Parse(ldapAttributeCreateTimestampLayout, userEntry.GetAttributeValue(ldapAttributeCreateTimestamp))
|
||||
user.CreateTime = createTimestamp
|
||||
user.ObjectMeta.CreationTimestamp.Time = createTimestamp
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) Create(user *iam.User) error {
|
||||
func (l *ldapInterfaceImpl) Create(user *iamv1alpha2.User) error {
|
||||
if _, err := l.Get(user.Name); err != nil {
|
||||
return ErrUserAlreadyExisted
|
||||
}
|
||||
@@ -266,19 +271,19 @@ func (l *ldapInterfaceImpl) Create(user *iam.User) error {
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeMail,
|
||||
Vals: []string{user.Email},
|
||||
Vals: []string{user.Spec.Email},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeUserPassword,
|
||||
Vals: []string{user.Password},
|
||||
Vals: []string{user.Spec.EncryptedPassword},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributePreferredLanguage,
|
||||
Vals: []string{user.Lang},
|
||||
Vals: []string{user.Spec.Lang},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeDescription,
|
||||
Vals: []string{user.Description},
|
||||
Vals: []string{user.Spec.Description},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -314,7 +319,7 @@ func (l *ldapInterfaceImpl) Delete(name string) error {
|
||||
return conn.Del(deleteRequest)
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) Update(newUser *iam.User) error {
|
||||
func (l *ldapInterfaceImpl) Update(newUser *iamv1alpha2.User) error {
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -331,16 +336,16 @@ func (l *ldapInterfaceImpl) Update(newUser *iam.User) error {
|
||||
DN: l.dnForUsername(newUser.Name),
|
||||
}
|
||||
|
||||
if newUser.Description != "" {
|
||||
modifyRequest.Replace(ldapAttributeDescription, []string{newUser.Description})
|
||||
if newUser.Spec.Description != "" {
|
||||
modifyRequest.Replace(ldapAttributeDescription, []string{newUser.Spec.Description})
|
||||
}
|
||||
|
||||
if newUser.Lang != "" {
|
||||
modifyRequest.Replace(ldapAttributePreferredLanguage, []string{newUser.Lang})
|
||||
if newUser.Spec.Lang != "" {
|
||||
modifyRequest.Replace(ldapAttributePreferredLanguage, []string{newUser.Spec.Lang})
|
||||
}
|
||||
|
||||
if newUser.Password != "" {
|
||||
modifyRequest.Replace(ldapAttributeUserPassword, []string{newUser.Password})
|
||||
if newUser.Spec.EncryptedPassword != "" {
|
||||
modifyRequest.Replace(ldapAttributeUserPassword, []string{newUser.Spec.EncryptedPassword})
|
||||
}
|
||||
|
||||
return conn.Modify(modifyRequest)
|
||||
|
||||
@@ -1,40 +1,43 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
"time"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
)
|
||||
|
||||
// simpleLdap is a implementation of ldap.Interface, you should never use this in production env!
|
||||
type simpleLdap struct {
|
||||
store map[string]*iam.User
|
||||
store map[string]*iamv1alpha2.User
|
||||
}
|
||||
|
||||
func NewSimpleLdap() Interface {
|
||||
sl := &simpleLdap{
|
||||
store: map[string]*iam.User{},
|
||||
store: map[string]*iamv1alpha2.User{},
|
||||
}
|
||||
|
||||
// initialize with a admin user
|
||||
admin := &iam.User{
|
||||
Name: "admin",
|
||||
Email: "admin@kubesphere.io",
|
||||
Lang: "eng",
|
||||
Description: "administrator",
|
||||
CreateTime: time.Now(),
|
||||
Groups: nil,
|
||||
Password: "P@88w0rd",
|
||||
admin := &iamv1alpha2.User{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "admin",
|
||||
},
|
||||
Spec: iamv1alpha2.UserSpec{
|
||||
Email: "admin@kubesphere.io",
|
||||
Lang: "eng",
|
||||
Description: "administrator",
|
||||
Groups: nil,
|
||||
EncryptedPassword: "P@88w0rd",
|
||||
},
|
||||
}
|
||||
sl.store[admin.Name] = admin
|
||||
return sl
|
||||
}
|
||||
|
||||
func (s simpleLdap) Create(user *iam.User) error {
|
||||
func (s simpleLdap) Create(user *iamv1alpha2.User) error {
|
||||
s.store[user.Name] = user
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s simpleLdap) Update(user *iam.User) error {
|
||||
func (s simpleLdap) Update(user *iamv1alpha2.User) error {
|
||||
_, err := s.Get(user.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -52,7 +55,7 @@ func (s simpleLdap) Delete(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s simpleLdap) Get(name string) (*iam.User, error) {
|
||||
func (s simpleLdap) Get(name string) (*iamv1alpha2.User, error) {
|
||||
if user, ok := s.store[name]; !ok {
|
||||
return nil, ErrUserNotExists
|
||||
} else {
|
||||
@@ -64,7 +67,7 @@ func (s simpleLdap) Authenticate(name string, password string) error {
|
||||
if user, err := s.Get(name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if user.Password != password {
|
||||
if user.Spec.EncryptedPassword != password {
|
||||
return ErrInvalidCredentials
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,22 +2,26 @@ package ldap
|
||||
|
||||
import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSimpleLdap(t *testing.T) {
|
||||
ldapClient := NewSimpleLdap()
|
||||
|
||||
foo := &iam.User{
|
||||
Name: "jerry",
|
||||
Email: "jerry@kubesphere.io",
|
||||
Lang: "en",
|
||||
Description: "Jerry is kind and gentle.",
|
||||
CreateTime: time.Now(),
|
||||
Groups: []string{},
|
||||
Password: "P@88w0rd",
|
||||
foo := &iamv1alpha2.User{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: iamv1alpha2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "jerry",
|
||||
},
|
||||
Spec: iamv1alpha2.UserSpec{
|
||||
Email: "jerry@kubesphere.io",
|
||||
Lang: "en",
|
||||
Description: "Jerry is kind and gentle.",
|
||||
Groups: []string{},
|
||||
EncryptedPassword: "P@88w0rd",
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("should create user", func(t *testing.T) {
|
||||
@@ -44,7 +48,7 @@ func TestSimpleLdap(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foo.Description = "Jerry needs some drinks."
|
||||
foo.Spec.Description = "Jerry needs some drinks."
|
||||
err = ldapClient.Update(foo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -85,7 +89,7 @@ func TestSimpleLdap(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ldapClient.Authenticate(foo.Name, foo.Password)
|
||||
err = ldapClient.Authenticate(foo.Name, foo.Spec.EncryptedPassword)
|
||||
if err != nil {
|
||||
t.Fatalf("should pass but got an error %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user