From 90d21f1dd8a1a3623fa1b9aac348427f2cfb3b08 Mon Sep 17 00:00:00 2001 From: Timo Behrendt Date: Fri, 15 May 2026 11:09:20 +0200 Subject: [PATCH] mvp working creation of proxy provider --- .gitignore | 7 ++- .vscode/launch.json | 17 ++++++ Makefile | 12 ++-- artifacts/{examples => crd}/crd.yaml | 8 +++ artifacts/examples/example-foo.yaml | 7 --- artifacts/examples/proxyProvider.yaml | 11 ++++ controller.go | 84 +++++++++++++++++++++++---- go.mod | 8 +-- go.sum | 23 +------- main.go | 46 +++++++++++++-- pkg/apis/proxyprovider/v1/types.go | 1 + 11 files changed, 166 insertions(+), 58 deletions(-) create mode 100644 .vscode/launch.json rename artifacts/{examples => crd}/crd.yaml (85%) delete mode 100644 artifacts/examples/example-foo.yaml create mode 100644 artifacts/examples/proxyProvider.yaml diff --git a/.gitignore b/.gitignore index eb38878..dc7f41b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,9 @@ go.work.sum # env file .env -vendor/* + +# vendor directory +vendor/ + +# build artifacts +main diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..edadf84 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${fileDirname}", + "args": ["--kubeconfig=/home/tbehrendt/.kube/config"], + "envFile": ".env" + } + ] +} diff --git a/Makefile b/Makefile index f9cac0a..0c34b95 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,15 @@ -REPO_ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) - +ifneq (,$(wildcard ./.env)) + include .env + export +endif .PHONY: build run codegen build: - go build + go build -o main run: make build - ./main + ./main --kubeconfig=/home/tbehrendt/.kube/config codegen: - $(REPO_ROOT)/scripts/codegen.sh + ./scripts/codegen.sh diff --git a/artifacts/examples/crd.yaml b/artifacts/crd/crd.yaml similarity index 85% rename from artifacts/examples/crd.yaml rename to artifacts/crd/crd.yaml index e492835..59cb9f9 100644 --- a/artifacts/examples/crd.yaml +++ b/artifacts/crd/crd.yaml @@ -8,6 +8,12 @@ spec: - name: v1 served: true storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: PK + type: string + jsonPath: .status.pk schema: openAPIV3Schema: type: object @@ -38,4 +44,6 @@ spec: names: kind: ProxyProvider plural: proxyproviders + shortNames: + - pp scope: Namespaced diff --git a/artifacts/examples/example-foo.yaml b/artifacts/examples/example-foo.yaml deleted file mode 100644 index 897059c..0000000 --- a/artifacts/examples/example-foo.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: samplecontroller.k8s.io/v1alpha1 -kind: Foo -metadata: - name: example-foo -spec: - deploymentName: example-foo - replicas: 1 diff --git a/artifacts/examples/proxyProvider.yaml b/artifacts/examples/proxyProvider.yaml new file mode 100644 index 0000000..94e55d7 --- /dev/null +++ b/artifacts/examples/proxyProvider.yaml @@ -0,0 +1,11 @@ +# Example ProxyProvider CRD +apiVersion: proxyprovider.t000-n.de/v1 +kind: ProxyProvider +metadata: + name: proxy-provider-example + namespace: kube-system +spec: + name: proxy-provider-example + authorization_flow: 16896c6d-b326-42d1-8d3f-93f32921962e + invalidation_flow: 7acac1ef-19e3-4a6f-8d8d-14ca7031d184 + external_host: https://example.t00n.de diff --git a/controller.go b/controller.go index 908fd98..d5f06c6 100644 --- a/controller.go +++ b/controller.go @@ -19,6 +19,7 @@ package main import ( "context" "fmt" + "strconv" "time" "golang.org/x/time/rate" @@ -39,10 +40,12 @@ import ( "k8s.io/client-go/util/workqueue" "k8s.io/klog/v2" + v1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1" clientset "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned" operatorscheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme" informers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/proxyprovider/v1" listers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/listers/proxyprovider/v1" + authentikapi "goauthentik.io/api/v3" ) const controllerAgentName = "proxy-provider-controller" @@ -56,8 +59,9 @@ const ( ) type Controller struct { - kubeclientset kubernetes.Interface - operatorclientset clientset.Interface + kubeclientset kubernetes.Interface + proxyProviderClientset clientset.Interface + authentik *authentikapi.APIClient deploymentsLister appslisters.DeploymentLister deploymentsSynced cache.InformerSynced @@ -71,7 +75,8 @@ type Controller struct { func NewController( ctx context.Context, kubeclientset kubernetes.Interface, - operatorclientset clientset.Interface, + proxyProviderClientset clientset.Interface, + authentik *authentikapi.APIClient, deploymentInformer appsinformers.DeploymentInformer, proxyInformer informers.ProxyProviderInformer, ) *Controller { @@ -90,14 +95,15 @@ func NewController( ) c := &Controller{ - kubeclientset: kubeclientset, - operatorclientset: operatorclientset, - deploymentsLister: deploymentInformer.Lister(), - deploymentsSynced: deploymentInformer.Informer().HasSynced, - proxyLister: proxyInformer.Lister(), - proxySynced: proxyInformer.Informer().HasSynced, - workqueue: workqueue.NewTypedRateLimitingQueue(ratelimiter), - recorder: recorder, + kubeclientset: kubeclientset, + proxyProviderClientset: proxyProviderClientset, + authentik: authentik, + deploymentsLister: deploymentInformer.Lister(), + deploymentsSynced: deploymentInformer.Informer().HasSynced, + proxyLister: proxyInformer.Lister(), + proxySynced: proxyInformer.Informer().HasSynced, + workqueue: workqueue.NewTypedRateLimitingQueue(ratelimiter), + recorder: recorder, } logger.Info("Setting up event handlers") @@ -181,8 +187,55 @@ func (c *Controller) syncHandler(ctx context.Context, objectRef cache.ObjectName } return err } - logger.V(4).Info("sync ProxyProvider", "name", pp.Name) + + if pp.Status.PK != "" { + // We retrieve the existing PP from the API by slug. + pk, err := strconv.ParseInt(pp.Status.PK, 10, 32) + if err != nil { + return fmt.Errorf("error parsing PK: %v", err) + } + _, _, err = c.authentik.ProvidersApi.ProvidersAllRetrieve(ctx, int32(pk)).Execute() + if err != nil { + return fmt.Errorf("error retrieving existing ProxyProvider: %v", err) + } + + // We update the existing PP with the new spec. + proxyProviderRequest := &authentikapi.ProxyProviderRequest{ + Name: pp.Spec.Name, + AuthorizationFlow: pp.Spec.AuthorizationFlow, + InvalidationFlow: pp.Spec.InvalidationFlow, + ExternalHost: pp.Spec.ExternalHost, + Mode: authentikapi.PROXYMODE_FORWARD_SINGLE.Ptr(), + } + resp, r, err := c.authentik.ProvidersApi.ProvidersProxyUpdate(ctx, int32(pk)).ProxyProviderRequest(*proxyProviderRequest).Execute() + if err != nil { + return fmt.Errorf("error when calling `ProvidersAPI.ProvidersProxyUpdate`: %w with response %v", err, r) + } + pp.Status.PK = strconv.Itoa(int(resp.Pk)) + err = c.updateProxyProviderStatus(ctx, pp) + if err != nil { + return fmt.Errorf("error updating ProxyProvider status: %v", err) + } + } else { + proxyProviderRequest := &authentikapi.ProxyProviderRequest{ + Name: pp.Spec.Name, + AuthorizationFlow: pp.Spec.AuthorizationFlow, + InvalidationFlow: pp.Spec.InvalidationFlow, + ExternalHost: pp.Spec.ExternalHost, + Mode: authentikapi.PROXYMODE_FORWARD_SINGLE.Ptr(), + } + resp, r, err := c.authentik.ProvidersApi.ProvidersProxyCreate(ctx).ProxyProviderRequest(*proxyProviderRequest).Execute() + if err != nil { + return fmt.Errorf("error when calling `ProvidersAPI.ProvidersProxyCreate`: %w with response %v", err, r) + } + pp.Status.PK = strconv.Itoa(int(resp.Pk)) + err = c.updateProxyProviderStatus(ctx, pp) + if err != nil { + return fmt.Errorf("error updating ProxyProvider status: %v", err) + } + } + return nil } @@ -211,3 +264,10 @@ func (c *Controller) handleObject(obj interface{}) { } } } + +func (c *Controller) updateProxyProviderStatus(ctx context.Context, pp *v1.ProxyProvider) error { + ppCopy := pp.DeepCopy() + ppCopy.Status.PK = pp.Status.PK + _, err := c.proxyProviderClientset.ProxyproviderV1().ProxyProviders(pp.Namespace).UpdateStatus(ctx, ppCopy, metav1.UpdateOptions{FieldManager: FieldManager}) + return err +} diff --git a/go.mod b/go.mod index 43b39a9..b6e9adc 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,13 @@ go 1.26.3 godebug default=go1.26 require ( + goauthentik.io/api/v3 v3.2026020.16 golang.org/x/time v0.15.0 k8s.io/api v0.0.0-20260509204538-0dfb117cc6ec k8s.io/apimachinery v0.0.0-20260513183604-f9371b815e42 k8s.io/client-go v0.0.0-20260509205101-ca52b81a2940 - k8s.io/code-generator v0.0.0-20260509210052-5595d1310975 k8s.io/klog/v2 v2.140.0 k8s.io/kube-openapi v0.0.0-20260511211612-da4e56fe5676 - k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 sigs.k8s.io/structured-merge-diff/v6 v6.4.0 ) @@ -46,18 +45,15 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.35.0 // indirect golang.org/x/net v0.53.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.43.0 // indirect golang.org/x/term v0.42.0 // indirect golang.org/x/text v0.36.0 // indirect - golang.org/x/tools v0.44.0 // indirect google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - k8s.io/gengo/v2 v2.0.0-20260408192533-25e2208e0dc3 // indirect + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect diff --git a/go.sum b/go.sum index 24b1ea4..8e707e6 100644 --- a/go.sum +++ b/go.sum @@ -84,14 +84,12 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +goauthentik.io/api/v3 v3.2026020.16 h1:sEqcVRXYSJTYaSdU5PzSEdFUWDqCONm5BeL62F5k+58= +goauthentik.io/api/v3 v3.2026020.16/go.mod h1:82lqAz4jxzl6Cg0YDbhNtvvTG2rm6605ZhdJFnbbsl8= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= @@ -100,12 +98,6 @@ golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= -golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= -golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= -golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= -golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -119,21 +111,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.0.0-20260509204538-0dfb117cc6ec h1:xf12Yh3ltN4fnNyP0CyyM0TwNVnZDfLJjV3+bf9fPFY= k8s.io/api v0.0.0-20260509204538-0dfb117cc6ec/go.mod h1:C+fcNlNQ9TcKHspN+DD7UybdfnjDAGyBjfCd6W7ogbY= -k8s.io/apimachinery v0.0.0-20260509204146-64dfe1db2af5 h1:k2HBxRBq6w2QCj14oAhBosjMqqgNlj4dmLXFj8f1A+8= -k8s.io/apimachinery v0.0.0-20260509204146-64dfe1db2af5/go.mod h1:37ALVDWo0LgW74Y9rAdewmZo20SVCGGH34806wUMrko= k8s.io/apimachinery v0.0.0-20260513183604-f9371b815e42 h1:rWdGOTor3z0WSyZcRl9ms4dn9Cw9CqmNBqXuf2z0k1k= k8s.io/apimachinery v0.0.0-20260513183604-f9371b815e42/go.mod h1:hiubQ6UTHIdr0bS8ExXOJEywFVOoudnldm/l/NiNVlA= k8s.io/client-go v0.0.0-20260509205101-ca52b81a2940 h1:n5t5Jx3VpLdiAGxIvIHsZDmsExtZVwghUPLM3wFi6Go= k8s.io/client-go v0.0.0-20260509205101-ca52b81a2940/go.mod h1:0e7OLwg7kdXISVFwn7ishFdvxfVgi7wsqHqsQPHl61w= -k8s.io/code-generator v0.0.0-20260509210052-5595d1310975 h1:hDrusFgTzvqcDJ7p13A9Eid4i8Y9uNSs/67lniaYHwM= -k8s.io/code-generator v0.0.0-20260509210052-5595d1310975/go.mod h1:mQXg0n0EeF4oU8aTwm9mzwoyAKqVRmUb9wLhjHnRq3I= -k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ= -k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= -k8s.io/gengo/v2 v2.0.0-20260408192533-25e2208e0dc3/go.mod h1:yvyl3l9E+UxlqOMUULdKTAYB0rEhsmjr7+2Vb/1pCSo= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/kube-openapi v0.0.0-20260509150519-312035bf509b h1:WrpNVPKkCaOO9h77E1P2HLnhWDQxrxzpf2jfsM8WevY= -k8s.io/kube-openapi v0.0.0-20260509150519-312035bf509b/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY= k8s.io/kube-openapi v0.0.0-20260511211612-da4e56fe5676 h1:ahjrVu/DBcaAhw/GcblfaOvvQ2wi8kqXWvn62nud3UU= k8s.io/kube-openapi v0.0.0-20260511211612-da4e56fe5676/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY= k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= @@ -142,8 +125,6 @@ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5E sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= -sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/structured-merge-diff/v6 v6.4.0 h1:qmp2e3ZfFi1/jJbDGpD4mt3wyp6PE1NfKHCYLqgNQJo= sigs.k8s.io/structured-merge-diff/v6 v6.4.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= diff --git a/main.go b/main.go index 58e139e..7351095 100644 --- a/main.go +++ b/main.go @@ -17,10 +17,14 @@ limitations under the License. package main import ( + "errors" "flag" + "net/url" + "os" "time" "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/signals" + authentikapi "goauthentik.io/api/v3" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" @@ -58,23 +62,29 @@ func main() { klog.FlushAndExit(klog.ExitFlushTimeout, 1) } - operatorClient, err := clientset.NewForConfig(cfg) + proxyProviderClient, err := clientset.NewForConfig(cfg) if err != nil { - logger.Error(err, "Error building kubernetes clientset") + 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) } kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30) - operatorInformerFactory := informers.NewSharedInformerFactory(operatorClient, time.Second*30) + proxyProviderInformerFactory := informers.NewSharedInformerFactory(proxyProviderClient, time.Second*30) - controller := NewController(ctx, kubeClient, operatorClient, + controller := NewController(ctx, kubeClient, proxyProviderClient, authentikClient, kubeInformerFactory.Apps().V1().Deployments(), - operatorInformerFactory.Proxyprovider().V1().ProxyProviders()) + proxyProviderInformerFactory.Proxyprovider().V1().ProxyProviders()) // 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. kubeInformerFactory.Start(ctx.Done()) - operatorInformerFactory.Start(ctx.Done()) + proxyProviderInformerFactory.Start(ctx.Done()) if err = controller.Run(ctx, 2); err != nil { logger.Error(err, "Error running controller") @@ -86,3 +96,27 @@ 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 +} diff --git a/pkg/apis/proxyprovider/v1/types.go b/pkg/apis/proxyprovider/v1/types.go index b0a4afa..c662c69 100644 --- a/pkg/apis/proxyprovider/v1/types.go +++ b/pkg/apis/proxyprovider/v1/types.go @@ -21,6 +21,7 @@ import ( ) // +genclient +// +kubebuilder:subresource:status // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type ProxyProvider struct {