145 lines
4.6 KiB
Go
145 lines
4.6 KiB
Go
/*
|
|
Copyright 2017 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"net/url"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/signals"
|
|
authentikapi "goauthentik.io/api/v3"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
"k8s.io/klog/v2"
|
|
|
|
// Uncomment the following line to load the gcp plugin (only required to authenticate against GKE clusters).
|
|
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
|
|
|
applicationcontroller "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/controllers/application"
|
|
proxyprovidercontroller "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/controllers/proxyprovider"
|
|
clientset "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
|
|
informers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions"
|
|
)
|
|
|
|
var (
|
|
masterURL string
|
|
kubeconfig string
|
|
)
|
|
|
|
func main() {
|
|
klog.InitFlags(nil)
|
|
flag.Parse()
|
|
|
|
// set up signals so we handle the shutdown signal gracefully
|
|
ctx := signals.SetupSignalHandler()
|
|
logger := klog.FromContext(ctx)
|
|
|
|
cfg, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
|
|
if err != nil {
|
|
logger.Error(err, "Error building kubeconfig")
|
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
|
}
|
|
|
|
kubeClient, err := kubernetes.NewForConfig(cfg)
|
|
if err != nil {
|
|
logger.Error(err, "Error building kubernetes clientset")
|
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
|
}
|
|
|
|
clientset, err := clientset.NewForConfig(cfg)
|
|
if err != nil {
|
|
logger.Error(err, "Error building proxy provider clientset")
|
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
|
}
|
|
|
|
authentikClient, err := newAuthentikAPIClient(os.Getenv("AUTENTIK_HOST"), os.Getenv("AUTENTIK_TOKEN"))
|
|
if err != nil {
|
|
logger.Error(err, "Error building Authentik API client")
|
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
|
}
|
|
|
|
proxyProviderInformerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)
|
|
|
|
ppController := proxyprovidercontroller.NewController(ctx, kubeClient, clientset, authentikClient,
|
|
proxyProviderInformerFactory.Proxyprovider().V1alpha1().ProxyProviders(),
|
|
)
|
|
|
|
applicationInformerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)
|
|
appController := applicationcontroller.NewController(ctx, kubeClient, clientset, authentikClient,
|
|
applicationInformerFactory.Application().V1alpha1().Applications(),
|
|
)
|
|
|
|
// notice that there is no need to run Start methods in a separate goroutine. (i.e. go kubeInformerFactory.Start(ctx.done())
|
|
// Start method is non-blocking and runs all registered informers in a dedicated goroutine.
|
|
proxyProviderInformerFactory.Start(ctx.Done())
|
|
applicationInformerFactory.Start(ctx.Done())
|
|
|
|
var wg sync.WaitGroup
|
|
wg.Add(2)
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
if err := ppController.Run(ctx, 2); err != nil {
|
|
logger.Error(err, "Error running proxy provider controller")
|
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
if err := appController.Run(ctx, 2); err != nil {
|
|
logger.Error(err, "Error running application controller")
|
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
|
}
|
|
}()
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func init() {
|
|
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
|
|
flag.StringVar(&masterURL, "master", "", "The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.")
|
|
}
|
|
|
|
// newAuthentikAPIClient builds the OpenAPI-generated goauthentik client when AUTENTIK_HOST is set.
|
|
func newAuthentikAPIClient(host, token string) (*authentikapi.APIClient, error) {
|
|
if host == "" {
|
|
return nil, errors.New("authentik host is not set")
|
|
}
|
|
cfg := authentikapi.NewConfiguration()
|
|
if u, err := url.Parse(host); err == nil && u.Host != "" {
|
|
cfg.Scheme = u.Scheme
|
|
if cfg.Scheme == "" {
|
|
cfg.Scheme = "https"
|
|
}
|
|
cfg.Host = u.Host
|
|
} else {
|
|
cfg.Scheme = "https"
|
|
cfg.Host = host
|
|
}
|
|
if token == "" {
|
|
return nil, errors.New("authentik token is not set")
|
|
}
|
|
cfg.AddDefaultHeader("Authorization", "Bearer "+token)
|
|
|
|
return authentikapi.NewAPIClient(cfg), nil
|
|
}
|