From c75bbbdc9394a21ad03f12f79b7a471cc2199b43 Mon Sep 17 00:00:00 2001 From: Gianluca Mardente Date: Sun, 6 Sep 2026 17:40:07 +0200 Subject: [PATCH] chore: advance libsveltos add a sanity to verify oidc --- .github/workflows/main.yaml | 13 +++ Makefile | 42 +++++++++ api/v1beta1/zz_generated.deepcopy.go | 5 +- controllers/handlers_utils.go | 2 +- go.mod | 2 +- go.sum | 4 +- test/fv/oidc_workload_identity_test.go | 112 +++++++++++++++++++++++ test/oidc/clusterclass-patch.json | 69 ++++++++++++++ test/oidc/dex.yaml | 120 +++++++++++++++++++++++++ test/oidc/sveltoscluster.yaml | 54 +++++++++++ test/oidc/workload-rbac.yaml | 16 ++++ 11 files changed, 433 insertions(+), 6 deletions(-) create mode 100644 test/fv/oidc_workload_identity_test.go create mode 100644 test/oidc/clusterclass-patch.json create mode 100644 test/oidc/dex.yaml create mode 100644 test/oidc/sveltoscluster.yaml create mode 100644 test/oidc/workload-rbac.yaml diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 9037ee66..0b3663c4 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -93,6 +93,19 @@ jobs: run: make create-cluster fv-agentless env: FV: true + FV_OIDC: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Set up Go + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version: 1.26.6 + - name: fv-oidc + run: make create-cluster create-cluster-oidc fv-oidc + env: + FV: true FV_PULLMODE: runs-on: ubuntu-latest steps: diff --git a/Makefile b/Makefile index ecc6c2e0..77afc829 100644 --- a/Makefile +++ b/Makefile @@ -222,6 +222,12 @@ TIMEOUT ?= 10m WORKLOAD_CLUSTER_YAML ?= test/$(WORKLOAD_CLUSTER_NAME).yaml NUM_NODES ?= 8 +# Used by create-cluster-oidc / fv-oidc. OIDC_CLIENT_SECRET is a test fixture, not a +# real credential. +DEX_NODE_PORT ?= 30556 +OIDC_CLIENT_ID ?= sveltos +OIDC_CLIENT_SECRET ?= sveltos-fv-secret + .PHONY: quickstart quickstart: ## start kind cluster; install all cluster api components; create a capi cluster; install projectsveltos $(MAKE) create-control-cluster @@ -285,6 +291,42 @@ fv-agentless: $(KUBECTL) $(GINKGO) ## Run Sveltos Controller tests using existin $(KUBECTL) wait --for=condition=Available deployment/addon-controller -n projectsveltos --timeout=$(TIMEOUT) cd test/fv; $(GINKGO) -nodes $(NUM_NODES) --label-filter='FV' --v --trace --randomize-all +.PHONY: create-cluster-oidc +create-cluster-oidc: $(KUBECTL) $(ENVSUBST) ## Deploy Dex and register the workload cluster as an OIDC SveltosCluster. Run once, right after create-cluster (not safe to re-run against the same cluster: it appends a patch to the ClusterClass). + @echo "Deploying Dex" + set -euo pipefail; \ + DEX_NODE_IP=$$(docker inspect $(CONTROL_CLUSTER_NAME)-control-plane --format '{{.NetworkSettings.Networks.kind.IPAddress}}'); \ + DEX_ISSUER_URL="https://$$DEX_NODE_IP:$(DEX_NODE_PORT)/dex"; \ + export DEX_NODE_IP DEX_NODE_PORT="$(DEX_NODE_PORT)" DEX_ISSUER_URL OIDC_CLIENT_ID="$(OIDC_CLIENT_ID)" OIDC_CLIENT_SECRET="$(OIDC_CLIENT_SECRET)"; \ + $(ENVSUBST) < test/oidc/dex.yaml | $(KUBECTL) apply -f -; \ + $(KUBECTL) wait --for=condition=Ready certificate/dex-tls -n dex --timeout=60s; \ + $(KUBECTL) rollout status deployment/dex -n dex --timeout=90s; \ + \ + echo "Trusting Dex as an OIDC issuer on the workload cluster's kube-apiserver"; \ + DEX_CA_B64=$$($(KUBECTL) get secret dex-tls -n dex -o jsonpath='{.data.tls\.crt}'); \ + export DEX_CA_B64; \ + $(ENVSUBST) < test/oidc/clusterclass-patch.json > test/oidc/clusterclass-patch.json.tmp; \ + $(KUBECTL) patch clusterclass quick-start -n default --type json --patch-file test/oidc/clusterclass-patch.json.tmp; \ + rm -f test/oidc/clusterclass-patch.json.tmp; \ + \ + echo "Waiting for the workload cluster's control plane to roll out with the OIDC trust"; \ + KCP=$$($(KUBECTL) get kubeadmcontrolplane -n default -l cluster.x-k8s.io/cluster-name=$(WORKLOAD_CLUSTER_NAME) -o jsonpath='{.items[0].metadata.name}'); \ + sleep 15; \ + $(KUBECTL) wait kubeadmcontrolplane $$KCP -n default --for='condition=RollingOut=False' --timeout=$(TIMEOUT); \ + \ + echo "Granting the OIDC identity cluster-admin on the workload cluster"; \ + OIDC_CLIENT_ID="$(OIDC_CLIENT_ID)" $(ENVSUBST) < test/oidc/workload-rbac.yaml | $(KUBECTL) --kubeconfig=./test/fv/workload_kubeconfig apply -f -; \ + \ + echo "Registering the workload cluster as an OIDC SveltosCluster"; \ + WORKLOAD_ENDPOINT="https://$$($(KUBECTL) get cluster $(WORKLOAD_CLUSTER_NAME) -n default -o jsonpath='{.spec.controlPlaneEndpoint.host}:{.spec.controlPlaneEndpoint.port}')"; \ + WORKLOAD_APISERVER_CA_B64=$$($(KUBECTL) get secret $(WORKLOAD_CLUSTER_NAME)-ca -n default -o jsonpath='{.data.tls\.crt}'); \ + export WORKLOAD_ENDPOINT WORKLOAD_APISERVER_CA_B64; \ + $(ENVSUBST) < test/oidc/sveltoscluster.yaml | $(KUBECTL) apply -f - + +.PHONY: fv-oidc +fv-oidc: $(KUBECTL) $(GINKGO) ## Run the OIDC workload identity FV test. Run after create-cluster and create-cluster-oidc. + cd test/fv; $(GINKGO) -nodes 1 --label-filter='OIDC' --v --trace + .PHONY: create-cluster-infra create-cluster-infra: $(KIND) $(CLUSTERCTL) $(KUBECTL) ## Create cluster infrastructure without deploying Sveltos $(MAKE) create-control-cluster diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index c6e84b84..ae5338bc 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -21,11 +21,12 @@ limitations under the License. package v1beta1 import ( - apiv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" + + apiv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/controllers/handlers_utils.go b/controllers/handlers_utils.go index 9cfc0999..93132c73 100644 --- a/controllers/handlers_utils.go +++ b/controllers/handlers_utils.go @@ -225,7 +225,7 @@ func instantiateTemplate(referencedObject client.Object, logger logr.Logger) boo annotations := referencedObject.GetAnnotations() if annotations != nil { if _, ok := annotations[libsveltosv1beta1.PolicyTemplateAnnotation]; ok { - logger.V(logs.LogInfo).Info(fmt.Sprintf("referencedObject %s %s/%s is a template", + logger.V(logs.LogDebug).Info(fmt.Sprintf("referencedObject %s %s/%s is a template", referencedObject.GetObjectKind().GroupVersionKind().Kind, referencedObject.GetNamespace(), referencedObject.GetName())) return true } diff --git a/go.mod b/go.mod index 8898c707..4af6eab7 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/onsi/gomega v1.43.0 github.com/opencontainers/image-spec v1.1.1 github.com/pkg/errors v0.9.1 - github.com/projectsveltos/libsveltos v1.14.1-0.20260905063009-a8a9f4f0cfd4 + github.com/projectsveltos/libsveltos v1.14.1-0.20260906152235-8d04320142da github.com/prometheus/client_golang v1.24.1 github.com/sigstore/cosign/v3 v3.1.3 github.com/sigstore/sigstore v1.10.9 diff --git a/go.sum b/go.sum index f03a1ab7..5e9f84fe 100644 --- a/go.sum +++ b/go.sum @@ -641,8 +641,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= -github.com/projectsveltos/libsveltos v1.14.1-0.20260905063009-a8a9f4f0cfd4 h1:A601K466dqM3yWv+U+BtFGPWHjbyAUo7p0iylNg+B74= -github.com/projectsveltos/libsveltos v1.14.1-0.20260905063009-a8a9f4f0cfd4/go.mod h1:U6iGj5KoC/PcTD2vh3XU6gy7g11suThT6sZSEpmLEkU= +github.com/projectsveltos/libsveltos v1.14.1-0.20260906152235-8d04320142da h1:UZpRfT1NHsnpojbGdhP2fuca+iqZYbHIqAw7qbOmneY= +github.com/projectsveltos/libsveltos v1.14.1-0.20260906152235-8d04320142da/go.mod h1:U6iGj5KoC/PcTD2vh3XU6gy7g11suThT6sZSEpmLEkU= github.com/projectsveltos/lua-utils/glua-json v0.0.0-20251212200258-2b3cdcb7c0f5 h1:khnc+994UszxZYu69J+R5FKiLA/Nk1JQj0EYAkwTWz0= github.com/projectsveltos/lua-utils/glua-json v0.0.0-20251212200258-2b3cdcb7c0f5/go.mod h1:yVL8KQFa9tmcxgwl9nwIMtKgtmIVC1zaFRSCfOwYvPY= github.com/projectsveltos/lua-utils/glua-runes v0.0.0-20251212200258-2b3cdcb7c0f5 h1:YbsebwRwTRhV8QacvEAdFqxcxHdeu7JTVtsBovbkgos= diff --git a/test/fv/oidc_workload_identity_test.go b/test/fv/oidc_workload_identity_test.go new file mode 100644 index 00000000..5ecc3097 --- /dev/null +++ b/test/fv/oidc_workload_identity_test.go @@ -0,0 +1,112 @@ +/* +Copyright 2026. projectsveltos.io. All rights reserved. + +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 fv_test + +import ( + "context" + "fmt" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + configv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1" + "github.com/projectsveltos/addon-controller/lib/clusterops" + libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" +) + +// The SveltosCluster and Secrets this test targets are created by `make create-cluster-oidc`, +// against the same physical workload cluster `make create-cluster` provisions: Dex is deployed +// as the IdP, the workload cluster's kube-apiserver is configured to trust it, and the cluster +// is registered a second time as a plain SveltosCluster using OIDC workload identity instead of +// a kubeconfig Secret, mirroring how an on-prem cluster fronted by an enterprise IdP (Dex, +// Keycloak, Okta) would be onboarded. +const ( + oidcWorkloadClusterNamespace = "oidc-test" + oidcWorkloadClusterName = "oidc-workload" +) + +var _ = Describe("OIDC workload identity", Serial, func() { + const namePrefix = "oidc-" + + It("deploys a ClusterProfile to a cluster registered via OIDC workload identity", Label("OIDC"), func() { + Byf("Verifying SveltosCluster %s/%s is ready", oidcWorkloadClusterNamespace, oidcWorkloadClusterName) + Eventually(func() bool { + sveltosCluster := &libsveltosv1beta1.SveltosCluster{} + err := k8sClient.Get(context.TODO(), + types.NamespacedName{Namespace: oidcWorkloadClusterNamespace, Name: oidcWorkloadClusterName}, + sveltosCluster) + return err == nil && sveltosCluster.Status.Ready + }, timeout, pollingInterval).Should(BeTrue()) + + devNamespaceName := randomString() + Byf("Create a ConfigMap with a Namespace to deploy") + configMap := createConfigMapWithPolicy(defaultNamespace, namePrefix+randomString(), + fmt.Sprintf(devNamespace, devNamespaceName)) + Expect(k8sClient.Create(context.TODO(), configMap)).To(Succeed()) + + Byf("Create a ClusterProfile targeting the OIDC SveltosCluster directly") + clusterProfile := &configv1beta1.ClusterProfile{ + ObjectMeta: metav1.ObjectMeta{ + Name: namePrefix + randomString(), + }, + Spec: configv1beta1.Spec{ + ClusterRefs: []corev1.ObjectReference{ + { + APIVersion: libsveltosv1beta1.GroupVersion.String(), + Kind: libsveltosv1beta1.SveltosClusterKind, + Namespace: oidcWorkloadClusterNamespace, + Name: oidcWorkloadClusterName, + }, + }, + SyncMode: configv1beta1.SyncModeContinuous, + PolicyRefs: []configv1beta1.PolicyRef{ + { + Kind: string(libsveltosv1beta1.ConfigMapReferencedResourceKind), + Namespace: configMap.Namespace, + Name: configMap.Name, + }, + }, + }, + } + Expect(k8sClient.Create(context.TODO(), clusterProfile)).To(Succeed()) + + clusterSummary := verifyClusterSummary(clusterops.ClusterProfileLabelName, clusterProfile.Name, + &clusterProfile.Spec, oidcWorkloadClusterNamespace, oidcWorkloadClusterName, + string(libsveltosv1beta1.ClusterTypeSveltos)) + + Byf("Verifying ClusterSummary %s status is set to Provisioned for Resources feature", clusterSummary.Name) + verifyFeatureStatusIsProvisioned(oidcWorkloadClusterNamespace, clusterSummary.Name, libsveltosv1beta1.FeatureResources) + + Byf("Getting client to access the workload cluster") + workloadClient, err := getKindWorkloadClusterKubeconfig() + Expect(err).To(BeNil()) + Expect(workloadClient).ToNot(BeNil()) + + Byf("Verifying Namespace %s was created in the workload cluster via the OIDC access token", + devNamespaceName) + Eventually(func() error { + currentNamespace := &corev1.Namespace{} + return workloadClient.Get(context.TODO(), types.NamespacedName{Name: devNamespaceName}, currentNamespace) + }, timeout, pollingInterval).Should(BeNil()) + + deleteClusterProfile(clusterProfile) + }) +}) diff --git a/test/oidc/clusterclass-patch.json b/test/oidc/clusterclass-patch.json new file mode 100644 index 00000000..e5b903d9 --- /dev/null +++ b/test/oidc/clusterclass-patch.json @@ -0,0 +1,69 @@ +[ + { + "op": "add", + "path": "/spec/patches/-", + "value": { + "name": "dexOIDC", + "description": "Trusts the FV Dex instance as an OIDC issuer, for the OIDC workload identity FV test.", + "definitions": [ + { + "selector": { + "apiVersion": "controlplane.cluster.x-k8s.io/v1beta2", + "kind": "KubeadmControlPlaneTemplate", + "matchResources": { + "controlPlane": true + } + }, + "jsonPatches": [ + { + "op": "add", + "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/-", + "value": {"name": "oidc-issuer-url", "value": "${DEX_ISSUER_URL}"} + }, + { + "op": "add", + "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/-", + "value": {"name": "oidc-client-id", "value": "${OIDC_CLIENT_ID}"} + }, + { + "op": "add", + "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/-", + "value": {"name": "oidc-username-claim", "value": "aud"} + }, + { + "op": "add", + "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/-", + "value": {"name": "oidc-username-prefix", "value": "-"} + }, + { + "op": "add", + "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/-", + "value": {"name": "oidc-ca-file", "value": "/etc/kubernetes/pki/dex-ca.crt"} + }, + { + "op": "add", + "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes/-", + "value": { + "name": "dex-ca", + "hostPath": "/etc/kubernetes/pki/dex-ca.crt", + "mountPath": "/etc/kubernetes/pki/dex-ca.crt", + "pathType": "File", + "readOnly": true + } + }, + { + "op": "add", + "path": "/spec/template/spec/kubeadmConfigSpec/files/-", + "value": { + "path": "/etc/kubernetes/pki/dex-ca.crt", + "permissions": "0644", + "encoding": "base64", + "content": "${DEX_CA_B64}" + } + } + ] + } + ] + } + } +] diff --git a/test/oidc/dex.yaml b/test/oidc/dex.yaml new file mode 100644 index 00000000..79932421 --- /dev/null +++ b/test/oidc/dex.yaml @@ -0,0 +1,120 @@ +# Dex, used by the OIDC workload identity FV test as a standalone IdP. Deployed into the +# management cluster and reached by both addon-controller (in-cluster DNS) and the FV +# workload cluster's kube-apiserver (over the shared kind Docker network, hence the NodePort +# and the IP-based issuer URL instead of a DNS name). +# +# ${DEX_NODE_IP}, ${DEX_NODE_PORT}, ${DEX_ISSUER_URL}, ${OIDC_CLIENT_ID} and +# ${OIDC_CLIENT_SECRET} are filled in by `make create-cluster-oidc` via envsubst. +apiVersion: v1 +kind: Namespace +metadata: + name: dex +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: dex-selfsigned + namespace: dex +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: dex-tls + namespace: dex +spec: + secretName: dex-tls + isCA: true + commonName: dex + ipAddresses: + - ${DEX_NODE_IP} + dnsNames: + - dex.dex.svc.cluster.local + - dex.dex.svc + issuerRef: + name: dex-selfsigned + kind: Issuer +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: dex-config + namespace: dex +data: + config.yaml: | + issuer: ${DEX_ISSUER_URL} + storage: + type: memory + web: + https: 0.0.0.0:5556 + tlsCert: /etc/dex/tls/tls.crt + tlsKey: /etc/dex/tls/tls.key + oauth2: + grantTypes: + - "client_credentials" + staticClients: + - id: ${OIDC_CLIENT_ID} + secret: ${OIDC_CLIENT_SECRET} + name: Sveltos FV + # client_credentials tokens carry no user identity, but Dex still requires at least + # one connector configured before it will start. + enablePasswordDB: true + staticPasswords: + - email: "admin@example.com" + hash: "$$2y$$10$$34AKFkjUplqWVEJ8u6tdieXAqWI642btGT2hFgd6MCdt.cf/ZOeBC" + username: admin + userID: 08a8684b-db88-4b73-90a9-3cd1661f5466 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dex + namespace: dex +spec: + replicas: 1 + selector: + matchLabels: + app: dex + template: + metadata: + labels: + app: dex + spec: + containers: + - name: dex + image: ghcr.io/dexidp/dex:latest + command: ["/usr/local/bin/dex", "serve", "/etc/dex/cfg/config.yaml"] + env: + - name: DEX_CLIENT_CREDENTIAL_GRANT_ENABLED_BY_DEFAULT + value: "true" + ports: + - name: https + containerPort: 5556 + volumeMounts: + - name: config + mountPath: /etc/dex/cfg + - name: tls + mountPath: /etc/dex/tls + volumes: + - name: config + configMap: + name: dex-config + - name: tls + secret: + secretName: dex-tls +--- +apiVersion: v1 +kind: Service +metadata: + name: dex + namespace: dex +spec: + type: NodePort + selector: + app: dex + ports: + - name: https + port: 5556 + targetPort: 5556 + nodePort: ${DEX_NODE_PORT} diff --git a/test/oidc/sveltoscluster.yaml b/test/oidc/sveltoscluster.yaml new file mode 100644 index 00000000..02dfd8fa --- /dev/null +++ b/test/oidc/sveltoscluster.yaml @@ -0,0 +1,54 @@ +# The SveltosCluster the OIDC FV test targets: same physical cluster as +# test/clusterapi-workload.yaml, registered separately with OIDC workload identity +# instead of a kubeconfig Secret, exactly like a real on-prem/self-managed customer +# cluster fronted by an enterprise IdP (Dex, Keycloak, Okta) would be. +apiVersion: v1 +kind: Namespace +metadata: + name: oidc-test +--- +apiVersion: v1 +kind: Secret +metadata: + name: oidc-workload-creds + namespace: oidc-test +type: Opaque +stringData: + client_id: ${OIDC_CLIENT_ID} + client_secret: ${OIDC_CLIENT_SECRET} +--- +apiVersion: v1 +kind: Secret +metadata: + name: oidc-idp-ca + namespace: oidc-test +type: Opaque +data: + ca.crt: ${DEX_CA_B64} +--- +apiVersion: v1 +kind: Secret +metadata: + name: oidc-workload-apiserver-ca + namespace: oidc-test +type: Opaque +data: + ca.crt: ${WORKLOAD_APISERVER_CA_B64} +--- +apiVersion: lib.projectsveltos.io/v1beta1 +kind: SveltosCluster +metadata: + name: oidc-workload + namespace: oidc-test +spec: + workloadIdentity: + provider: OIDC + endpoint: ${WORKLOAD_ENDPOINT} + caSecretRef: + name: oidc-workload-apiserver-ca + oidc: + tokenURL: ${DEX_ISSUER_URL}/token + secretRef: + name: oidc-workload-creds + caSecretRef: + name: oidc-idp-ca diff --git a/test/oidc/workload-rbac.yaml b/test/oidc/workload-rbac.yaml new file mode 100644 index 00000000..37370aba --- /dev/null +++ b/test/oidc/workload-rbac.yaml @@ -0,0 +1,16 @@ +# Grants the OIDC identity Sveltos authenticates as (the client_id itself, since the +# apiserver is configured with --oidc-username-claim=aud --oidc-username-prefix=-) the +# permissions Sveltos needs in the managed cluster. Applied with +# --kubeconfig test/fv/workload_kubeconfig, i.e. against the workload cluster itself. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: sveltos-oidc-workload-identity +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: User + name: "${OIDC_CLIENT_ID}" + apiGroup: rbac.authorization.k8s.io