133 lines
4.0 KiB
Go
133 lines
4.0 KiB
Go
/*
|
||
* Copyright 2024 the KubeSphere Authors.
|
||
* Please refer to the LICENSE file in the root directory of the project.
|
||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||
*/
|
||
|
||
package identityprovider
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"sync"
|
||
|
||
v1 "k8s.io/api/core/v1"
|
||
toolscache "k8s.io/client-go/tools/cache"
|
||
"k8s.io/klog/v2"
|
||
runtimecache "sigs.k8s.io/controller-runtime/pkg/cache"
|
||
)
|
||
|
||
var SharedIdentityProviderController = NewController()
|
||
|
||
type Controller struct {
|
||
identityProviders *sync.Map
|
||
identityProviderConfigs *sync.Map
|
||
}
|
||
|
||
func NewController() *Controller {
|
||
return &Controller{identityProviders: &sync.Map{}, identityProviderConfigs: &sync.Map{}}
|
||
}
|
||
|
||
func (c *Controller) WatchConfigurationChanges(ctx context.Context, cache runtimecache.Cache) error {
|
||
informer, err := cache.GetInformer(ctx, &v1.Secret{})
|
||
if err != nil {
|
||
return fmt.Errorf("get informer failed: %w", err)
|
||
}
|
||
|
||
_, err = informer.AddEventHandler(toolscache.FilteringResourceEventHandler{
|
||
FilterFunc: func(obj interface{}) bool {
|
||
return IsIdentityProviderConfiguration(obj.(*v1.Secret))
|
||
},
|
||
Handler: &toolscache.ResourceEventHandlerFuncs{
|
||
AddFunc: func(obj interface{}) {
|
||
c.OnConfigurationChange(obj.(*v1.Secret))
|
||
},
|
||
UpdateFunc: func(old, new interface{}) {
|
||
c.OnConfigurationChange(new.(*v1.Secret))
|
||
},
|
||
DeleteFunc: func(obj interface{}) {
|
||
c.OnConfigurationDelete(obj.(*v1.Secret))
|
||
},
|
||
},
|
||
})
|
||
|
||
if err != nil {
|
||
return fmt.Errorf("add event handler failed: %w", err)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func (c *Controller) OnConfigurationDelete(secret *v1.Secret) {
|
||
configuration, err := UnmarshalFrom(secret)
|
||
if err != nil {
|
||
klog.Errorf("failed to unmarshal secret data: %s", err)
|
||
return
|
||
}
|
||
c.identityProviders.Delete(configuration.Name)
|
||
c.identityProviderConfigs.Delete(configuration.Name)
|
||
}
|
||
|
||
func (c *Controller) OnConfigurationChange(secret *v1.Secret) {
|
||
configuration, err := UnmarshalFrom(secret)
|
||
if err != nil {
|
||
klog.Errorf("failed to unmarshal secret data: %s", err)
|
||
return
|
||
}
|
||
|
||
if genericProviderFactories[configuration.Type] == nil && oauthProviderFactories[configuration.Type] == nil {
|
||
klog.Errorf("identity provider %s with type %s is not supported", configuration.Name, configuration.Type)
|
||
return
|
||
}
|
||
|
||
if factory, ok := oauthProviderFactories[configuration.Type]; ok {
|
||
if provider, err := factory.Create(configuration.ProviderOptions); err != nil {
|
||
// don’t return errors, decoupling external dependencies
|
||
klog.Error(fmt.Sprintf("failed to create identity provider %s: %s", configuration.Name, err))
|
||
} else {
|
||
c.identityProviders.Store(configuration.Name, provider)
|
||
c.identityProviderConfigs.Store(configuration.Name, configuration)
|
||
klog.Infof("create identity provider %s successfully", configuration.Name)
|
||
}
|
||
}
|
||
if factory, ok := genericProviderFactories[configuration.Type]; ok {
|
||
if provider, err := factory.Create(configuration.ProviderOptions); err != nil {
|
||
klog.Error(fmt.Sprintf("failed to create identity provider %s: %s", configuration.Name, err))
|
||
} else {
|
||
c.identityProviders.Store(configuration.Name, provider)
|
||
c.identityProviderConfigs.Store(configuration.Name, configuration)
|
||
klog.V(4).Infof("create identity provider %s successfully", configuration.Name)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
func (c *Controller) GetGenericProvider(providerName string) (GenericProvider, bool) {
|
||
if obj, ok := c.identityProviders.Load(providerName); ok {
|
||
if provider, ok := obj.(GenericProvider); ok {
|
||
return provider, true
|
||
}
|
||
}
|
||
return nil, false
|
||
}
|
||
|
||
func (c *Controller) GetOAuthProvider(providerName string) (OAuthProvider, bool) {
|
||
if obj, ok := c.identityProviders.Load(providerName); ok {
|
||
if provider, ok := obj.(OAuthProvider); ok {
|
||
return provider, true
|
||
}
|
||
}
|
||
return nil, false
|
||
}
|
||
|
||
func (c *Controller) ListConfigurations() []*Configuration {
|
||
configurations := make([]*Configuration, 0)
|
||
c.identityProviderConfigs.Range(func(key, value any) bool {
|
||
if configuration, ok := value.(*Configuration); ok {
|
||
configurations = append(configurations, configuration)
|
||
}
|
||
return true
|
||
})
|
||
return configurations
|
||
}
|