add iam crd

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-04-05 03:52:12 +08:00
parent 3c73471f79
commit 0e814bb5e4
879 changed files with 5869 additions and 139213 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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
}
}

View File

@@ -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)
}