feat(auth): support multiple identity provider associations (#6299)

Signed-off-by: hongming <coder.scala@gmail.com>
This commit is contained in:
hongming
2025-02-28 16:48:36 +08:00
committed by GitHub
parent 99d2408c34
commit 018f6045ee
12 changed files with 177 additions and 221 deletions

View File

@@ -8,6 +8,7 @@ package identityprovider
import (
"context"
"errors"
"fmt"
"gopkg.in/yaml.v3"
v1 "k8s.io/api/core/v1"
@@ -35,6 +36,8 @@ const (
var ErrorIdentityProviderNotFound = errors.New("the Identity provider was not found")
var IdentityProviderIsDisabled = errors.New("the Identity provider was Disabled")
type MappingMethod string
type Configuration struct {
@@ -52,6 +55,15 @@ type Configuration struct {
// The type of identity provider
Type string `json:"type" yaml:"type"`
// The hidden of login button
Hidden bool `json:"hidden" yaml:"hidden"`
// The disabled of identify provider
Disabled bool `json:"disabled" yaml:"disabled"`
// The display name of identify provider
DisplayName string `json:"displayName" yaml:"displayName"`
// The options of identify provider
ProviderOptions options.DynamicOptions `json:"provider" yaml:"provider"`
}
@@ -72,19 +84,19 @@ type configurationGetter struct {
func (o *configurationGetter) ListConfigurations(ctx context.Context) ([]*Configuration, error) {
configurations := make([]*Configuration, 0)
secrets := &v1.SecretList{}
if err := o.List(ctx, secrets, client.InNamespace(constants.KubeSphereNamespace), client.MatchingLabels{constants.GenericConfigTypeLabel: ConfigTypeIdentityProvider}); err != nil {
klog.Errorf("failed to list secrets: %v", err)
return nil, err
if err := o.List(ctx, secrets, client.InNamespace(constants.KubeSphereNamespace),
client.MatchingLabels{constants.GenericConfigTypeLabel: ConfigTypeIdentityProvider}); err != nil {
return nil, fmt.Errorf("failed to list secrets: %s", err)
}
for _, secret := range secrets.Items {
if secret.Type != SecretTypeIdentityProvider {
continue
}
if c, err := UnmarshalFrom(&secret); err != nil {
if config, err := UnmarshalFrom(&secret); err != nil {
klog.Errorf("failed to unmarshal secret data: %s", err)
continue
} else {
configurations = append(configurations, c)
configurations = append(configurations, config)
}
}
return configurations, nil
@@ -93,23 +105,25 @@ func (o *configurationGetter) ListConfigurations(ctx context.Context) ([]*Config
func (o *configurationGetter) GetConfiguration(ctx context.Context, name string) (*Configuration, error) {
configurations, err := o.ListConfigurations(ctx)
if err != nil {
klog.Errorf("failed to list identity providers: %v", err)
return nil, err
return nil, fmt.Errorf("failed to list configurations: %s", err)
}
for _, c := range configurations {
if c.Name == name {
return c, nil
for _, config := range configurations {
if config.Name == name {
if config.Disabled {
return nil, IdentityProviderIsDisabled
}
return config, nil
}
}
return nil, ErrorIdentityProviderNotFound
}
func UnmarshalFrom(secret *v1.Secret) (*Configuration, error) {
c := &Configuration{}
if err := yaml.Unmarshal(secret.Data[SecretDataKey], c); err != nil {
return nil, err
config := &Configuration{}
if err := yaml.Unmarshal(secret.Data[SecretDataKey], config); err != nil {
return nil, fmt.Errorf("failed to unmarshal secret data: %s", err)
}
return c, nil
return config, nil
}
func IsIdentityProviderConfiguration(secret *v1.Secret) bool {

View File

@@ -268,34 +268,6 @@ func (r *Reconciler) reconcileUserStatus(ctx context.Context, user *iamv1beta1.U
return nil
}
if user.Spec.EncryptedPassword == "" {
if user.Labels[iamv1beta1.IdentifyProviderLabel] != "" {
// mapped user from another identity provider always active until disabled
if user.Status.State != iamv1beta1.UserActive {
user.Status = iamv1beta1.UserStatus{
State: iamv1beta1.UserActive,
LastTransitionTime: &metav1.Time{Time: time.Now()},
}
if err := r.Update(ctx, user, &client.UpdateOptions{}); err != nil {
return err
}
}
} else {
// empty password is not allowed for normal user
if user.Status.State != iamv1beta1.UserDisabled {
user.Status = iamv1beta1.UserStatus{
State: iamv1beta1.UserDisabled,
LastTransitionTime: &metav1.Time{Time: time.Now()},
}
if err := r.Update(ctx, user, &client.UpdateOptions{}); err != nil {
return err
}
}
}
// skip auth limit check
return nil
}
// becomes active after password encrypted
if user.Status.State == "" && isEncrypted(user.Spec.EncryptedPassword) {
user.Status = iamv1beta1.UserStatus{

View File

@@ -144,11 +144,10 @@ func (h *handler) CreateUser(req *restful.Request, resp *restful.Response) {
api.HandleBadRequest(resp, req, err)
return
}
if user.Labels == nil {
if user.Annotations == nil {
user.Labels = make(map[string]string)
}
user.Labels[iamv1beta1.IdentifyProviderLabel] = extra[iamv1beta1.ExtraIdentityProvider][0]
user.Labels[iamv1beta1.OriginUIDLabel] = extra[iamv1beta1.ExtraUID][0]
user.Annotations[fmt.Sprintf("%s.%s", iamv1beta1.IdentityProviderAnnotation, extra[iamv1beta1.ExtraIdentityProvider][0])] = extra[iamv1beta1.ExtraUID][0]
delete(user.Annotations, iamv1beta1.GlobalRoleAnnotation)
}

View File

@@ -17,7 +17,6 @@ import (
"github.com/go-jose/go-jose/v4"
"github.com/golang-jwt/jwt/v4"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog/v2"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
@@ -530,7 +529,7 @@ func (h *handler) refreshTokenGrant(req *restful.Request, response *restful.Resp
idp := authenticated.GetExtra()[iamv1beta1.ExtraIdentityProvider][0]
uid := authenticated.GetExtra()[iamv1beta1.ExtraUID][0]
queryParam := query.New()
queryParam.LabelSelector = labels.SelectorFromSet(labels.Set{iamv1beta1.IdentifyProviderLabel: idp, iamv1beta1.OriginUIDLabel: uid}).String()
queryParam.Filters = map[query.Field]query.Value{query.FieldAnnotation: query.Value(fmt.Sprintf("%s.%s=%s", iamv1beta1.IdentityProviderAnnotation, idp, uid))}
users, err := h.im.ListUsers(queryParam)
if err != nil {
klog.Errorf("failed to list users: %s", err)

View File

@@ -13,7 +13,10 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
authuser "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog/v2"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider"
)
@@ -54,17 +57,56 @@ func newRreRegistrationUser(idp string, identity identityprovider.Identity) auth
}
}
func newMappedUser(idp string, identity identityprovider.Identity) *iamv1beta1.User {
// username convert
username := strings.ToLower(identity.GetUsername())
return &iamv1beta1.User{
ObjectMeta: metav1.ObjectMeta{
Name: username,
Labels: map[string]string{
iamv1beta1.IdentifyProviderLabel: idp,
iamv1beta1.OriginUIDLabel: identity.GetUserID(),
},
},
Spec: iamv1beta1.UserSpec{Email: identity.GetEmail()},
func authByIdentityProvider(ctx context.Context, client client.Client, mapper UserMapper, providerConfig *identityprovider.Configuration, identity identityprovider.Identity) (authuser.Info, error) {
mappedUser, err := mapper.FindMappedUser(ctx, providerConfig.Name, identity.GetUserID())
if err != nil {
return nil, fmt.Errorf("failed to find mapped user: %s", err)
}
if mappedUser.Name == "" {
if providerConfig.MappingMethod == identityprovider.MappingMethodLookup {
return nil, fmt.Errorf("failed to find mapped user: %s", identity.GetUserID())
}
if providerConfig.MappingMethod == identityprovider.MappingMethodManual {
return newRreRegistrationUser(providerConfig.Name, identity), nil
}
if providerConfig.MappingMethod == identityprovider.MappingMethodAuto {
mappedUser := iamv1beta1.User{ObjectMeta: metav1.ObjectMeta{Name: strings.ToLower(identity.GetUsername())}}
op, err := ctrl.CreateOrUpdate(ctx, client, &mappedUser, func() error {
if mappedUser.Status.State == iamv1beta1.UserDisabled {
return AccountIsNotActiveError
}
if mappedUser.Annotations == nil {
mappedUser.Annotations = make(map[string]string)
}
mappedUser.Annotations[fmt.Sprintf("%s.%s", iamv1beta1.IdentityProviderAnnotation, providerConfig.Name)] = identity.GetUserID()
mappedUser.Status.State = iamv1beta1.UserActive
if identity.GetEmail() != "" {
mappedUser.Spec.Email = identity.GetEmail()
}
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to create or update user %s, error: %v", mappedUser.Name, err)
}
klog.V(4).Infof("user %s has been updated successfully, operation: %s", mappedUser.Name, op)
return &authuser.DefaultInfo{Name: mappedUser.GetName()}, nil
}
return nil, fmt.Errorf("invalid mapping method found %s", providerConfig.MappingMethod)
}
if mappedUser.Status.State == iamv1beta1.UserDisabled {
return nil, AccountIsNotActiveError
}
return &authuser.DefaultInfo{Name: mappedUser.GetName()}, nil
}

View File

@@ -9,7 +9,6 @@ import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
@@ -37,12 +36,10 @@ func (l *loginRecorder) RecordLogin(ctx context.Context, username string, loginT
// only for existing accounts, solve the problem of huge entries
user, err := l.userMapper.Find(ctx, username)
if err != nil {
// ignore not found error
if errors.IsNotFound(err) {
return nil
}
klog.Error(err)
return err
return fmt.Errorf("failed to find user %s", username)
}
if user.Name == "" {
return nil
}
record := &iamv1beta1.LoginRecord{
ObjectMeta: metav1.ObjectMeta{

View File

@@ -7,51 +7,74 @@ package auth
import (
"context"
"fmt"
"net/mail"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
)
type UserMapper interface {
Find(ctx context.Context, username string) (iamv1beta1.User, error)
FindMappedUser(ctx context.Context, idp, uid string) (iamv1beta1.User, error)
}
type userMapper struct {
cache runtimeclient.Reader
}
// Find returns the user associated with the username or email
func (u *userMapper) Find(ctx context.Context, username string) (*iamv1beta1.User, error) {
user := &iamv1beta1.User{}
if _, err := mail.ParseAddress(username); err != nil {
return user, u.cache.Get(ctx, types.NamespacedName{Name: username}, user)
func (u *userMapper) Find(ctx context.Context, username string) (iamv1beta1.User, error) {
user, err := u.getUserByUsernameOrEmail(ctx, username)
if err != nil {
return iamv1beta1.User{}, err
}
return user, nil
}
// TODO cache with index
userList := &iamv1beta1.UserList{}
if err := u.cache.List(ctx, userList); err != nil {
return nil, err
func (u *userMapper) FindMappedUser(ctx context.Context, idp, uid string) (iamv1beta1.User, error) {
user, err := u.getUserByAnnotation(ctx, fmt.Sprintf("%s.%s", iamv1beta1.IdentityProviderAnnotation, idp), uid)
if err != nil {
return iamv1beta1.User{}, err
}
return user, nil
}
for _, user := range userList.Items {
if user.Spec.Email == username {
return &user, nil
func (u *userMapper) getUserByUsernameOrEmail(ctx context.Context, username string) (iamv1beta1.User, error) {
if _, err := mail.ParseAddress(username); err == nil {
return u.getUserByEmail(ctx, username)
}
return u.getUserByName(ctx, username)
}
func (u *userMapper) getUserByName(ctx context.Context, username string) (iamv1beta1.User, error) {
user := iamv1beta1.User{}
err := u.cache.Get(ctx, types.NamespacedName{Name: username}, &user)
return user, runtimeclient.IgnoreNotFound(err)
}
func (u *userMapper) getUserByEmail(ctx context.Context, email string) (iamv1beta1.User, error) {
users := &iamv1beta1.UserList{}
if err := u.cache.List(ctx, users); err != nil {
return iamv1beta1.User{}, err
}
for _, user := range users.Items {
if user.Spec.Email == email {
return user, nil
}
}
return nil, errors.NewNotFound(iamv1beta1.Resource("user"), username)
return iamv1beta1.User{}, nil
}
// FindMappedUser returns the user which mapped to the identity
func (u *userMapper) FindMappedUser(ctx context.Context, idp, uid string) (*iamv1beta1.User, error) {
userList := &iamv1beta1.UserList{}
if err := u.cache.List(ctx, userList, runtimeclient.MatchingLabels{
iamv1beta1.IdentifyProviderLabel: idp,
iamv1beta1.OriginUIDLabel: uid,
}); err != nil {
return nil, err
func (u *userMapper) getUserByAnnotation(ctx context.Context, annotation, value string) (iamv1beta1.User, error) {
users := &iamv1beta1.UserList{}
if err := u.cache.List(ctx, users); err != nil {
return iamv1beta1.User{}, err
}
if len(userList.Items) != 1 {
return nil, nil
for _, user := range users.Items {
if user.Annotations[annotation] == value {
return user, nil
}
}
return &userList.Items[0], nil
return iamv1beta1.User{}, nil
}

View File

@@ -11,7 +11,6 @@ import (
"net/http"
authuser "k8s.io/apiserver/pkg/authentication/user"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider"
@@ -19,15 +18,15 @@ import (
type oauthAuthenticator struct {
client runtimeclient.Client
userGetter *userMapper
userMapper UserMapper
idpConfigurationGetter identityprovider.ConfigurationGetter
}
func NewOAuthAuthenticator(cacheClient runtimeclient.Client) OAuthAuthenticator {
func NewOAuthAuthenticator(client runtimeclient.Client) OAuthAuthenticator {
authenticator := &oauthAuthenticator{
client: cacheClient,
userGetter: &userMapper{cache: cacheClient},
idpConfigurationGetter: identityprovider.NewConfigurationGetter(cacheClient),
client: client,
userMapper: &userMapper{cache: client},
idpConfigurationGetter: identityprovider.NewConfigurationGetter(client),
}
return authenticator
}
@@ -49,36 +48,5 @@ func (o *oauthAuthenticator) Authenticate(ctx context.Context, provider string,
return nil, fmt.Errorf("failed to exchange identity for %s, error: %v", provider, err)
}
mappedUser, err := o.userGetter.FindMappedUser(ctx, providerConfig.Name, identity.GetUserID())
if err != nil {
return nil, fmt.Errorf("failed to find mapped user for %s, error: %v", provider, err)
}
if mappedUser == nil {
if providerConfig.MappingMethod == identityprovider.MappingMethodLookup {
return nil, fmt.Errorf("failed to find mapped user: %s", identity.GetUserID())
}
if providerConfig.MappingMethod == identityprovider.MappingMethodManual {
return newRreRegistrationUser(providerConfig.Name, identity), nil
}
if providerConfig.MappingMethod == identityprovider.MappingMethodAuto {
mappedUser = newMappedUser(providerConfig.Name, identity)
if err = o.client.Create(ctx, mappedUser); err != nil {
return nil, err
}
return &authuser.DefaultInfo{Name: mappedUser.GetName()}, nil
}
return nil, fmt.Errorf("invalid mapping method found %s", providerConfig.MappingMethod)
}
if mappedUser.Status.State == iamv1beta1.UserDisabled {
return nil, AccountIsNotActiveError
}
return &authuser.DefaultInfo{Name: mappedUser.GetName()}, nil
return authByIdentityProvider(ctx, o.client, o.userMapper, providerConfig, identity)
}

View File

@@ -51,10 +51,7 @@ func Test_oauthAuthenticator_Authenticate(t *testing.T) {
},
}
marshal, err := yaml.Marshal(fakeIDP)
if err != nil {
return
}
marshal, _ := yaml.Marshal(fakeIDP)
secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
@@ -71,8 +68,8 @@ func Test_oauthAuthenticator_Authenticate(t *testing.T) {
}
fakeCache := informertest.FakeInformers{Scheme: scheme.Scheme}
err = fakeCache.Start(context.Background())
if err != nil {
if err := fakeCache.Start(context.Background()); err != nil {
t.Fatal(err)
}
fakeSecretInformer, err := fakeCache.FakeInformerFor(context.Background(), &v1.Secret{})
@@ -177,9 +174,8 @@ func newUser(username string, uid string, idp string) *iamv1beta1.User {
},
ObjectMeta: metav1.ObjectMeta{
Name: username,
Labels: map[string]string{
iamv1beta1.IdentifyProviderLabel: idp,
iamv1beta1.OriginUIDLabel: uid,
Annotations: map[string]string{
fmt.Sprintf("%s.%s", iamv1beta1.IdentityProviderAnnotation, idp): uid,
},
},
}

View File

@@ -20,7 +20,7 @@ import (
)
type passwordAuthenticator struct {
userGetter *userMapper
userMapper UserMapper
client runtimeclient.Client
authOptions *authentication.Options
identityProviderConfigurationGetter identityprovider.ConfigurationGetter
@@ -29,7 +29,7 @@ type passwordAuthenticator struct {
func NewPasswordAuthenticator(cacheClient runtimeclient.Client, options *authentication.Options) PasswordAuthenticator {
passwordAuthenticator := &passwordAuthenticator{
client: cacheClient,
userGetter: &userMapper{cache: cacheClient},
userMapper: &userMapper{cache: cacheClient},
identityProviderConfigurationGetter: identityprovider.NewConfigurationGetter(cacheClient),
authOptions: options,
}
@@ -49,36 +49,28 @@ func (p *passwordAuthenticator) Authenticate(ctx context.Context, provider, user
// authByKubeSphere authenticate by the kubesphere user
func (p *passwordAuthenticator) authByKubeSphere(ctx context.Context, username, password string) (authuser.Info, error) {
user, err := p.userGetter.Find(ctx, username)
user, err := p.userMapper.Find(ctx, username)
if err != nil {
if errors.IsNotFound(err) {
return nil, IncorrectPasswordError
}
return nil, fmt.Errorf("failed to find user: %s", err)
}
if user == nil {
if user.Name == "" {
return nil, IncorrectPasswordError
}
// check user status
if user.Status.State != iamv1beta1.UserActive {
if user.Status.State == iamv1beta1.UserAuthLimitExceeded {
return nil, RateLimitExceededError
} else {
return nil, AccountIsNotActiveError
}
switch user.Status.State {
case iamv1beta1.UserAuthLimitExceeded:
return nil, RateLimitExceededError
case iamv1beta1.UserActive:
break
default:
return nil, AccountIsNotActiveError
}
// if the password is not empty, means that the password has been reset, even if the user was mapping from IDP
if user.Spec.EncryptedPassword == "" {
if user.Spec.EncryptedPassword == "" || PasswordVerify(user.Spec.EncryptedPassword, password) != nil {
return nil, IncorrectPasswordError
}
if err = PasswordVerify(user.Spec.EncryptedPassword, password); err != nil {
return nil, err
}
info := &authuser.DefaultInfo{
Name: user.Name,
Groups: user.Spec.Groups,
@@ -111,41 +103,10 @@ func (p *passwordAuthenticator) authByProvider(ctx context.Context, provider, us
if errors.IsUnauthorized(err) {
return nil, IncorrectPasswordError
}
return nil, err
return nil, fmt.Errorf("failed to authenticate by identity provider %s: %s", provider, err)
}
mappedUser, err := p.userGetter.FindMappedUser(ctx, provider, identity.GetUserID())
if err != nil {
return nil, fmt.Errorf("failed to find mapped user: %s", err)
}
if mappedUser == nil {
if providerConfig.MappingMethod == identityprovider.MappingMethodLookup {
return nil, fmt.Errorf("failed to find mapped user: %s", identity.GetUserID())
}
if providerConfig.MappingMethod == identityprovider.MappingMethodManual {
return newRreRegistrationUser(providerConfig.Name, identity), nil
}
if providerConfig.MappingMethod == identityprovider.MappingMethodAuto {
mappedUser = newMappedUser(providerConfig.Name, identity)
if err = p.client.Create(ctx, mappedUser); err != nil {
return nil, err
}
return &authuser.DefaultInfo{Name: mappedUser.GetName()}, nil
}
return nil, fmt.Errorf("invalid mapping method found %s", providerConfig.MappingMethod)
}
if mappedUser.Status.State == iamv1beta1.UserDisabled {
return nil, AccountIsNotActiveError
}
return &authuser.DefaultInfo{Name: mappedUser.GetName()}, nil
return authByIdentityProvider(ctx, p.client, p.userMapper, providerConfig, identity)
}
func PasswordVerify(encryptedPassword, password string) error {

View File

@@ -10,30 +10,24 @@ import (
"reflect"
"testing"
"sigs.k8s.io/controller-runtime/pkg/cache/informertest"
"kubesphere.io/kubesphere/pkg/constants"
"gopkg.in/yaml.v3"
runtimefakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
"kubesphere.io/kubesphere/pkg/scheme"
"kubesphere.io/kubesphere/pkg/server/options"
"github.com/mitchellh/mapstructure"
"golang.org/x/crypto/bcrypt"
"gopkg.in/yaml.v3"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/user"
authuser "k8s.io/apiserver/pkg/authentication/user"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/cache/informertest"
runtimefakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
"kubesphere.io/kubesphere/pkg/apiserver/authentication"
"kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider"
"kubesphere.io/kubesphere/pkg/apiserver/authentication/oauth"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/scheme"
"kubesphere.io/kubesphere/pkg/server/options"
)
func TestEncryptPassword(t *testing.T) {
@@ -112,10 +106,7 @@ func Test_passwordAuthenticator_Authenticate(t *testing.T) {
},
}
marshal1, err := yaml.Marshal(fakepwd1)
if err != nil {
return
}
marshal1, _ := yaml.Marshal(fakepwd1)
fakepwd1Secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
@@ -131,10 +122,8 @@ func Test_passwordAuthenticator_Authenticate(t *testing.T) {
Type: identityprovider.SecretTypeIdentityProvider,
}
marshal2, err := yaml.Marshal(fakepwd2)
if err != nil {
return
}
marshal2, _ := yaml.Marshal(fakepwd2)
fakepwd2Secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-fake-idp2",
@@ -149,10 +138,8 @@ func Test_passwordAuthenticator_Authenticate(t *testing.T) {
Type: identityprovider.SecretTypeIdentityProvider,
}
marshal3, err := yaml.Marshal(fakepwd3)
if err != nil {
return
}
marshal3, _ := yaml.Marshal(fakepwd3)
fakepwd3Secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-fake-idp3",
@@ -180,8 +167,8 @@ func Test_passwordAuthenticator_Authenticate(t *testing.T) {
Build()
fakeCache := informertest.FakeInformers{Scheme: scheme.Scheme}
err = fakeCache.Start(context.Background())
if err != nil {
if err := fakeCache.Start(context.Background()); err != nil {
t.Fatal(err)
}
fakeSecretInformer, err := fakeCache.FakeInformerFor(context.Background(), &v1.Secret{})

View File

@@ -54,8 +54,7 @@ const (
ScopeLabel = "iam.kubesphere.io/scope"
UserReferenceLabel = "iam.kubesphere.io/user-ref"
RoleReferenceLabel = "iam.kubesphere.io/role-ref"
IdentifyProviderLabel = "iam.kubesphere.io/identify-provider"
OriginUIDLabel = "iam.kubesphere.io/origin-uid"
IdentityProviderAnnotation = "iam.kubesphere.io/identity-provider"
ServiceAccountReferenceLabel = "iam.kubesphere.io/serviceaccount-ref"
FieldEmail = "email"
ExtraEmail = FieldEmail
@@ -71,7 +70,6 @@ const (
NamespaceAdmin = "admin"
ClusterAdmin = "cluster-admin"
PreRegistrationUser = "system:pre-registration"
OTPAuthRequiredUser = "system:otp-auth-required"
ResourcePluralGroup = "groups"
GroupReferenceLabel = "iam.kubesphere.io/group-ref"
GroupParent = "iam.kubesphere.io/group-parent"