@@ -23,6 +23,9 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
@@ -68,6 +71,21 @@ func preRegistrationUser(idp string, identity identityprovider.Identity) authuse
|
||||
}
|
||||
}
|
||||
|
||||
func mappedUser(idp string, identity identityprovider.Identity) *iamv1alpha2.User {
|
||||
// username convert
|
||||
username := strings.ToLower(identity.GetUsername())
|
||||
return &iamv1alpha2.User{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: username,
|
||||
Labels: map[string]string{
|
||||
iamv1alpha2.IdentifyProviderLabel: idp,
|
||||
iamv1alpha2.OriginUIDLabel: identity.GetUserID(),
|
||||
},
|
||||
},
|
||||
Spec: iamv1alpha2.UserSpec{Email: identity.GetEmail()},
|
||||
}
|
||||
}
|
||||
|
||||
// findUser returns the user associated with the username or email
|
||||
func (u *userGetter) findUser(username string) (*iamv1alpha2.User, error) {
|
||||
if _, err := mail.ParseAddress(username); err != nil {
|
||||
|
||||
@@ -22,6 +22,10 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -35,49 +39,60 @@ import (
|
||||
)
|
||||
|
||||
type oauthAuthenticator struct {
|
||||
*userGetter
|
||||
options *authentication.Options
|
||||
ksClient kubesphere.Interface
|
||||
userGetter *userGetter
|
||||
options *authentication.Options
|
||||
}
|
||||
|
||||
func NewOAuthAuthenticator(userLister iamv1alpha2listers.UserLister,
|
||||
func NewOAuthAuthenticator(ksClient kubesphere.Interface,
|
||||
userLister iamv1alpha2listers.UserLister,
|
||||
options *authentication.Options) OAuthAuthenticator {
|
||||
authenticator := &oauthAuthenticator{
|
||||
ksClient: ksClient,
|
||||
userGetter: &userGetter{userLister: userLister},
|
||||
options: options,
|
||||
}
|
||||
return authenticator
|
||||
}
|
||||
|
||||
func (o oauthAuthenticator) Authenticate(ctx context.Context, provider string, req *http.Request) (authuser.Info, string, error) {
|
||||
options, err := o.options.OAuthOptions.IdentityProviderOptions(provider)
|
||||
func (o *oauthAuthenticator) Authenticate(_ context.Context, provider string, req *http.Request) (authuser.Info, string, error) {
|
||||
providerOptions, err := o.options.OAuthOptions.IdentityProviderOptions(provider)
|
||||
// identity provider not registered
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, "", err
|
||||
}
|
||||
identityProvider, err := identityprovider.GetOAuthProvider(options.Name)
|
||||
oauthIdentityProvider, err := identityprovider.GetOAuthProvider(providerOptions.Name)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, "", err
|
||||
}
|
||||
identity, err := identityProvider.IdentityExchangeCallback(req)
|
||||
authenticated, err := oauthIdentityProvider.IdentityExchangeCallback(req)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
mappedUser, err := o.findMappedUser(options.Name, identity.GetUserID())
|
||||
if mappedUser == nil && options.MappingMethod == oauth.MappingMethodLookup {
|
||||
user, err := o.userGetter.findMappedUser(providerOptions.Name, authenticated.GetUserID())
|
||||
if user == nil && providerOptions.MappingMethod == oauth.MappingMethodLookup {
|
||||
klog.Error(err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// the user will automatically create and mapping when login successful.
|
||||
if mappedUser == nil && options.MappingMethod == oauth.MappingMethodAuto {
|
||||
return preRegistrationUser(options.Name, identity), options.Name, nil
|
||||
}
|
||||
if mappedUser != nil {
|
||||
return &authuser.DefaultInfo{Name: mappedUser.GetName()}, options.Name, nil
|
||||
if user == nil && providerOptions.MappingMethod == oauth.MappingMethodAuto {
|
||||
if !providerOptions.DisableLoginConfirmation {
|
||||
return preRegistrationUser(providerOptions.Name, authenticated), providerOptions.Name, nil
|
||||
}
|
||||
user, err = o.ksClient.IamV1alpha2().Users().Create(context.Background(), mappedUser(providerOptions.Name, authenticated), metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, "", errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularUser), identity.GetUsername())
|
||||
if user != nil {
|
||||
return &authuser.DefaultInfo{Name: user.GetName()}, providerOptions.Name, nil
|
||||
}
|
||||
|
||||
return nil, "", errors.NewNotFound(iamv1alpha2.Resource("user"), authenticated.GetUsername())
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ func Test_oauthAuthenticator_Authenticate(t *testing.T) {
|
||||
{
|
||||
name: "Should successfully",
|
||||
oauthAuthenticator: NewOAuthAuthenticator(
|
||||
nil,
|
||||
ksInformerFactory.Iam().V1alpha2().Users().Lister(),
|
||||
oauthOptions,
|
||||
),
|
||||
@@ -105,6 +106,7 @@ func Test_oauthAuthenticator_Authenticate(t *testing.T) {
|
||||
{
|
||||
name: "Should successfully",
|
||||
oauthAuthenticator: NewOAuthAuthenticator(
|
||||
nil,
|
||||
ksInformerFactory.Iam().V1alpha2().Users().Lister(),
|
||||
oauthOptions,
|
||||
),
|
||||
|
||||
@@ -21,6 +21,10 @@ package auth
|
||||
import (
|
||||
"context"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@@ -36,20 +40,23 @@ import (
|
||||
)
|
||||
|
||||
type passwordAuthenticator struct {
|
||||
ksClient kubesphere.Interface
|
||||
userGetter *userGetter
|
||||
authOptions *authentication.Options
|
||||
}
|
||||
|
||||
func NewPasswordAuthenticator(userLister iamv1alpha2listers.UserLister,
|
||||
func NewPasswordAuthenticator(ksClient kubesphere.Interface,
|
||||
userLister iamv1alpha2listers.UserLister,
|
||||
options *authentication.Options) PasswordAuthenticator {
|
||||
passwordAuthenticator := &passwordAuthenticator{
|
||||
ksClient: ksClient,
|
||||
userGetter: &userGetter{userLister: userLister},
|
||||
authOptions: options,
|
||||
}
|
||||
return passwordAuthenticator
|
||||
}
|
||||
|
||||
func (p *passwordAuthenticator) Authenticate(ctx context.Context, username, password string) (authuser.Info, string, error) {
|
||||
func (p *passwordAuthenticator) Authenticate(_ context.Context, username, password string) (authuser.Info, string, error) {
|
||||
// empty username or password are not allowed
|
||||
if username == "" || password == "" {
|
||||
return nil, "", IncorrectPasswordError
|
||||
@@ -69,17 +76,27 @@ func (p *passwordAuthenticator) Authenticate(ctx context.Context, username, pass
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
linkedAccount, err := p.userGetter.findMappedUser(providerOptions.Name, authenticated.GetUserID())
|
||||
if err != nil {
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
// using this method requires you to manually provision users.
|
||||
if providerOptions.MappingMethod == oauth.MappingMethodLookup && linkedAccount == nil {
|
||||
continue
|
||||
}
|
||||
// the user will automatically create and mapping when login successful.
|
||||
if linkedAccount == nil && providerOptions.MappingMethod == oauth.MappingMethodAuto {
|
||||
if !providerOptions.DisableLoginConfirmation {
|
||||
return preRegistrationUser(providerOptions.Name, authenticated), providerOptions.Name, nil
|
||||
}
|
||||
|
||||
linkedAccount, err = p.ksClient.IamV1alpha2().Users().Create(context.Background(), mappedUser(providerOptions.Name, authenticated), metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
}
|
||||
if linkedAccount != nil {
|
||||
return &authuser.DefaultInfo{Name: linkedAccount.GetName()}, providerOptions.Name, nil
|
||||
}
|
||||
// the user will automatically create and mapping when login successful.
|
||||
if providerOptions.MappingMethod == oauth.MappingMethodAuto {
|
||||
return preRegistrationUser(providerOptions.Name, authenticated), providerOptions.Name, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user