From 32bcb2fa76ab7430609741948b6cb8473fa968bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 10 Sep 2024 13:00:48 +0200 Subject: [PATCH 01/36] WiP draft of boostraping OIDC fsm --- api/v1/runtime_types.go | 1 + .../runtime/fsm/runtime_fsm_configure_oidc.go | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go diff --git a/api/v1/runtime_types.go b/api/v1/runtime_types.go index dbbc7c83..e4bd0446 100644 --- a/api/v1/runtime_types.go +++ b/api/v1/runtime_types.go @@ -64,6 +64,7 @@ const ( ConditionTypeRuntimeProvisioned RuntimeConditionType = "Provisioned" ConditionTypeRuntimeProvisionedDryRun RuntimeConditionType = "ProvisionedDryRun" ConditionTypeRuntimeKubeconfigReady RuntimeConditionType = "KubeconfigReady" + ConditionTypeOidcConfigured RuntimeConditionType = "OidcConfigured" ConditionTypeRuntimeConfigured RuntimeConditionType = "Configured" ConditionTypeAuditLogConfigured RuntimeConditionType = "AuditlogConfigured" ConditionTypeRuntimeDeprovisioned RuntimeConditionType = "Deprovisioned" diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go new file mode 100644 index 00000000..81ae5837 --- /dev/null +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -0,0 +1,36 @@ +package fsm + +import ( + "context" + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + ctrl "sigs.k8s.io/controller-runtime" +) + +func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { + m.log.Info("Configure OIDC state") + + //TODO: 0. plug in to the state machine without actually doing anything + //TODO: 2/3. check condition if going into this state is necessary + //TODO: 2/3. remove existing "additionalOidcs" from the Shoot spec + //TODO: 3.5 revisit the default OIDC requirements, implementation drafted in https://github.com/kyma-project/infrastructure-manager/commit/32f016d38dafdee0ff1f9e772183825c703f046d + //TODO: 1. recreate "additionalOidcs" in the Shoot spec + //TODO: 4. create OpenID resource on the shoot + //TODO: 4. extract rest client to a separate interface + //TODO: 5. unit test the function + // create OIDCConnect CR in shoot + + //s.instance.UpdateStatePending(imv1.ConditionTypeRuntimeKubeconfigReady, imv1.ConditionReasonGardenerCRCreated, "Unknown", "Gardener Cluster CR created, waiting for readiness") + //return updateStatusAndRequeueAfter(controlPlaneRequeueDuration) + + // wait section - is it needed? + + s.instance.UpdateStateReady( + imv1.ConditionTypeOidcConfigured, + imv1.ConditionReasonConfigurationCompleted, + "OIDC configuration completed", + ) + + m.log.Info("OIDC has been configured", "Name", s.shoot.Name) + + return updateStatusAndStop() +} From a8d0e36406450f8205cc2306b4faa137835ec287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Thu, 12 Sep 2024 16:03:58 +0200 Subject: [PATCH 02/36] fixes logger panics --- .../runtime/fsm/runtime_fsm_configure_auditlog.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go index d03cb5d6..c06681f9 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go @@ -2,6 +2,7 @@ package fsm import ( "context" + "strconv" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" @@ -26,11 +27,13 @@ func sFnConfigureAuditLog(ctx context.Context, m *fsm, s *systemState) (stateFn, return updateStatusAndRequeueAfter(gardenerRequeueDuration) } + auditLogMandatoryString := strconv.FormatBool(m.RCCfg.AuditLogMandatory) + if err != nil { //nolint:nestif errorMessage := err.Error() if errors.Is(err, auditlogging.ErrMissingMapping) { if m.RCCfg.AuditLogMandatory { - m.log.Error(err, "Failed to configure Audit Log, missing region mapping for this shoot", "AuditLogMandatory", m.RCCfg.AuditLogMandatory, "providerType", s.shoot.Spec.Provider.Type, "region", s.shoot.Spec.Region) + m.log.Error(err, "AuditLogMandatory", auditLogMandatoryString, "providerType", s.shoot.Spec.Provider.Type, "region", s.shoot.Spec.Region) s.instance.UpdateStatePending( imv1.ConditionTypeAuditLogConfigured, imv1.ConditionReasonAuditLogMissingRegionMapping, @@ -38,7 +41,7 @@ func sFnConfigureAuditLog(ctx context.Context, m *fsm, s *systemState) (stateFn, errorMessage, ) } else { - m.log.Info(errorMessage, "Audit Log was not configured, missing region mapping for this shoot.", "AuditLogMandatory", m.RCCfg.AuditLogMandatory, "providerType", s.shoot.Spec.Provider.Type, "region", s.shoot.Spec.Region) + m.log.Info(errorMessage, "AuditLogMandatory", auditLogMandatoryString, "providerType", s.shoot.Spec.Provider.Type, "region", s.shoot.Spec.Region) s.instance.UpdateStateReady( imv1.ConditionTypeAuditLogConfigured, imv1.ConditionReasonAuditLogMissingRegionMapping, @@ -46,14 +49,14 @@ func sFnConfigureAuditLog(ctx context.Context, m *fsm, s *systemState) (stateFn, } } else { if m.RCCfg.AuditLogMandatory { - m.log.Error(err, "Failed to configure Audit Log", "AuditLogMandatory", m.RCCfg.AuditLogMandatory) + m.log.Error(err, "AuditLogMandatory", auditLogMandatoryString) s.instance.UpdateStatePending( imv1.ConditionTypeAuditLogConfigured, imv1.ConditionReasonAuditLogError, "False", errorMessage) } else { - m.log.Info(errorMessage, "AuditLogMandatory", m.RCCfg.AuditLogMandatory) + m.log.Info(errorMessage, "AuditLogMandatory", auditLogMandatoryString) s.instance.UpdateStateReady( imv1.ConditionTypeAuditLogConfigured, imv1.ConditionReasonAuditLogError, From db4a7164880a4ab29cdfd47f0d08dc7658c19d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Fri, 13 Sep 2024 15:04:51 +0200 Subject: [PATCH 03/36] creating OpenIDConnect on shoot with fake data --- cmd/main.go | 14 +++- go.mod | 18 +++-- go.sum | 58 +++++++------ .../fsm/runtime_fsm_configure_auditlog.go | 2 +- .../runtime_fsm_configure_auditlog_test.go | 10 +-- .../runtime/fsm/runtime_fsm_configure_oidc.go | 81 ++++++++++++++++--- 6 files changed, 127 insertions(+), 56 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 2f07e0a0..4715be7f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -26,6 +26,7 @@ import ( "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_apis "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1" + gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "github.com/go-playground/validator/v10" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" @@ -58,6 +59,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(infrastructuremanagerv1.AddToScheme(scheme)) utilruntime.Must(rbacv1.AddToScheme(scheme)) + utilruntime.Must(gardener_oidc.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -240,13 +242,19 @@ func initGardenerClients(kubeconfigPath string, namespace string) (client.Client return nil, nil, nil, err } - shootClient := gardenerClientSet.Shoots(namespace) - dynamicKubeconfigAPI := gardenerClient.SubResource("adminkubeconfig") - err = v1beta1.AddToScheme(gardenerClient.Scheme()) if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to register Gardener schema") } + + err = gardener_oidc.AddToScheme(gardenerClient.Scheme()) + if err != nil { + return nil, nil, nil, errors.Wrap(err, "failed to register Gardener schema") + } + + shootClient := gardenerClientSet.Shoots(namespace) + dynamicKubeconfigAPI := gardenerClient.SubResource("adminkubeconfig") + return gardenerClient, shootClient, dynamicKubeconfigAPI, nil } diff --git a/go.mod b/go.mod index 6d86e97c..6b195750 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/gardener/gardener-extension-provider-aws v1.56.1 github.com/gardener/gardener-extension-provider-gcp v1.37.0 github.com/gardener/gardener-extension-provider-openstack v1.41.0 + github.com/gardener/oidc-webhook-authenticator v0.31.0 github.com/go-logr/logr v1.4.2 github.com/go-playground/validator/v10 v10.22.0 github.com/onsi/ginkgo/v2 v2.20.2 @@ -25,16 +26,16 @@ require ( require ( github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -42,7 +43,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect @@ -58,9 +59,9 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.54.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -77,11 +78,12 @@ require ( gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.30.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/go.sum b/go.sum index b38f5b60..d9cce153 100644 --- a/go.sum +++ b/go.sum @@ -4,15 +4,14 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1 github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= +github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= @@ -29,16 +28,16 @@ github.com/gardener/gardener-extension-provider-gcp v1.37.0 h1:lRvh4syK7h8JzG9tV github.com/gardener/gardener-extension-provider-gcp v1.37.0/go.mod h1:/bDiE8xZz2vfP8u3A5Pr2IqVo0VX9keL5ntjExqhB5A= github.com/gardener/gardener-extension-provider-openstack v1.41.0 h1:AlzWuvw3DhkeXsQ6AnSHqp7tkWjtBZB+e7oCFpnFVBY= github.com/gardener/gardener-extension-provider-openstack v1.41.0/go.mod h1:DqpbvoN61U7qSzRFXv3UyRTLkopd2yIXhtPRLzfE2Ro= +github.com/gardener/oidc-webhook-authenticator v0.31.0 h1:M6blkT63Kgt1/J8YkyKjEJ6JBfuRZ+KKDL8gUJBhjII= +github.com/gardener/oidc-webhook-authenticator v0.31.0/go.mod h1:FrZLNLZOw12GwKmlVwpyFx1w02rOPwTP3mAoVUGRVR4= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -57,8 +56,8 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -82,11 +81,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= @@ -100,6 +96,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= @@ -110,25 +110,20 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= +github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -173,10 +168,13 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ= @@ -189,8 +187,8 @@ k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k= k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a h1:zD1uj3Jf+mD4zmA7W+goE5TxDkI7OGJjBNBzq5fJtLA= +k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw= diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go index c06681f9..11edf6b3 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go @@ -71,5 +71,5 @@ func sFnConfigureAuditLog(ctx context.Context, m *fsm, s *systemState) (stateFn, ) } - return updateStatusAndStop() + return switchState(sFnConfigureOidc) } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go index 925a93f2..1e2e637e 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go @@ -84,7 +84,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnUpdateStatus") + require.Contains(t, stateFn.name(), "sFnConfigureOidc") assert.Equal(t, v1.RuntimeStateReady, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -121,7 +121,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnUpdateStatus") + require.Contains(t, stateFn.name(), "sFnConfigureOidc") assert.Equal(t, v1.RuntimeStateFailed, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -158,7 +158,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnUpdateStatus") + require.Contains(t, stateFn.name(), "sFnConfigureOidc") assert.Equal(t, v1.RuntimeStateReady, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -195,7 +195,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnUpdateStatus") + require.Contains(t, stateFn.name(), "sFnConfigureOidc") assert.Equal(t, v1.RuntimeStateFailed, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -232,7 +232,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnUpdateStatus") + require.Contains(t, stateFn.name(), "sFnConfigureOidc") assert.Equal(t, v1.RuntimeStateReady, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 81ae5837..c5f0e67d 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -2,28 +2,54 @@ package fsm import ( "context" + authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" ) func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Configure OIDC state") - //TODO: 0. plug in to the state machine without actually doing anything - //TODO: 2/3. check condition if going into this state is necessary - //TODO: 2/3. remove existing "additionalOidcs" from the Shoot spec - //TODO: 3.5 revisit the default OIDC requirements, implementation drafted in https://github.com/kyma-project/infrastructure-manager/commit/32f016d38dafdee0ff1f9e772183825c703f046d - //TODO: 1. recreate "additionalOidcs" in the Shoot spec - //TODO: 4. create OpenID resource on the shoot - //TODO: 4. extract rest client to a separate interface - //TODO: 5. unit test the function - // create OIDCConnect CR in shoot + createOpenIDConnectResource(s.instance) + + //done 0. plug in to the state machine without actually doing anything + //TODO: - check condition if going into this state is necessary + // - extension enabled + // - OIDC config present + //TODO: - revisit the default OIDC requirements, implementation drafted in https://github.com/kyma-project/infrastructure-manager/commit/32f016d38dafdee0ff1f9e772183825c703f046d + //done - double check RBACs if they're in the right context (right client shoot vs gardener vs kcp ) + //done - create OpenID resource on the shoot + //TODO: - openID resource using non-fake values + //TODO: - (???) remove existing "additionalOidcs" from the Shoot spec + //TODO: - recreate "additionalOidcs" in the Shoot spec + //TODO: - extract rest client to a separate interface + //TODO: consider if we should stop in case of a failure + //TODO: the condition set should reflect framefrog condition strategy + //TODO: - unit test the function //s.instance.UpdateStatePending(imv1.ConditionTypeRuntimeKubeconfigReady, imv1.ConditionReasonGardenerCRCreated, "Unknown", "Gardener Cluster CR created, waiting for readiness") //return updateStatusAndRequeueAfter(controlPlaneRequeueDuration) // wait section - is it needed? + //prepare subresource client to request admin kubeconfig + srscClient := m.ShootClient.SubResource("adminkubeconfig") + shootAdminClient, err := GetShootClient(ctx, srscClient, s.shoot) + + if err != nil { + //TODO: handle error before updating status + return updateStatusAndStopWithError(err) + } + + openIDConnectResource := createOpenIDConnectResource(s.instance) + errResourceCreation := shootAdminClient.Create(ctx, openIDConnectResource) + + if errResourceCreation != nil { + m.log.Error(errResourceCreation, "Failed to create OpenIDConnect resource") + } + s.instance.UpdateStateReady( imv1.ConditionTypeOidcConfigured, imv1.ConditionReasonConfigurationCompleted, @@ -34,3 +60,40 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStop() } + +func createOpenIDConnectResource(runtime imv1.Runtime) *authenticationv1alpha1.OpenIDConnect { + //additionalOidcConfig := (*runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig)[0] + + //cr := &authenticationv1alpha1.OpenIDConnect{ + // Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ + // IssuerURL: *additionalOidcConfig.IssuerURL, + // ClientID: *additionalOidcConfig.ClientID, + // UsernameClaim: additionalOidcConfig.UsernameClaim, + // UsernamePrefix: additionalOidcConfig.UsernamePrefix, + // GroupsClaim: additionalOidcConfig.GroupsClaim, + // GroupsPrefix: additionalOidcConfig.GroupsPrefix, + // RequiredClaims: additionalOidcConfig.RequiredClaims, + // }, + //} + + cr := &authenticationv1alpha1.OpenIDConnect{ + TypeMeta: metav1.TypeMeta{ + Kind: "OpenIDConnect", + APIVersion: "authentication.gardener.cloud/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-oidc", + }, + Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ + IssuerURL: "https://token.actions.githubusercontent.com", + ClientID: "my-kubernetes-cluster", + UsernameClaim: ptr.To("sub"), + UsernamePrefix: ptr.To("actions-oidc:"), + GroupsPrefix: ptr.To("deploy-kubernetes"), + GroupsClaim: ptr.To("myOrg/myRepo"), + RequiredClaims: map[string]string{}, + }, + } + + return cr +} From c034a7ff1d882f4521506c57091fd0d8d1c5a2f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Fri, 13 Sep 2024 16:15:27 +0200 Subject: [PATCH 04/36] defaults additionalOidcs if not set and uses actual data in openidconnect resource --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 70 +++++++++++-------- .../runtime/fsm/runtime_fsm_patch_shoot.go | 13 ++++ 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index c5f0e67d..a58ec0eb 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -2,18 +2,17 @@ package fsm import ( "context" + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" ) func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Configure OIDC state") - createOpenIDConnectResource(s.instance) - //done 0. plug in to the state machine without actually doing anything //TODO: - check condition if going into this state is necessary // - extension enabled @@ -25,8 +24,9 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct //TODO: - (???) remove existing "additionalOidcs" from the Shoot spec //TODO: - recreate "additionalOidcs" in the Shoot spec //TODO: - extract rest client to a separate interface - //TODO: consider if we should stop in case of a failure - //TODO: the condition set should reflect framefrog condition strategy + //TODO: - consider if we should stop in case of a failure + //TODO: - possibly merge with CRB state + //TODO: - the condition set should reflect framefrog condition strategy //TODO: - unit test the function //s.instance.UpdateStatePending(imv1.ConditionTypeRuntimeKubeconfigReady, imv1.ConditionReasonGardenerCRCreated, "Unknown", "Gardener Cluster CR created, waiting for readiness") @@ -43,7 +43,14 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStopWithError(err) } - openIDConnectResource := createOpenIDConnectResource(s.instance) + if s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig == nil { + var error = errors.New("default OIDC configuration is not present") + m.log.Error(error, "default OIDC configuration is not present") + return updateStatusAndStopWithError(error) + } + + additionalOidcConfig := (*s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig)[0] + openIDConnectResource := createOpenIDConnectResource(additionalOidcConfig) errResourceCreation := shootAdminClient.Create(ctx, openIDConnectResource) if errResourceCreation != nil { @@ -61,39 +68,44 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStop() } -func createOpenIDConnectResource(runtime imv1.Runtime) *authenticationv1alpha1.OpenIDConnect { - //additionalOidcConfig := (*runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig)[0] - - //cr := &authenticationv1alpha1.OpenIDConnect{ - // Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ - // IssuerURL: *additionalOidcConfig.IssuerURL, - // ClientID: *additionalOidcConfig.ClientID, - // UsernameClaim: additionalOidcConfig.UsernameClaim, - // UsernamePrefix: additionalOidcConfig.UsernamePrefix, - // GroupsClaim: additionalOidcConfig.GroupsClaim, - // GroupsPrefix: additionalOidcConfig.GroupsPrefix, - // RequiredClaims: additionalOidcConfig.RequiredClaims, - // }, - //} - +func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig) *authenticationv1alpha1.OpenIDConnect { cr := &authenticationv1alpha1.OpenIDConnect{ TypeMeta: metav1.TypeMeta{ Kind: "OpenIDConnect", APIVersion: "authentication.gardener.cloud/v1alpha1", }, ObjectMeta: metav1.ObjectMeta{ - Name: "my-oidc", + Name: "to-be-changed", }, Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ - IssuerURL: "https://token.actions.githubusercontent.com", - ClientID: "my-kubernetes-cluster", - UsernameClaim: ptr.To("sub"), - UsernamePrefix: ptr.To("actions-oidc:"), - GroupsPrefix: ptr.To("deploy-kubernetes"), - GroupsClaim: ptr.To("myOrg/myRepo"), - RequiredClaims: map[string]string{}, + IssuerURL: *additionalOidcConfig.IssuerURL, + ClientID: *additionalOidcConfig.ClientID, + UsernameClaim: additionalOidcConfig.UsernameClaim, + UsernamePrefix: additionalOidcConfig.UsernamePrefix, + GroupsClaim: additionalOidcConfig.GroupsClaim, + GroupsPrefix: additionalOidcConfig.GroupsPrefix, + RequiredClaims: additionalOidcConfig.RequiredClaims, }, } + //cr := &authenticationv1alpha1.OpenIDConnect{ + // TypeMeta: metav1.TypeMeta{ + // Kind: "OpenIDConnect", + // APIVersion: "authentication.gardener.cloud/v1alpha1", + // }, + // ObjectMeta: metav1.ObjectMeta{ + // Name: "my-oidc", + // }, + // Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ + // IssuerURL: "https://token.actions.githubusercontent.com", + // ClientID: "my-kubernetes-cluster", + // UsernameClaim: ptr.To("sub"), + // UsernamePrefix: ptr.To("actions-oidc:"), + // GroupsPrefix: ptr.To("deploy-kubernetes"), + // GroupsClaim: ptr.To("myOrg/myRepo"), + // RequiredClaims: map[string]string{}, + // }, + //} + return cr } diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index fb8e1e15..ee9944b5 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -57,6 +57,7 @@ func convertShoot(instance *imv1.Runtime, cfg shoot.ConverterConfig) (gardener.S return gardener.Shoot{}, err } + defaultAdditionalOidcIfNotPresent(instance) converter := gardener_shoot.NewConverter(cfg) newShoot, err := converter.ToShoot(*instance) @@ -67,6 +68,18 @@ func convertShoot(instance *imv1.Runtime, cfg shoot.ConverterConfig) (gardener.S return newShoot, err } +func defaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime) { + oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig + additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig + + if nil == additionalOidcConfig { + additionalOidcConfig = &[]gardener.OIDCConfig{} + *additionalOidcConfig = append(*additionalOidcConfig, oidcConfig) + } + + runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig +} + // workaround func setObjectFields(shoot *gardener.Shoot) { shoot.Kind = "Shoot" From d52e212be73dfbadb4aa3bc888f52817030868cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Mon, 16 Sep 2024 10:36:30 +0200 Subject: [PATCH 05/36] creates OpenIdConnect CRs only if extension is enabled --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 91 ++++++++----------- 1 file changed, 37 insertions(+), 54 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index a58ec0eb..e3f3d37a 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -2,9 +2,11 @@ package fsm import ( "context" + "fmt" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -13,34 +15,9 @@ import ( func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Configure OIDC state") - //done 0. plug in to the state machine without actually doing anything - //TODO: - check condition if going into this state is necessary - // - extension enabled - // - OIDC config present - //TODO: - revisit the default OIDC requirements, implementation drafted in https://github.com/kyma-project/infrastructure-manager/commit/32f016d38dafdee0ff1f9e772183825c703f046d - //done - double check RBACs if they're in the right context (right client shoot vs gardener vs kcp ) - //done - create OpenID resource on the shoot - //TODO: - openID resource using non-fake values - //TODO: - (???) remove existing "additionalOidcs" from the Shoot spec - //TODO: - recreate "additionalOidcs" in the Shoot spec - //TODO: - extract rest client to a separate interface - //TODO: - consider if we should stop in case of a failure - //TODO: - possibly merge with CRB state - //TODO: - the condition set should reflect framefrog condition strategy - //TODO: - unit test the function - - //s.instance.UpdateStatePending(imv1.ConditionTypeRuntimeKubeconfigReady, imv1.ConditionReasonGardenerCRCreated, "Unknown", "Gardener Cluster CR created, waiting for readiness") - //return updateStatusAndRequeueAfter(controlPlaneRequeueDuration) - - // wait section - is it needed? - - //prepare subresource client to request admin kubeconfig - srscClient := m.ShootClient.SubResource("adminkubeconfig") - shootAdminClient, err := GetShootClient(ctx, srscClient, s.shoot) - - if err != nil { - //TODO: handle error before updating status - return updateStatusAndStopWithError(err) + if !isOidcExtensionEnabled(*s.shoot) { + m.log.Info("OIDC extension is disabled") + updateStatusAndStop() } if s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig == nil { @@ -49,12 +26,10 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStopWithError(error) } - additionalOidcConfig := (*s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig)[0] - openIDConnectResource := createOpenIDConnectResource(additionalOidcConfig) - errResourceCreation := shootAdminClient.Create(ctx, openIDConnectResource) + err := createOpenIdConnectResources(ctx, m, s) - if errResourceCreation != nil { - m.log.Error(errResourceCreation, "Failed to create OpenIDConnect resource") + if err != nil { + m.log.Error(err, "Failed to create OpenIDConnect resource") } s.instance.UpdateStateReady( @@ -68,14 +43,41 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStop() } -func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig) *authenticationv1alpha1.OpenIDConnect { +func createOpenIdConnectResources(ctx context.Context, m *fsm, s *systemState) error { + srscClient := m.ShootClient.SubResource("adminkubeconfig") + shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) + + if shootClientError != nil { + return shootClientError + } + + additionalOidcConfigs := *s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig + + var errResourceCreation error + for id, additionalOidcConfig := range additionalOidcConfigs { + openIDConnectResource := createOpenIDConnectResource(additionalOidcConfig, id) + errResourceCreation = shootAdminClient.Create(ctx, openIDConnectResource) + } + return errResourceCreation +} + +func isOidcExtensionEnabled(shoot gardener.Shoot) bool { + for _, extension := range shoot.Spec.Extensions { + if extension.Type == extender.OidcExtensionType { + return !(*extension.Disabled) + } + } + return false +} + +func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig, oidcId int) *authenticationv1alpha1.OpenIDConnect { cr := &authenticationv1alpha1.OpenIDConnect{ TypeMeta: metav1.TypeMeta{ Kind: "OpenIDConnect", APIVersion: "authentication.gardener.cloud/v1alpha1", }, ObjectMeta: metav1.ObjectMeta{ - Name: "to-be-changed", + Name: fmt.Sprintf("kyma-oidc-%v", oidcId), }, Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ IssuerURL: *additionalOidcConfig.IssuerURL, @@ -88,24 +90,5 @@ func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig) *auth }, } - //cr := &authenticationv1alpha1.OpenIDConnect{ - // TypeMeta: metav1.TypeMeta{ - // Kind: "OpenIDConnect", - // APIVersion: "authentication.gardener.cloud/v1alpha1", - // }, - // ObjectMeta: metav1.ObjectMeta{ - // Name: "my-oidc", - // }, - // Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ - // IssuerURL: "https://token.actions.githubusercontent.com", - // ClientID: "my-kubernetes-cluster", - // UsernameClaim: ptr.To("sub"), - // UsernamePrefix: ptr.To("actions-oidc:"), - // GroupsPrefix: ptr.To("deploy-kubernetes"), - // GroupsClaim: ptr.To("myOrg/myRepo"), - // RequiredClaims: map[string]string{}, - // }, - //} - return cr } From 77e50eb2cbaa6cb83c9a16516d120002091065ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Mon, 16 Sep 2024 11:18:48 +0200 Subject: [PATCH 06/36] adds OIDC conditions --- api/v1/runtime_types.go | 2 ++ .../runtime/fsm/runtime_fsm_configure_oidc.go | 34 ++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/api/v1/runtime_types.go b/api/v1/runtime_types.go index e4bd0446..257f1c7d 100644 --- a/api/v1/runtime_types.go +++ b/api/v1/runtime_types.go @@ -101,6 +101,8 @@ const ( ConditionReasonAuditLogConfigured = RuntimeConditionReason("AuditLogConfigured") ConditionReasonAuditLogError = RuntimeConditionReason("AuditLogErr") ConditionReasonAuditLogMissingRegionMapping = RuntimeConditionReason("AuditLogMissingRegionMappingErr") + ConditionReasonOidcConfigured = RuntimeConditionReason("OidcConfigured") + ConditionReasonOidcError = RuntimeConditionReason("OidcConfigurationErr") ) //+kubebuilder:object:root=true diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index e3f3d37a..362e4742 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -17,24 +17,32 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct if !isOidcExtensionEnabled(*s.shoot) { m.log.Info("OIDC extension is disabled") + s.instance.UpdateStateReady( + imv1.ConditionTypeOidcConfigured, + imv1.ConditionReasonOidcConfigured, + "OIDC extension disabled", + ) updateStatusAndStop() } - if s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig == nil { - var error = errors.New("default OIDC configuration is not present") - m.log.Error(error, "default OIDC configuration is not present") - return updateStatusAndStopWithError(error) + validationError := validateOidcConfiguration(s.instance) + if validationError != nil { + m.log.Error(validationError, "default OIDC configuration is not present") + updateConditionFailed(&s.instance) + return updateStatusAndStopWithError(validationError) } err := createOpenIdConnectResources(ctx, m, s) if err != nil { m.log.Error(err, "Failed to create OpenIDConnect resource") + updateConditionFailed(&s.instance) + return updateStatusAndStopWithError(err) } s.instance.UpdateStateReady( imv1.ConditionTypeOidcConfigured, - imv1.ConditionReasonConfigurationCompleted, + imv1.ConditionReasonOidcConfigured, "OIDC configuration completed", ) @@ -43,6 +51,13 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStop() } +func validateOidcConfiguration(rt imv1.Runtime) (err error) { + if rt.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig == nil { + err = errors.New("default OIDC configuration is not present") + } + return err +} + func createOpenIdConnectResources(ctx context.Context, m *fsm, s *systemState) error { srscClient := m.ShootClient.SubResource("adminkubeconfig") shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) @@ -92,3 +107,12 @@ func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig, oidcI return cr } + +func updateConditionFailed(rt *imv1.Runtime) { + rt.UpdateStatePending( + imv1.ConditionTypeOidcConfigured, + imv1.ConditionReasonOidcError, + string(metav1.ConditionFalse), + "failed to configure OIDC", + ) +} From d51eda90e300621e5ca2f2e94b63c9a22ee73293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 17 Sep 2024 07:54:59 +0200 Subject: [PATCH 07/36] oidc state is moved from last to be before CRB state --- .../runtime/fsm/runtime_fsm_apply_clusterrolebindings.go | 2 +- .../runtime/fsm/runtime_fsm_configure_auditlog.go | 2 +- .../runtime/fsm/runtime_fsm_configure_auditlog_test.go | 8 ++++---- .../runtime/fsm/runtime_fsm_create_kubeconfig.go | 2 +- .../runtime/fsm/runtime_fsm_create_kubeconfig_test.go | 2 +- .../controller/runtime/fsm/runtime_fsm_patch_shoot.go | 2 +- .../fsm/runtime_fsm_waiting_for_shoot_reconcile.go | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go index 7e7737ed..751b141c 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go +++ b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go @@ -51,7 +51,7 @@ func sFnApplyClusterRoleBindings(ctx context.Context, m *fsm, s *systemState) (s } } - return switchState(sFnConfigureAuditLog) + return switchState(sFnApplyClusterRoleBindings) } //nolint:gochecknoglobals diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go index 05490da5..11e87060 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go @@ -82,5 +82,5 @@ func sFnConfigureAuditLog(ctx context.Context, m *fsm, s *systemState) (stateFn, ) } - return switchState(sFnConfigureOidc) + return updateStatusAndStop() } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go index ce4c0cf7..02aa68e8 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go @@ -85,7 +85,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnConfigureOidc") + require.Contains(t, stateFn.name(), "sFnUpdateStatus") assert.Equal(t, v1.RuntimeStateReady, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -122,7 +122,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnConfigureOidc") + require.Contains(t, stateFn.name(), "sFnUpdateStatus") assert.Equal(t, v1.RuntimeStateFailed, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -159,7 +159,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnConfigureOidc") + require.Contains(t, stateFn.name(), "sFnUpdateStatus") assert.Equal(t, v1.RuntimeStateReady, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -196,7 +196,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnConfigureOidc") + require.Contains(t, stateFn.name(), "sFnUpdateStatus") assert.Equal(t, v1.RuntimeStateFailed, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go index 00c0fde7..8d83944e 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go @@ -66,7 +66,7 @@ func sFnCreateKubeconfig(ctx context.Context, m *fsm, s *systemState) (stateFn, imv1.ConditionTypeRuntimeKubeconfigReady, imv1.ConditionReasonGardenerCRReady, "Gardener Cluster CR is ready.", - sFnApplyClusterRoleBindings) + sFnConfigureOidc) } func makeGardenerClusterForRuntime(runtime imv1.Runtime, shoot *gardener.Shoot) *imv1.GardenerCluster { diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig_test.go b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig_test.go index 8cce9d75..095524de 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig_test.go @@ -99,7 +99,7 @@ var _ = Describe("KIM sFnCreateKubeconfig", func() { &systemState{instance: *inputRtWithLabelsAndCondition, shoot: &testShoot}, testOpts{ MatchExpectedErr: BeNil(), - MatchNextFnState: haveName("sFnApplyClusterRoleBindings"), + MatchNextFnState: haveName("sFnConfigureOidc"), }, ), Entry( diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index ee9944b5..1824303a 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -35,7 +35,7 @@ func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn if updatedShoot.Generation == s.shoot.Generation { m.log.Info("Gardener shoot for runtime did not change after patch, moving to processing", "Name", s.shoot.Name, "Namespace", s.shoot.Namespace) - return switchState(sFnApplyClusterRoleBindings) + return switchState(sFnConfigureOidc) } m.log.Info("Gardener shoot for runtime patched successfully", "Name", s.shoot.Name, "Namespace", s.shoot.Namespace) diff --git a/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go b/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go index b70e09a2..2510c239 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go +++ b/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go @@ -49,7 +49,7 @@ func sFnWaitForShootReconcile(_ context.Context, m *fsm, s *systemState) (stateF imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonConfigurationCompleted, "Runtime processing completed successfully", - sFnApplyClusterRoleBindings) + sFnConfigureOidc) } m.log.Info("Update did not processed, exiting with no retry") From 2e927eedf703aba7ab5b90236e413d91ee2dbc3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 17 Sep 2024 08:30:17 +0200 Subject: [PATCH 08/36] golangci-lint run --fix --- .../controller/runtime/fsm/runtime_fsm_configure_oidc.go | 1 + internal/controller/runtime/suite_test.go | 6 +++--- internal/controller/runtime/test_client_obj_tracker_test.go | 3 ++- internal/gardener/shoot/extender/oidc_test.go | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 362e4742..a8c33eca 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,6 +3,7 @@ package fsm import ( "context" "fmt" + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index 22c538b2..f29815dd 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -19,19 +19,19 @@ package runtime import ( "context" "encoding/json" - "github.com/kyma-project/infrastructure-manager/internal/auditlogging" - v1 "k8s.io/api/autoscaling/v1" - v12 "k8s.io/api/core/v1" "path/filepath" "testing" "time" gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/auditlogging" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive + v1 "k8s.io/api/autoscaling/v1" + v12 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" //nolint:revive diff --git a/internal/controller/runtime/test_client_obj_tracker_test.go b/internal/controller/runtime/test_client_obj_tracker_test.go index 2604945a..5fe1388f 100644 --- a/internal/controller/runtime/test_client_obj_tracker_test.go +++ b/internal/controller/runtime/test_client_obj_tracker_test.go @@ -1,11 +1,12 @@ package runtime import ( + "testing" + gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - "testing" ) func TestCustomTracker_Get(t *testing.T) { diff --git a/internal/gardener/shoot/extender/oidc_test.go b/internal/gardener/shoot/extender/oidc_test.go index 3fc0e683..88082cdf 100644 --- a/internal/gardener/shoot/extender/oidc_test.go +++ b/internal/gardener/shoot/extender/oidc_test.go @@ -1,13 +1,13 @@ package extender import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "testing" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestOidcExtender(t *testing.T) { From a5b648cbbe35b5acee8c33143bd8f2397c266468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 17 Sep 2024 08:34:47 +0200 Subject: [PATCH 09/36] further lint fixes around oidc fsm --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 10 +++++----- internal/gardener/shoot/extender/oidc_test.go | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index a8c33eca..fdd34c6a 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -23,7 +23,7 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct imv1.ConditionReasonOidcConfigured, "OIDC extension disabled", ) - updateStatusAndStop() + return updateStatusAndStop() } validationError := validateOidcConfiguration(s.instance) @@ -33,7 +33,7 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStopWithError(validationError) } - err := createOpenIdConnectResources(ctx, m, s) + err := createOpenIDConnectResources(ctx, m, s) if err != nil { m.log.Error(err, "Failed to create OpenIDConnect resource") @@ -59,7 +59,7 @@ func validateOidcConfiguration(rt imv1.Runtime) (err error) { return err } -func createOpenIdConnectResources(ctx context.Context, m *fsm, s *systemState) error { +func createOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { srscClient := m.ShootClient.SubResource("adminkubeconfig") shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) @@ -86,14 +86,14 @@ func isOidcExtensionEnabled(shoot gardener.Shoot) bool { return false } -func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig, oidcId int) *authenticationv1alpha1.OpenIDConnect { +func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig, oidcID int) *authenticationv1alpha1.OpenIDConnect { cr := &authenticationv1alpha1.OpenIDConnect{ TypeMeta: metav1.TypeMeta{ Kind: "OpenIDConnect", APIVersion: "authentication.gardener.cloud/v1alpha1", }, ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("kyma-oidc-%v", oidcId), + Name: fmt.Sprintf("kyma-oidc-%v", oidcID), }, Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ IssuerURL: *additionalOidcConfig.IssuerURL, diff --git a/internal/gardener/shoot/extender/oidc_test.go b/internal/gardener/shoot/extender/oidc_test.go index 88082cdf..1d8add40 100644 --- a/internal/gardener/shoot/extender/oidc_test.go +++ b/internal/gardener/shoot/extender/oidc_test.go @@ -11,7 +11,7 @@ import ( ) func TestOidcExtender(t *testing.T) { - const MigratorLabel = "operator.kyma-project.io/created-by-migrator" + const migratorLabel = "operator.kyma-project.io/created-by-migrator" for _, testCase := range []struct { name string migratorLabel map[string]string @@ -19,12 +19,12 @@ func TestOidcExtender(t *testing.T) { }{ { name: "label created-by-migrator=true should not configure OIDC", - migratorLabel: map[string]string{MigratorLabel: "true"}, + migratorLabel: map[string]string{migratorLabel: "true"}, expectedOidcExtensionEnabled: false, }, { name: "label created-by-migrator=false should configure OIDC", - migratorLabel: map[string]string{MigratorLabel: "false"}, + migratorLabel: map[string]string{migratorLabel: "false"}, expectedOidcExtensionEnabled: true, }, { @@ -44,7 +44,7 @@ func TestOidcExtender(t *testing.T) { runtimeShoot := imv1.Runtime{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - MigratorLabel: testCase.migratorLabel[MigratorLabel], + migratorLabel: testCase.migratorLabel[migratorLabel], }, }, Spec: imv1.RuntimeSpec{ From 6e95ce18a7a82b5442e149d85703e7a2aaed42c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 17 Sep 2024 08:43:54 +0200 Subject: [PATCH 10/36] attempt to fix trivy and imports reordering --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index 6b195750..6bf8fe22 100644 --- a/go.mod +++ b/go.mod @@ -93,4 +93,5 @@ replace ( golang.org/x/sys => golang.org/x/sys v0.21.0 golang.org/x/text => golang.org/x/text v0.16.0 golang.org/x/tools => golang.org/x/tools v0.22.0 + gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.6.0 ) From 83a8553fdf7bf4aa216dfb3bdb44f3fe120da4fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 17 Sep 2024 08:58:45 +0200 Subject: [PATCH 11/36] replaces indirect dependency of go-jose from 2.6.0 to 4.0.4 to fix cve-2024-28180 --- go.mod | 3 ++- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6bf8fe22..c2484d93 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect @@ -93,5 +94,5 @@ replace ( golang.org/x/sys => golang.org/x/sys v0.21.0 golang.org/x/text => golang.org/x/text v0.16.0 golang.org/x/tools => golang.org/x/tools v0.22.0 - gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.6.0 + gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4 v4.0.4 ) diff --git a/go.sum b/go.sum index d9cce153..06ac5a86 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,10 @@ github.com/gardener/gardener-extension-provider-openstack v1.41.0 h1:AlzWuvw3Dhk github.com/gardener/gardener-extension-provider-openstack v1.41.0/go.mod h1:DqpbvoN61U7qSzRFXv3UyRTLkopd2yIXhtPRLzfE2Ro= github.com/gardener/oidc-webhook-authenticator v0.31.0 h1:M6blkT63Kgt1/J8YkyKjEJ6JBfuRZ+KKDL8gUJBhjII= github.com/gardener/oidc-webhook-authenticator v0.31.0/go.mod h1:FrZLNLZOw12GwKmlVwpyFx1w02rOPwTP3mAoVUGRVR4= +github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= +github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -168,8 +172,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 85ae26c0da3b95c379a5b5854246f201d32b4fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 17 Sep 2024 09:05:23 +0200 Subject: [PATCH 12/36] replaces go-jose/v4 4.0.4 with go-jose/v2 2.6.3 which is closer major version to one used by external library --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c2484d93..d7ca0927 100644 --- a/go.mod +++ b/go.mod @@ -94,5 +94,5 @@ replace ( golang.org/x/sys => golang.org/x/sys v0.21.0 golang.org/x/text => golang.org/x/text v0.16.0 golang.org/x/tools => golang.org/x/tools v0.22.0 - gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4 v4.0.4 + gopkg.in/square/go-jose.v2 => gopkg.in/go-jose/go-jose.v2 v2.6.3 ) From 474b53556f5b9a717a67bd4101a1ff0d226663ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 17 Sep 2024 10:34:55 +0200 Subject: [PATCH 13/36] Revert "replaces go-jose/v4 4.0.4 with go-jose/v2 2.6.3 which is closer major version to one used by external library" This reverts commit 85ae26c0da3b95c379a5b5854246f201d32b4fb7. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d7ca0927..c2484d93 100644 --- a/go.mod +++ b/go.mod @@ -94,5 +94,5 @@ replace ( golang.org/x/sys => golang.org/x/sys v0.21.0 golang.org/x/text => golang.org/x/text v0.16.0 golang.org/x/tools => golang.org/x/tools v0.22.0 - gopkg.in/square/go-jose.v2 => gopkg.in/go-jose/go-jose.v2 v2.6.3 + gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4 v4.0.4 ) From 538b69c7f446a51583389591840ceea2c1724887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 18 Sep 2024 08:18:16 +0200 Subject: [PATCH 14/36] fixes runtime controller tests --- .../runtime_fsm_apply_clusterrolebindings.go | 2 +- .../runtime_fsm_configure_auditlog_test.go | 2 +- .../runtime/fsm/runtime_fsm_configure_oidc.go | 10 +++- .../runtime/fsm/runtime_fsm_patch_shoot.go | 13 ----- .../runtime/runtime_controller_test.go | 13 +++++ internal/controller/runtime/suite_test.go | 2 + internal/gardener/shoot/oidc_defaulter.go | 18 +++++++ .../gardener/shoot/oidc_defaulter_test.go | 51 +++++++++++++++++++ 8 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 internal/gardener/shoot/oidc_defaulter.go create mode 100644 internal/gardener/shoot/oidc_defaulter_test.go diff --git a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go index 751b141c..7e7737ed 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go +++ b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go @@ -51,7 +51,7 @@ func sFnApplyClusterRoleBindings(ctx context.Context, m *fsm, s *systemState) (s } } - return switchState(sFnApplyClusterRoleBindings) + return switchState(sFnConfigureAuditLog) } //nolint:gochecknoglobals diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go index 02aa68e8..cf48b935 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go @@ -233,7 +233,7 @@ func TestAuditLogState(t *testing.T) { // then auditLog.AssertExpectations(t) - require.Contains(t, stateFn.name(), "sFnConfigureOidc") + require.Contains(t, stateFn.name(), "sFnUpdateStatus") assert.Equal(t, v1.RuntimeStateReady, string(systemState.instance.Status.State)) assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index fdd34c6a..aa8910fb 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,6 +3,8 @@ package fsm import ( "context" "fmt" + "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" + k8serrors "k8s.io/apimachinery/pkg/api/errors" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" @@ -25,7 +27,7 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct ) return updateStatusAndStop() } - + shoot.DefaultAdditionalOidcIfNotPresent(&s.instance) validationError := validateOidcConfiguration(s.instance) if validationError != nil { m.log.Error(validationError, "default OIDC configuration is not present") @@ -35,6 +37,10 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct err := createOpenIDConnectResources(ctx, m, s) + if k8serrors.IsAlreadyExists(err) { + return switchState(sFnApplyClusterRoleBindings) + } + if err != nil { m.log.Error(err, "Failed to create OpenIDConnect resource") updateConditionFailed(&s.instance) @@ -49,7 +55,7 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct m.log.Info("OIDC has been configured", "Name", s.shoot.Name) - return updateStatusAndStop() + return switchState(sFnApplyClusterRoleBindings) } func validateOidcConfiguration(rt imv1.Runtime) (err error) { diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index 1824303a..a43e1e42 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -57,7 +57,6 @@ func convertShoot(instance *imv1.Runtime, cfg shoot.ConverterConfig) (gardener.S return gardener.Shoot{}, err } - defaultAdditionalOidcIfNotPresent(instance) converter := gardener_shoot.NewConverter(cfg) newShoot, err := converter.ToShoot(*instance) @@ -68,18 +67,6 @@ func convertShoot(instance *imv1.Runtime, cfg shoot.ConverterConfig) (gardener.S return newShoot, err } -func defaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime) { - oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig - additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig - - if nil == additionalOidcConfig { - additionalOidcConfig = &[]gardener.OIDCConfig{} - *additionalOidcConfig = append(*additionalOidcConfig, oidcConfig) - } - - runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig -} - // workaround func setObjectFields(shoot *gardener.Shoot) { shoot.Kind = "Shoot" diff --git a/internal/controller/runtime/runtime_controller_test.go b/internal/controller/runtime/runtime_controller_test.go index 8811ef74..7a78bc8c 100644 --- a/internal/controller/runtime/runtime_controller_test.go +++ b/internal/controller/runtime/runtime_controller_test.go @@ -18,6 +18,7 @@ package runtime import ( "context" + "k8s.io/utils/ptr" "time" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" @@ -257,6 +258,18 @@ func CreateRuntimeStub(resourceName string) *imv1.Runtime { }, }, Region: "eu-central-1", + Kubernetes: imv1.Kubernetes{ + KubeAPIServer: imv1.APIServer{ + OidcConfig: gardener.OIDCConfig{ + ClientID: ptr.To("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"), + GroupsClaim: ptr.To("groups"), + IssuerURL: ptr.To("https://example.com"), + SigningAlgs: []string{"RSA256"}, + UsernameClaim: ptr.To("sub"), + UsernamePrefix: ptr.To("-"), + }, + }, + }, }, Security: imv1.Security{ Administrators: []string{ diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index f29815dd..df83661f 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -19,6 +19,7 @@ package runtime import ( "context" "encoding/json" + gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "path/filepath" "testing" "time" @@ -119,6 +120,7 @@ var _ = BeforeSuite(func() { shootClientScheme := runtime.NewScheme() _ = rbacv1.AddToScheme(shootClientScheme) + err = gardener_oidc.AddToScheme(shootClientScheme) k8sFakeClientRoleBindings = fake.NewClientBuilder().WithScheme(shootClientScheme).Build() fsm.GetShootClient = func(_ context.Context, _ client.SubResourceClient, _ *gardener_api.Shoot) (client.Client, error) { diff --git a/internal/gardener/shoot/oidc_defaulter.go b/internal/gardener/shoot/oidc_defaulter.go new file mode 100644 index 00000000..e17b50e2 --- /dev/null +++ b/internal/gardener/shoot/oidc_defaulter.go @@ -0,0 +1,18 @@ +package shoot + +import ( + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" +) + +func DefaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime) { + oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig + additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig + + if nil == additionalOidcConfig { + additionalOidcConfig = &[]gardener.OIDCConfig{} + *additionalOidcConfig = append(*additionalOidcConfig, oidcConfig) + } + + runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig +} diff --git a/internal/gardener/shoot/oidc_defaulter_test.go b/internal/gardener/shoot/oidc_defaulter_test.go new file mode 100644 index 00000000..4adff3be --- /dev/null +++ b/internal/gardener/shoot/oidc_defaulter_test.go @@ -0,0 +1,51 @@ +package shoot + +import ( + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "testing" +) + +func TestOidcDefaulter(t *testing.T) { + t.Run("Create shoot from Runtime", func(t *testing.T) { + // given + runtime := CreateRuntimeStub("runtime") + + // when + DefaultAdditionalOidcIfNotPresent(runtime) + + // then + assert.NotNil(t, runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig) + assert.Equal(t, runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig, (*runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig)[0]) + }) +} + +func CreateRuntimeStub(resourceName string) *imv1.Runtime { + resource := &imv1.Runtime{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: "default", + }, + Spec: imv1.RuntimeSpec{ + Shoot: imv1.RuntimeShoot{ + Name: resourceName, + Kubernetes: imv1.Kubernetes{ + KubeAPIServer: imv1.APIServer{ + OidcConfig: gardener.OIDCConfig{ + ClientID: ptr.To("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"), + GroupsClaim: ptr.To("groups"), + IssuerURL: ptr.To("https://example.com"), + SigningAlgs: []string{"RSA256"}, + UsernameClaim: ptr.To("sub"), + UsernamePrefix: ptr.To("-"), + }, + }, + }, + }, + }, + } + return resource +} From 1a01f478942a1d331dcc9b1b3115dc8fec3d9212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 18 Sep 2024 08:21:50 +0200 Subject: [PATCH 15/36] fixes linter --- internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go | 4 ++-- internal/controller/runtime/runtime_controller_test.go | 2 +- internal/controller/runtime/suite_test.go | 2 +- internal/gardener/shoot/oidc_defaulter_test.go | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index aa8910fb..5ef2a82c 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,14 +3,14 @@ package fsm import ( "context" "fmt" - "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" - k8serrors "k8s.io/apimachinery/pkg/api/errors" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" "github.com/pkg/errors" + k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" ) diff --git a/internal/controller/runtime/runtime_controller_test.go b/internal/controller/runtime/runtime_controller_test.go index 7a78bc8c..52a243ea 100644 --- a/internal/controller/runtime/runtime_controller_test.go +++ b/internal/controller/runtime/runtime_controller_test.go @@ -18,7 +18,6 @@ package runtime import ( "context" - "k8s.io/utils/ptr" "time" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" @@ -28,6 +27,7 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index df83661f..01fa28ff 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -19,12 +19,12 @@ package runtime import ( "context" "encoding/json" - gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "path/filepath" "testing" "time" gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" + gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" diff --git a/internal/gardener/shoot/oidc_defaulter_test.go b/internal/gardener/shoot/oidc_defaulter_test.go index 4adff3be..d761398b 100644 --- a/internal/gardener/shoot/oidc_defaulter_test.go +++ b/internal/gardener/shoot/oidc_defaulter_test.go @@ -1,12 +1,13 @@ package shoot import ( + "testing" + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" - "testing" ) func TestOidcDefaulter(t *testing.T) { From 3845a58af0331db5ff7ca3155eea0c2105c05727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Fri, 20 Sep 2024 12:41:16 +0200 Subject: [PATCH 16/36] WiP work on oidc/additionalOidc defaults --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 16 ++++++++-- .../runtime/runtime_controller_test.go | 10 ++++++ internal/gardener/shoot/converter.go | 24 +++++++++++--- internal/gardener/shoot/extender/oidc.go | 32 +++++++++++++++---- internal/gardener/shoot/extender/oidc_test.go | 15 +++++---- internal/gardener/shoot/oidc_defaulter.go | 24 ++++++++++---- .../gardener/shoot/oidc_defaulter_test.go | 2 +- 7 files changed, 96 insertions(+), 27 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 5ef2a82c..986b0964 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,7 +3,6 @@ package fsm import ( "context" "fmt" - gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" @@ -15,6 +14,17 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) +func DefaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { + additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig + + if nil == additionalOidcConfig { + additionalOidcConfig = &[]gardener.OIDCConfig{} + defaultOIDCConfig := shoot.CreateDefaultOIDCConfig(cfg.Kubernetes.DefaultSharedIASTenant) + *additionalOidcConfig = append(*additionalOidcConfig, defaultOIDCConfig) + runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig + } +} + func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Configure OIDC state") @@ -27,7 +37,9 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct ) return updateStatusAndStop() } - shoot.DefaultAdditionalOidcIfNotPresent(&s.instance) + + //DefaultOidcIfNotPresent(&s.instance, m.RCCfg) + DefaultAdditionalOidcIfNotPresent(&s.instance, m.RCCfg) validationError := validateOidcConfiguration(s.instance) if validationError != nil { m.log.Error(validationError, "default OIDC configuration is not present") diff --git a/internal/controller/runtime/runtime_controller_test.go b/internal/controller/runtime/runtime_controller_test.go index 52a243ea..14aaafed 100644 --- a/internal/controller/runtime/runtime_controller_test.go +++ b/internal/controller/runtime/runtime_controller_test.go @@ -107,10 +107,20 @@ var _ = Describe("Runtime Controller", func() { return false } + if !runtime.IsConditionSet(imv1.ConditionTypeOidcConfigured, imv1.ConditionReasonOidcConfigured) { + return false + } + + if !runtime.IsConditionSetWithStatus(imv1.ConditionTypeOidcConfigured, imv1.ConditionReasonOidcConfigured, metav1.ConditionTrue) { + return false + } + if !runtime.IsConditionSet(imv1.ConditionTypeAuditLogConfigured, imv1.ConditionReasonAuditLogConfigured) { return false } + //TODO: condition should be 'TRUE' + return true }, time.Second*300, time.Second*3).Should(BeTrue()) diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index 4e6a891b..1aed63a2 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -33,9 +33,20 @@ type DNSConfig struct { } type KubernetesConfig struct { - DefaultVersion string `json:"defaultVersion" validate:"required"` - EnableKubernetesVersionAutoUpdate bool `json:"enableKubernetesVersionAutoUpdate"` - EnableMachineImageVersionAutoUpdate bool `json:"enableMachineImageVersionVersionAutoUpdate"` + DefaultVersion string `json:"defaultVersion" validate:"required"` + EnableKubernetesVersionAutoUpdate bool `json:"enableKubernetesVersionAutoUpdate"` + EnableMachineImageVersionAutoUpdate bool `json:"enableMachineImageVersionVersionAutoUpdate"` + DefaultOperatorOidc OidcProvider `json:"defaultOperatorOidc" validate:"required"` + DefaultSharedIASTenant OidcProvider `json:"defaultSharedIASTenant" validate:"required"` +} + +type OidcProvider struct { + ClientID string `json:"clientID" validate:"required"` + GroupsClaim string `json:"groupsClaim" validate:"required"` + IssuerURL string `json:"issuerURL" validate:"required"` + SigningAlgs []string `json:"signingAlgs" validate:"required"` + UsernameClaim string `json:"usernameClaim" validate:"required"` + UsernamePrefix string `json:"usernamePrefix" validate:"required"` } type AuditLogConfig struct { @@ -77,7 +88,12 @@ func NewConverter(config ConverterConfig) Converter { extender.NewKubernetesExtender(config.Kubernetes.DefaultVersion), extender.NewProviderExtender(config.Provider.AWS.EnableIMDSv2, config.MachineImage.DefaultVersion), extender.NewDNSExtender(config.DNS.SecretName, config.DNS.DomainPrefix, config.DNS.ProviderType), - extender.ExtendWithOIDC, + extender.NewOidcExtender(config.Kubernetes.DefaultOperatorOidc.ClientID, + config.Kubernetes.DefaultOperatorOidc.GroupsClaim, + config.Kubernetes.DefaultOperatorOidc.IssuerURL, + config.Kubernetes.DefaultOperatorOidc.UsernameClaim, + config.Kubernetes.DefaultOperatorOidc.UsernamePrefix, + config.Kubernetes.DefaultOperatorOidc.SigningAlgs), extender.ExtendWithCloudProfile, extender.ExtendWithNetworkFilter, extender.ExtendWithCertConfig, diff --git a/internal/gardener/shoot/extender/oidc.go b/internal/gardener/shoot/extender/oidc.go index b776cf71..57676bc8 100644 --- a/internal/gardener/shoot/extender/oidc.go +++ b/internal/gardener/shoot/extender/oidc.go @@ -10,15 +10,33 @@ const ( OidcExtensionType = "shoot-oidc-service" ) -func ExtendWithOIDC(runtime imv1.Runtime, shoot *gardener.Shoot) error { - oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig +func ShouldDefaultOidcConfig(config gardener.OIDCConfig) bool { + return config.ClientID == nil && config.IssuerURL == nil +} - if CanEnableExtension(runtime) { - setOIDCExtension(shoot) - } - setKubeAPIServerOIDCConfig(shoot, oidcConfig) +func NewOidcExtender(clientId, groupsClaim, issuerURL, usernameClaim, usernamePrefix string, signingAlgs []string) func(runtime imv1.Runtime, shoot *gardener.Shoot) error { + return func(runtime imv1.Runtime, shoot *gardener.Shoot) error { + if CanEnableExtension(runtime) { + setOIDCExtension(shoot) + } + + oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig - return nil + if ShouldDefaultOidcConfig(oidcConfig) { + oidcConfig = gardener.OIDCConfig{ + ClientID: &clientId, + GroupsClaim: &groupsClaim, + IssuerURL: &issuerURL, + SigningAlgs: signingAlgs, + UsernameClaim: &usernameClaim, + UsernamePrefix: &usernamePrefix, + } + } + + setKubeAPIServerOIDCConfig(shoot, oidcConfig) + + return nil + } } func CanEnableExtension(runtime imv1.Runtime) bool { diff --git a/internal/gardener/shoot/extender/oidc_test.go b/internal/gardener/shoot/extender/oidc_test.go index 1d8add40..6b93e1c1 100644 --- a/internal/gardener/shoot/extender/oidc_test.go +++ b/internal/gardener/shoot/extender/oidc_test.go @@ -39,6 +39,8 @@ func TestOidcExtender(t *testing.T) { groupsClaim := "groups" issuerURL := "https://my.cool.tokens.com" usernameClaim := "sub" + usernamePrefix := "-" + signingAlgs := []string{"RS256"} shoot := fixEmptyGardenerShoot("test", "kcp-system") runtimeShoot := imv1.Runtime{ @@ -52,12 +54,10 @@ func TestOidcExtender(t *testing.T) { Kubernetes: imv1.Kubernetes{ KubeAPIServer: imv1.APIServer{ OidcConfig: gardener.OIDCConfig{ - ClientID: &clientID, - GroupsClaim: &groupsClaim, - IssuerURL: &issuerURL, - SigningAlgs: []string{ - "RS256", - }, + ClientID: &clientID, + GroupsClaim: &groupsClaim, + IssuerURL: &issuerURL, + SigningAlgs: signingAlgs, UsernameClaim: &usernameClaim, }, }, @@ -67,7 +67,8 @@ func TestOidcExtender(t *testing.T) { } // when - err := ExtendWithOIDC(runtimeShoot, &shoot) + extender := NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePrefix, signingAlgs) + err := extender(runtimeShoot, &shoot) // then require.NoError(t, err) diff --git a/internal/gardener/shoot/oidc_defaulter.go b/internal/gardener/shoot/oidc_defaulter.go index e17b50e2..75512a1c 100644 --- a/internal/gardener/shoot/oidc_defaulter.go +++ b/internal/gardener/shoot/oidc_defaulter.go @@ -5,14 +5,26 @@ import ( imv1 "github.com/kyma-project/infrastructure-manager/api/v1" ) -func DefaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime) { +func DefaultOidcIfNotPresent(runtime *imv1.Runtime, oidcProviderCfg OidcProvider) { oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig - additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig - if nil == additionalOidcConfig { - additionalOidcConfig = &[]gardener.OIDCConfig{} - *additionalOidcConfig = append(*additionalOidcConfig, oidcConfig) + if ShouldDefaultOidcConfig(oidcConfig) { + defaultOIDCConfig := CreateDefaultOIDCConfig(oidcProviderCfg) + runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig = defaultOIDCConfig } +} + +func ShouldDefaultOidcConfig(config gardener.OIDCConfig) bool { + return config.ClientID == nil && config.IssuerURL == nil +} - runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig +func CreateDefaultOIDCConfig(defaultSharedIASTenant OidcProvider) gardener.OIDCConfig { + return gardener.OIDCConfig{ + ClientID: &defaultSharedIASTenant.ClientID, + GroupsClaim: &defaultSharedIASTenant.GroupsClaim, + IssuerURL: &defaultSharedIASTenant.IssuerURL, + SigningAlgs: defaultSharedIASTenant.SigningAlgs, + UsernameClaim: &defaultSharedIASTenant.UsernameClaim, + UsernamePrefix: &defaultSharedIASTenant.UsernamePrefix, + } } diff --git a/internal/gardener/shoot/oidc_defaulter_test.go b/internal/gardener/shoot/oidc_defaulter_test.go index d761398b..6f6dff3e 100644 --- a/internal/gardener/shoot/oidc_defaulter_test.go +++ b/internal/gardener/shoot/oidc_defaulter_test.go @@ -16,7 +16,7 @@ func TestOidcDefaulter(t *testing.T) { runtime := CreateRuntimeStub("runtime") // when - DefaultAdditionalOidcIfNotPresent(runtime) + DefaultOidcConfigurationIfNotPresent(runtime) // then assert.NotNil(t, runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig) From 6c15d44ce0b26763517ec68c8cba3b7295f81089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Fri, 20 Sep 2024 13:33:10 +0200 Subject: [PATCH 17/36] OIDCConfig is now optional --- api/v1/runtime_types.go | 2 +- .../bases/infrastructuremanager.kyma-project.io_runtimes.yaml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/api/v1/runtime_types.go b/api/v1/runtime_types.go index dbbc7c83..b1fb7619 100644 --- a/api/v1/runtime_types.go +++ b/api/v1/runtime_types.go @@ -164,7 +164,7 @@ type Kubernetes struct { } type APIServer struct { - OidcConfig gardener.OIDCConfig `json:"oidcConfig"` + OidcConfig gardener.OIDCConfig `json:"oidcConfig,omitempty"` AdditionalOidcConfig *[]gardener.OIDCConfig `json:"additionalOidcConfig,omitempty"` } diff --git a/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml b/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml index 034516ab..f3743ca0 100644 --- a/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml +++ b/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml @@ -279,8 +279,6 @@ spec: the value '-'. type: string type: object - required: - - oidcConfig type: object version: type: string From 81be84ea4be7da235847b98cbc940b785bd54e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 24 Sep 2024 08:09:48 +0200 Subject: [PATCH 18/36] clean-ups the code around defaulting oidc --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 13 ++++- internal/gardener/shoot/extender/oidc.go | 3 -- internal/gardener/shoot/oidc_defaulter.go | 30 ----------- .../gardener/shoot/oidc_defaulter_test.go | 52 ------------------- 4 files changed, 12 insertions(+), 86 deletions(-) delete mode 100644 internal/gardener/shoot/oidc_defaulter.go delete mode 100644 internal/gardener/shoot/oidc_defaulter_test.go diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 986b0964..60993be8 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -19,12 +19,23 @@ func DefaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { if nil == additionalOidcConfig { additionalOidcConfig = &[]gardener.OIDCConfig{} - defaultOIDCConfig := shoot.CreateDefaultOIDCConfig(cfg.Kubernetes.DefaultSharedIASTenant) + defaultOIDCConfig := CreateDefaultOIDCConfig(cfg.Kubernetes.DefaultSharedIASTenant) *additionalOidcConfig = append(*additionalOidcConfig, defaultOIDCConfig) runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig } } +func CreateDefaultOIDCConfig(defaultSharedIASTenant shoot.OidcProvider) gardener.OIDCConfig { + return gardener.OIDCConfig{ + ClientID: &defaultSharedIASTenant.ClientID, + GroupsClaim: &defaultSharedIASTenant.GroupsClaim, + IssuerURL: &defaultSharedIASTenant.IssuerURL, + SigningAlgs: defaultSharedIASTenant.SigningAlgs, + UsernameClaim: &defaultSharedIASTenant.UsernameClaim, + UsernamePrefix: &defaultSharedIASTenant.UsernamePrefix, + } +} + func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Configure OIDC state") diff --git a/internal/gardener/shoot/extender/oidc.go b/internal/gardener/shoot/extender/oidc.go index 57676bc8..820bdb53 100644 --- a/internal/gardener/shoot/extender/oidc.go +++ b/internal/gardener/shoot/extender/oidc.go @@ -21,7 +21,6 @@ func NewOidcExtender(clientId, groupsClaim, issuerURL, usernameClaim, usernamePr } oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig - if ShouldDefaultOidcConfig(oidcConfig) { oidcConfig = gardener.OIDCConfig{ ClientID: &clientId, @@ -32,13 +31,11 @@ func NewOidcExtender(clientId, groupsClaim, issuerURL, usernameClaim, usernamePr UsernamePrefix: &usernamePrefix, } } - setKubeAPIServerOIDCConfig(shoot, oidcConfig) return nil } } - func CanEnableExtension(runtime imv1.Runtime) bool { canEnable := true createdByMigrator := runtime.Labels["operator.kyma-project.io/created-by-migrator"] diff --git a/internal/gardener/shoot/oidc_defaulter.go b/internal/gardener/shoot/oidc_defaulter.go deleted file mode 100644 index 75512a1c..00000000 --- a/internal/gardener/shoot/oidc_defaulter.go +++ /dev/null @@ -1,30 +0,0 @@ -package shoot - -import ( - gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" - imv1 "github.com/kyma-project/infrastructure-manager/api/v1" -) - -func DefaultOidcIfNotPresent(runtime *imv1.Runtime, oidcProviderCfg OidcProvider) { - oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig - - if ShouldDefaultOidcConfig(oidcConfig) { - defaultOIDCConfig := CreateDefaultOIDCConfig(oidcProviderCfg) - runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig = defaultOIDCConfig - } -} - -func ShouldDefaultOidcConfig(config gardener.OIDCConfig) bool { - return config.ClientID == nil && config.IssuerURL == nil -} - -func CreateDefaultOIDCConfig(defaultSharedIASTenant OidcProvider) gardener.OIDCConfig { - return gardener.OIDCConfig{ - ClientID: &defaultSharedIASTenant.ClientID, - GroupsClaim: &defaultSharedIASTenant.GroupsClaim, - IssuerURL: &defaultSharedIASTenant.IssuerURL, - SigningAlgs: defaultSharedIASTenant.SigningAlgs, - UsernameClaim: &defaultSharedIASTenant.UsernameClaim, - UsernamePrefix: &defaultSharedIASTenant.UsernamePrefix, - } -} diff --git a/internal/gardener/shoot/oidc_defaulter_test.go b/internal/gardener/shoot/oidc_defaulter_test.go deleted file mode 100644 index 6f6dff3e..00000000 --- a/internal/gardener/shoot/oidc_defaulter_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package shoot - -import ( - "testing" - - gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" - imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" -) - -func TestOidcDefaulter(t *testing.T) { - t.Run("Create shoot from Runtime", func(t *testing.T) { - // given - runtime := CreateRuntimeStub("runtime") - - // when - DefaultOidcConfigurationIfNotPresent(runtime) - - // then - assert.NotNil(t, runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig) - assert.Equal(t, runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig, (*runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig)[0]) - }) -} - -func CreateRuntimeStub(resourceName string) *imv1.Runtime { - resource := &imv1.Runtime{ - ObjectMeta: metav1.ObjectMeta{ - Name: resourceName, - Namespace: "default", - }, - Spec: imv1.RuntimeSpec{ - Shoot: imv1.RuntimeShoot{ - Name: resourceName, - Kubernetes: imv1.Kubernetes{ - KubeAPIServer: imv1.APIServer{ - OidcConfig: gardener.OIDCConfig{ - ClientID: ptr.To("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"), - GroupsClaim: ptr.To("groups"), - IssuerURL: ptr.To("https://example.com"), - SigningAlgs: []string{"RSA256"}, - UsernameClaim: ptr.To("sub"), - UsernamePrefix: ptr.To("-"), - }, - }, - }, - }, - }, - } - return resource -} From 6c970805df358758c7b23aca2aa7420b208d41a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 24 Sep 2024 08:24:07 +0200 Subject: [PATCH 19/36] linter fixes --- internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go | 3 ++- internal/gardener/shoot/extender/oidc.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 60993be8..6c0fef99 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,6 +3,7 @@ package fsm import ( "context" "fmt" + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" @@ -49,7 +50,7 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStop() } - //DefaultOidcIfNotPresent(&s.instance, m.RCCfg) + // DefaultOidcIfNotPresent(&s.instance, m.RCCfg) DefaultAdditionalOidcIfNotPresent(&s.instance, m.RCCfg) validationError := validateOidcConfiguration(s.instance) if validationError != nil { diff --git a/internal/gardener/shoot/extender/oidc.go b/internal/gardener/shoot/extender/oidc.go index 820bdb53..60c4ef01 100644 --- a/internal/gardener/shoot/extender/oidc.go +++ b/internal/gardener/shoot/extender/oidc.go @@ -14,7 +14,7 @@ func ShouldDefaultOidcConfig(config gardener.OIDCConfig) bool { return config.ClientID == nil && config.IssuerURL == nil } -func NewOidcExtender(clientId, groupsClaim, issuerURL, usernameClaim, usernamePrefix string, signingAlgs []string) func(runtime imv1.Runtime, shoot *gardener.Shoot) error { +func NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePrefix string, signingAlgs []string) func(runtime imv1.Runtime, shoot *gardener.Shoot) error { return func(runtime imv1.Runtime, shoot *gardener.Shoot) error { if CanEnableExtension(runtime) { setOIDCExtension(shoot) @@ -23,7 +23,7 @@ func NewOidcExtender(clientId, groupsClaim, issuerURL, usernameClaim, usernamePr oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig if ShouldDefaultOidcConfig(oidcConfig) { oidcConfig = gardener.OIDCConfig{ - ClientID: &clientId, + ClientID: &clientID, GroupsClaim: &groupsClaim, IssuerURL: &issuerURL, SigningAlgs: signingAlgs, From 9bc3152ef25c53d8a72be3e924dd855097290c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 24 Sep 2024 08:42:28 +0200 Subject: [PATCH 20/36] fixes converter test after adding new fields --- internal/gardener/shoot/converter_test.go | 34 ++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index 67389c12..810f311c 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -138,7 +138,23 @@ var testReader io.Reader = strings.NewReader(`{ "kubernetes": { "defaultVersion": "0.1.2.3", "enableKubernetesVersionAutoUpdate": true, - "enableMachineImageVersionAutoUpdate": false + "enableMachineImageVersionAutoUpdate": false, + "defaultOperatorOidc": { + "clientID": "test-clientID", + "groupsClaim": "test-group", + "issuerURL": "test-issuer-url", + "signingAlgs": ["test-alg"], + "usernameClaim": "test-username-claim", + "usernamePrefix": "-" + }, + "defaultSharedIASTenant": { + "clientID": "test-clientID", + "groupsClaim": "test-group", + "issuerURL": "test-issuer-url", + "signingAlgs": ["test-alg"], + "usernameClaim": "test-username-claim", + "usernamePrefix": "-" + } }, "dns": { "secretName": "test-secret-name", @@ -177,6 +193,22 @@ func Test_ConverterConfig_Load_OK(t *testing.T) { DefaultVersion: "0.1.2.3", EnableKubernetesVersionAutoUpdate: true, EnableMachineImageVersionAutoUpdate: false, + DefaultOperatorOidc: OidcProvider{ + ClientID: "test-clientID", + GroupsClaim: "test-group", + IssuerURL: "test-issuer-url", + SigningAlgs: []string{"test-alg"}, + UsernameClaim: "test-username-claim", + UsernamePrefix: "-", + }, + DefaultSharedIASTenant: OidcProvider{ + ClientID: "test-clientID", + GroupsClaim: "test-group", + IssuerURL: "test-issuer-url", + SigningAlgs: []string{"test-alg"}, + UsernameClaim: "test-username-claim", + UsernamePrefix: "-", + }, }, DNS: DNSConfig{ SecretName: "test-secret-name", From 9e92dc37cbbd05a8cede617f78d53509d609c5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 24 Sep 2024 13:07:20 +0200 Subject: [PATCH 21/36] recreate oiddopenconnect CRs --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 6c0fef99..8f0b213a 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,6 +3,7 @@ package fsm import ( "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" @@ -59,7 +60,7 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return updateStatusAndStopWithError(validationError) } - err := createOpenIDConnectResources(ctx, m, s) + err := recreateOpenIDConnectResources(ctx, m, s) if k8serrors.IsAlreadyExists(err) { return switchState(sFnApplyClusterRoleBindings) @@ -89,7 +90,7 @@ func validateOidcConfiguration(rt imv1.Runtime) (err error) { return err } -func createOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { +func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { srscClient := m.ShootClient.SubResource("adminkubeconfig") shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) @@ -97,8 +98,12 @@ func createOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) e return shootClientError } - additionalOidcConfigs := *s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig + err := deleteExistingKymaOpenIDConnectResources(ctx, shootAdminClient) + if err != nil { + return err + } + additionalOidcConfigs := *s.instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig var errResourceCreation error for id, additionalOidcConfig := range additionalOidcConfigs { openIDConnectResource := createOpenIDConnectResource(additionalOidcConfig, id) @@ -107,6 +112,23 @@ func createOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) e return errResourceCreation } +func deleteExistingKymaOpenIDConnectResources(ctx context.Context, client client.Client) error { + + oidcList := &authenticationv1alpha1.OpenIDConnectList{} + if err := client.List(ctx, oidcList); err != nil { + return err + } + + for _, oidc := range oidcList.Items { + if _, ok := oidc.Labels[imv1.LabelKymaManagedBy]; ok { + err := client.Delete(ctx, &oidc) + if err != nil { + return err + } + } + } +} + func isOidcExtensionEnabled(shoot gardener.Shoot) bool { for _, extension := range shoot.Spec.Extensions { if extension.Type == extender.OidcExtensionType { @@ -124,6 +146,9 @@ func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig, oidcI }, ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("kyma-oidc-%v", oidcID), + Labels: map[string]string{ + imv1.LabelKymaManagedBy: "infrastructure-manager", + }, }, Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ IssuerURL: *additionalOidcConfig.IssuerURL, From 369b97481b3c932259c89b0beaf01bd96f4390c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 25 Sep 2024 10:40:13 +0200 Subject: [PATCH 22/36] fixes incorrect return statements in oidc fsm --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 8f0b213a..2faa5400 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -112,21 +112,23 @@ func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) return errResourceCreation } -func deleteExistingKymaOpenIDConnectResources(ctx context.Context, client client.Client) error { +func deleteExistingKymaOpenIDConnectResources(ctx context.Context, client client.Client) (err error) { oidcList := &authenticationv1alpha1.OpenIDConnectList{} - if err := client.List(ctx, oidcList); err != nil { - return err + if err = client.List(ctx, oidcList); err != nil { + return } for _, oidc := range oidcList.Items { if _, ok := oidc.Labels[imv1.LabelKymaManagedBy]; ok { - err := client.Delete(ctx, &oidc) + err = client.Delete(ctx, &oidc) if err != nil { - return err + return } } } + + return } func isOidcExtensionEnabled(shoot gardener.Shoot) bool { From 94b30340bd4f782b520c102c10ee370ef79f6ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 25 Sep 2024 10:42:03 +0200 Subject: [PATCH 23/36] linter --- internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 2faa5400..bfc34601 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,7 +3,6 @@ package fsm import ( "context" "fmt" - "sigs.k8s.io/controller-runtime/pkg/client" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" @@ -14,6 +13,7 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) func DefaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { @@ -113,7 +113,6 @@ func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) } func deleteExistingKymaOpenIDConnectResources(ctx context.Context, client client.Client) (err error) { - oidcList := &authenticationv1alpha1.OpenIDConnectList{} if err = client.List(ctx, oidcList); err != nil { return From 66a30395b746aa39a4890a4c29e97a56647a7a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 1 Oct 2024 08:18:45 +0200 Subject: [PATCH 24/36] applying review remarks --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 24 +++++++------------ internal/gardener/shoot/extender/oidc.go | 14 ++++------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index bfc34601..05bd5dc2 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -10,24 +10,23 @@ import ( "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" "github.com/pkg/errors" - k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) -func DefaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { +func defaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig - if nil == additionalOidcConfig { + if additionalOidcConfig == nil { additionalOidcConfig = &[]gardener.OIDCConfig{} - defaultOIDCConfig := CreateDefaultOIDCConfig(cfg.Kubernetes.DefaultSharedIASTenant) + defaultOIDCConfig := createDefaultOIDCConfig(cfg.Kubernetes.DefaultSharedIASTenant) *additionalOidcConfig = append(*additionalOidcConfig, defaultOIDCConfig) runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig } } -func CreateDefaultOIDCConfig(defaultSharedIASTenant shoot.OidcProvider) gardener.OIDCConfig { +func createDefaultOIDCConfig(defaultSharedIASTenant shoot.OidcProvider) gardener.OIDCConfig { return gardener.OIDCConfig{ ClientID: &defaultSharedIASTenant.ClientID, GroupsClaim: &defaultSharedIASTenant.GroupsClaim, @@ -48,11 +47,10 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct imv1.ConditionReasonOidcConfigured, "OIDC extension disabled", ) - return updateStatusAndStop() + return switchState(sFnApplyClusterRoleBindings) } - // DefaultOidcIfNotPresent(&s.instance, m.RCCfg) - DefaultAdditionalOidcIfNotPresent(&s.instance, m.RCCfg) + defaultAdditionalOidcIfNotPresent(&s.instance, m.RCCfg) validationError := validateOidcConfiguration(s.instance) if validationError != nil { m.log.Error(validationError, "default OIDC configuration is not present") @@ -62,10 +60,6 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct err := recreateOpenIDConnectResources(ctx, m, s) - if k8serrors.IsAlreadyExists(err) { - return switchState(sFnApplyClusterRoleBindings) - } - if err != nil { m.log.Error(err, "Failed to create OpenIDConnect resource") updateConditionFailed(&s.instance) @@ -115,19 +109,19 @@ func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) func deleteExistingKymaOpenIDConnectResources(ctx context.Context, client client.Client) (err error) { oidcList := &authenticationv1alpha1.OpenIDConnectList{} if err = client.List(ctx, oidcList); err != nil { - return + return err } for _, oidc := range oidcList.Items { if _, ok := oidc.Labels[imv1.LabelKymaManagedBy]; ok { err = client.Delete(ctx, &oidc) if err != nil { - return + return err } } } - return + return err } func isOidcExtensionEnabled(shoot gardener.Shoot) bool { diff --git a/internal/gardener/shoot/extender/oidc.go b/internal/gardener/shoot/extender/oidc.go index 60c4ef01..992ff0b4 100644 --- a/internal/gardener/shoot/extender/oidc.go +++ b/internal/gardener/shoot/extender/oidc.go @@ -10,7 +10,7 @@ const ( OidcExtensionType = "shoot-oidc-service" ) -func ShouldDefaultOidcConfig(config gardener.OIDCConfig) bool { +func shouldDefaultOidcConfig(config gardener.OIDCConfig) bool { return config.ClientID == nil && config.IssuerURL == nil } @@ -21,7 +21,7 @@ func NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePr } oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig - if ShouldDefaultOidcConfig(oidcConfig) { + if shouldDefaultOidcConfig(oidcConfig) { oidcConfig = gardener.OIDCConfig{ ClientID: &clientID, GroupsClaim: &groupsClaim, @@ -37,14 +37,10 @@ func NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePr } } func CanEnableExtension(runtime imv1.Runtime) bool { - canEnable := true - createdByMigrator := runtime.Labels["operator.kyma-project.io/created-by-migrator"] - - if createdByMigrator == "true" { - canEnable = false + if runtime.Labels["operator.kyma-project.io/created-by-migrator"] == "true" { + return false } - - return canEnable + return true } func setOIDCExtension(shoot *gardener.Shoot) { From 806497a52551981f2ca4c1c3c1f4d3269f8cf665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 1 Oct 2024 09:14:52 +0200 Subject: [PATCH 25/36] applying review remarks --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 15 --------------- internal/gardener/shoot/extender/oidc.go | 6 ++---- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 05bd5dc2..fc999f69 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -9,7 +9,6 @@ import ( imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" - "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -51,13 +50,6 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct } defaultAdditionalOidcIfNotPresent(&s.instance, m.RCCfg) - validationError := validateOidcConfiguration(s.instance) - if validationError != nil { - m.log.Error(validationError, "default OIDC configuration is not present") - updateConditionFailed(&s.instance) - return updateStatusAndStopWithError(validationError) - } - err := recreateOpenIDConnectResources(ctx, m, s) if err != nil { @@ -77,13 +69,6 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return switchState(sFnApplyClusterRoleBindings) } -func validateOidcConfiguration(rt imv1.Runtime) (err error) { - if rt.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig == nil { - err = errors.New("default OIDC configuration is not present") - } - return err -} - func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { srscClient := m.ShootClient.SubResource("adminkubeconfig") shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) diff --git a/internal/gardener/shoot/extender/oidc.go b/internal/gardener/shoot/extender/oidc.go index 992ff0b4..c670a83a 100644 --- a/internal/gardener/shoot/extender/oidc.go +++ b/internal/gardener/shoot/extender/oidc.go @@ -36,11 +36,9 @@ func NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePr return nil } } + func CanEnableExtension(runtime imv1.Runtime) bool { - if runtime.Labels["operator.kyma-project.io/created-by-migrator"] == "true" { - return false - } - return true + return runtime.Labels["operator.kyma-project.io/created-by-migrator"] != "true" } func setOIDCExtension(shoot *gardener.Shoot) { From a1751fa5fb3f822d260c050ef31efd0561e71a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 1 Oct 2024 11:47:58 +0200 Subject: [PATCH 26/36] extends ConverterConfig to be InfrastructureManagerConfig --- cmd/main.go | 14 ++-- internal/InfrastructureManagerConfig.go | 74 +++++++++++++++++++ .../controller/runtime/fsm/runtime_fsm.go | 6 +- .../runtime/fsm/runtime_fsm_configure_oidc.go | 6 +- .../runtime/fsm/runtime_fsm_create_shoot.go | 2 +- .../fsm/runtime_fsm_create_shoot_dry_run.go | 2 +- .../runtime/fsm/runtime_fsm_patch_shoot.go | 6 +- .../runtime/fsm/runtime_fsm_persist_shoot.go | 2 +- .../fsm/runtime_fsm_persist_shoot_test.go | 4 +- .../controller/runtime/fsm/utilz_for_test.go | 4 +- internal/controller/runtime/suite_test.go | 17 +++-- internal/gardener/shoot/converter.go | 72 +----------------- internal/gardener/shoot/converter_test.go | 37 +++++----- 13 files changed, 128 insertions(+), 118 deletions(-) create mode 100644 internal/InfrastructureManagerConfig.go diff --git a/cmd/main.go b/cmd/main.go index 4715be7f..612a145e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -20,6 +20,7 @@ import ( "encoding/json" "flag" "fmt" + "github.com/kyma-project/infrastructure-manager/internal" "io" "os" "time" @@ -36,7 +37,6 @@ import ( "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" "github.com/kyma-project/infrastructure-manager/internal/gardener" "github.com/kyma-project/infrastructure-manager/internal/gardener/kubeconfig" - "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "github.com/pkg/errors" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime" @@ -165,7 +165,7 @@ func main() { getReader := func() (io.Reader, error) { return os.Open(converterConfigFilepath) } - var converterConfig shoot.ConverterConfig + var converterConfig internal.InfrastructureManagerConfig if err = converterConfig.Load(getReader); err != nil { setupLog.Error(err, "unable to load converter configuration") os.Exit(1) @@ -177,17 +177,17 @@ func main() { os.Exit(1) } - err = validateAuditLogConfiguration(converterConfig.AuditLog.TenantConfigPath) + err = validateAuditLogConfiguration(converterConfig.Converter.AuditLog.TenantConfigPath) if err != nil { setupLog.Error(err, "invalid Audit Log configuration") os.Exit(1) } cfg := fsm.RCCfg{ - Finalizer: infrastructuremanagerv1.Finalizer, - ShootNamesapace: gardenerNamespace, - ConverterConfig: converterConfig, - AuditLogMandatory: auditLogMandatory, + Finalizer: infrastructuremanagerv1.Finalizer, + ShootNamesapace: gardenerNamespace, + InfrastructureManagerConfig: converterConfig, + AuditLogMandatory: auditLogMandatory, } if shootSpecDumpEnabled { cfg.PVCPath = "/testdata/kim" diff --git a/internal/InfrastructureManagerConfig.go b/internal/InfrastructureManagerConfig.go new file mode 100644 index 00000000..030a9445 --- /dev/null +++ b/internal/InfrastructureManagerConfig.go @@ -0,0 +1,74 @@ +package internal + +import ( + "encoding/json" + "io" +) + +type InfrastructureManagerConfig struct { + Converter ConverterConfig `json:"converter" validate:"required"` + DefaultSharedIASTenant OidcProvider `json:"defaultSharedIASTenant" validate:"required"` +} + +type ProviderConfig struct { + AWS AWSConfig `json:"aws"` +} + +type AWSConfig struct { + EnableIMDSv2 bool `json:"enableIMDSv2"` +} + +type DNSConfig struct { + SecretName string `json:"secretName" validate:"required"` + DomainPrefix string `json:"domainPrefix" validate:"required"` + ProviderType string `json:"providerType" validate:"required"` +} + +type KubernetesConfig struct { + DefaultVersion string `json:"defaultVersion" validate:"required"` + EnableKubernetesVersionAutoUpdate bool `json:"enableKubernetesVersionAutoUpdate"` + EnableMachineImageVersionAutoUpdate bool `json:"enableMachineImageVersionVersionAutoUpdate"` + DefaultOperatorOidc OidcProvider `json:"defaultOperatorOidc" validate:"required"` +} + +type OidcProvider struct { + ClientID string `json:"clientID" validate:"required"` + GroupsClaim string `json:"groupsClaim" validate:"required"` + IssuerURL string `json:"issuerURL" validate:"required"` + SigningAlgs []string `json:"signingAlgs" validate:"required"` + UsernameClaim string `json:"usernameClaim" validate:"required"` + UsernamePrefix string `json:"usernamePrefix" validate:"required"` +} + +type AuditLogConfig struct { + PolicyConfigMapName string `json:"policyConfigMapName" validate:"required"` + TenantConfigPath string `json:"tenantConfigPath" validate:"required"` +} + +type GardenerConfig struct { + ProjectName string `json:"projectName" validate:"required"` +} + +type MachineImageConfig struct { + DefaultName string `json:"defaultName" validate:"required"` + DefaultVersion string `json:"defaultVersion" validate:"required"` +} + +type ConverterConfig struct { + Kubernetes KubernetesConfig `json:"kubernetes" validate:"required"` + DNS DNSConfig `json:"dns" validate:"required"` + Provider ProviderConfig `json:"provider"` + MachineImage MachineImageConfig `json:"machineImage" validate:"required"` + Gardener GardenerConfig `json:"gardener" validate:"required"` + AuditLog AuditLogConfig `json:"auditLogging" validate:"required"` +} + +type ReaderGetter = func() (io.Reader, error) + +func (c *InfrastructureManagerConfig) Load(f ReaderGetter) error { + r, err := f() + if err != nil { + return err + } + return json.NewDecoder(r).Decode(c) +} diff --git a/internal/controller/runtime/fsm/runtime_fsm.go b/internal/controller/runtime/fsm/runtime_fsm.go index bc9d1a14..b5ef9e38 100644 --- a/internal/controller/runtime/fsm/runtime_fsm.go +++ b/internal/controller/runtime/fsm/runtime_fsm.go @@ -3,6 +3,7 @@ package fsm import ( "context" "fmt" + "github.com/kyma-project/infrastructure-manager/internal" "io" "reflect" "runtime" @@ -11,7 +12,6 @@ import ( "github.com/go-logr/logr" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" - "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -34,7 +34,7 @@ type RCCfg struct { PVCPath string ShootNamesapace string AuditLogMandatory bool - shoot.ConverterConfig + internal.InfrastructureManagerConfig } func (f stateFn) String() string { @@ -108,6 +108,6 @@ func NewFsm(log logr.Logger, cfg RCCfg, k8s K8s) Fsm { RCCfg: cfg, log: log, K8s: k8s, - AuditLogging: auditlogging.NewAuditLogging(cfg.AuditLog.TenantConfigPath, cfg.AuditLog.PolicyConfigMapName, k8s.ShootClient), + AuditLogging: auditlogging.NewAuditLogging(cfg.InfrastructureManagerConfig.Converter.AuditLog.TenantConfigPath, cfg.InfrastructureManagerConfig.Converter.AuditLog.PolicyConfigMapName, k8s.ShootClient), } } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index fc999f69..3776a52d 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,11 +3,11 @@ package fsm import ( "context" "fmt" + "github.com/kyma-project/infrastructure-manager/internal" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -19,13 +19,13 @@ func defaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { if additionalOidcConfig == nil { additionalOidcConfig = &[]gardener.OIDCConfig{} - defaultOIDCConfig := createDefaultOIDCConfig(cfg.Kubernetes.DefaultSharedIASTenant) + defaultOIDCConfig := createDefaultOIDCConfig(cfg.DefaultSharedIASTenant) *additionalOidcConfig = append(*additionalOidcConfig, defaultOIDCConfig) runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig } } -func createDefaultOIDCConfig(defaultSharedIASTenant shoot.OidcProvider) gardener.OIDCConfig { +func createDefaultOIDCConfig(defaultSharedIASTenant internal.OidcProvider) gardener.OIDCConfig { return gardener.OIDCConfig{ ClientID: &defaultSharedIASTenant.ClientID, GroupsClaim: &defaultSharedIASTenant.GroupsClaim, diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go index 9269c07c..8ad2a957 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go @@ -11,7 +11,7 @@ import ( func sFnCreateShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create shoot state") - newShoot, err := convertShoot(&s.instance, m.ConverterConfig) + newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object") return updateStatePendingWithErrorAndStop( diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go b/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go index 61a021f7..3962b27d 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go @@ -10,7 +10,7 @@ import ( func sFnCreateShootDryRun(_ context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create shoot [dry-run]") - newShoot, err := convertShoot(&s.instance, m.ConverterConfig) + newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object [dry-run]") return updateStatePendingWithErrorAndStop( diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index a43e1e42..592194dd 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -2,10 +2,10 @@ package fsm import ( "context" + "github.com/kyma-project/infrastructure-manager/internal" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" @@ -15,7 +15,7 @@ import ( func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Patch shoot state") - updatedShoot, err := convertShoot(&s.instance, m.ConverterConfig) + updatedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object, exiting with no retry") return updateStatePendingWithErrorAndStop(&s.instance, imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonConversionError, "Runtime conversion error") @@ -52,7 +52,7 @@ func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn return updateStatusAndRequeueAfter(gardenerRequeueDuration) } -func convertShoot(instance *imv1.Runtime, cfg shoot.ConverterConfig) (gardener.Shoot, error) { +func convertShoot(instance *imv1.Runtime, cfg internal.ConverterConfig) (gardener.Shoot, error) { if err := instance.ValidateRequiredLabels(); err != nil { return gardener.Shoot{}, err } diff --git a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go index f5ac9a27..bf3e9c58 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go @@ -42,7 +42,7 @@ func sFnDumpShootSpec(_ context.Context, m *fsm, s *systemState) (stateFn, *ctrl // To make comparison easier we don't store object obtained from the cluster as it contains additional fields that are not relevant for the comparison. // We use object created by the converter instead (the Provisioner uses the same approach) - convertedShoot, err := convertShoot(&s.instance, m.ConverterConfig) + convertedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) if err != nil { return updateStatusAndStopWithError(err) } diff --git a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go index 5fee081d..942285ee 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go @@ -3,12 +3,12 @@ package fsm import ( "bytes" "context" + "github.com/kyma-project/infrastructure-manager/internal" "io" "time" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm/testing" - "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive "sigs.k8s.io/yaml" @@ -30,7 +30,7 @@ var _ = Describe("KIM sFnPersist", func() { expectedRuntime.Spec.Shoot.Provider.Type = "aws" It("should persist shoot data", func() { - next, _, err := sFnDumpShootSpec(testCtx, must(newFakeFSM, withStorageWriter(testWriterGetter), withConverterConfig(shoot.ConverterConfig{})), &systemState{shoot: &testing.ShootNoDNS, instance: *expectedRuntime}) + next, _, err := sFnDumpShootSpec(testCtx, must(newFakeFSM, withStorageWriter(testWriterGetter), withConverterConfig(internal.ConverterConfig{})), &systemState{shoot: &testing.ShootNoDNS, instance: *expectedRuntime}) Expect(err).To(BeNil()) Expect(next).To(haveName("sFnUpdateStatus")) diff --git a/internal/controller/runtime/fsm/utilz_for_test.go b/internal/controller/runtime/fsm/utilz_for_test.go index 9e92a2ef..d2358311 100644 --- a/internal/controller/runtime/fsm/utilz_for_test.go +++ b/internal/controller/runtime/fsm/utilz_for_test.go @@ -3,10 +3,10 @@ package fsm import ( "context" "fmt" + "github.com/kyma-project/infrastructure-manager/internal" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" - "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,7 +44,7 @@ var ( } } - withConverterConfig = func(config shoot.ConverterConfig) fakeFSMOpt { + withConverterConfig = func(config internal.ConverterConfig) fakeFSMOpt { return func(fsm *fsm) error { fsm.ConverterConfig = config return nil diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index 01fa28ff..27c3fc64 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -19,6 +19,7 @@ package runtime import ( "context" "encoding/json" + "github.com/kyma-project/infrastructure-manager/internal" "path/filepath" "testing" "time" @@ -331,26 +332,26 @@ func setupSeedObjectOnCluster(client client.Client) error { return client.Create(context.Background(), seed) } -func fixConverterConfigForTests() gardener_shoot.ConverterConfig { - return gardener_shoot.ConverterConfig{ - Kubernetes: gardener_shoot.KubernetesConfig{ +func fixConverterConfigForTests() internal.ConverterConfig { + return internal.ConverterConfig{ + Kubernetes: internal.KubernetesConfig{ DefaultVersion: "1.29", }, - DNS: gardener_shoot.DNSConfig{ + DNS: internal.DNSConfig{ SecretName: "aws-route53-secret-dev", DomainPrefix: "dev.kyma.ondemand.com", ProviderType: "aws-route53", }, - Provider: gardener_shoot.ProviderConfig{ - AWS: gardener_shoot.AWSConfig{ + Provider: internal.ProviderConfig{ + AWS: internal.AWSConfig{ EnableIMDSv2: true, }, }, - Gardener: gardener_shoot.GardenerConfig{ + Gardener: internal.GardenerConfig{ ProjectName: "kyma-dev", }, - AuditLog: gardener_shoot.AuditLogConfig{ + AuditLog: internal.AuditLogConfig{ PolicyConfigMapName: "policy-config-map", TenantConfigPath: filepath.Join("testdata", "auditConfig.json"), }, diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index bcaf7405..2c197c5e 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -1,12 +1,10 @@ package shoot import ( - "encoding/json" "fmt" - "io" - gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -15,74 +13,10 @@ type Extend func(imv1.Runtime, *gardener.Shoot) error type Converter struct { extenders []Extend - config ConverterConfig -} - -type ProviderConfig struct { - AWS AWSConfig `json:"aws"` -} - -type AWSConfig struct { - EnableIMDSv2 bool `json:"enableIMDSv2"` -} - -type DNSConfig struct { - SecretName string `json:"secretName" validate:"required"` - DomainPrefix string `json:"domainPrefix" validate:"required"` - ProviderType string `json:"providerType" validate:"required"` -} - -type KubernetesConfig struct { - DefaultVersion string `json:"defaultVersion" validate:"required"` - EnableKubernetesVersionAutoUpdate bool `json:"enableKubernetesVersionAutoUpdate"` - EnableMachineImageVersionAutoUpdate bool `json:"enableMachineImageVersionVersionAutoUpdate"` - DefaultOperatorOidc OidcProvider `json:"defaultOperatorOidc" validate:"required"` - DefaultSharedIASTenant OidcProvider `json:"defaultSharedIASTenant" validate:"required"` -} - -type OidcProvider struct { - ClientID string `json:"clientID" validate:"required"` - GroupsClaim string `json:"groupsClaim" validate:"required"` - IssuerURL string `json:"issuerURL" validate:"required"` - SigningAlgs []string `json:"signingAlgs" validate:"required"` - UsernameClaim string `json:"usernameClaim" validate:"required"` - UsernamePrefix string `json:"usernamePrefix" validate:"required"` -} - -type AuditLogConfig struct { - PolicyConfigMapName string `json:"policyConfigMapName" validate:"required"` - TenantConfigPath string `json:"tenantConfigPath" validate:"required"` -} - -type ReaderGetter = func() (io.Reader, error) - -type ConverterConfig struct { - Kubernetes KubernetesConfig `json:"kubernetes" validate:"required"` - DNS DNSConfig `json:"dns" validate:"required"` - Provider ProviderConfig `json:"provider"` - MachineImage MachineImageConfig `json:"machineImage" validate:"required"` - Gardener GardenerConfig `json:"gardener" validate:"required"` - AuditLog AuditLogConfig `json:"auditLogging" validate:"required"` -} - -func (c *ConverterConfig) Load(f ReaderGetter) error { - r, err := f() - if err != nil { - return err - } - return json.NewDecoder(r).Decode(c) -} - -type GardenerConfig struct { - ProjectName string `json:"projectName" validate:"required"` -} - -type MachineImageConfig struct { - DefaultName string `json:"defaultName" validate:"required"` - DefaultVersion string `json:"defaultVersion" validate:"required"` + config internal.ConverterConfig } -func NewConverter(config ConverterConfig) Converter { +func NewConverter(config internal.ConverterConfig) Converter { extenders := []Extend{ extender.ExtendWithAnnotations, extender.ExtendWithLabels, diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index 810f311c..e1b9faba 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -2,6 +2,7 @@ package shoot import ( "fmt" + "github.com/kyma-project/infrastructure-manager/internal" "io" "strings" "testing" @@ -37,20 +38,20 @@ func TestConverter(t *testing.T) { }) } -func fixConverterConfig() ConverterConfig { - return ConverterConfig{ - Kubernetes: KubernetesConfig{ +func fixConverterConfig() internal.ConverterConfig { + return internal.ConverterConfig{ + Kubernetes: internal.KubernetesConfig{ DefaultVersion: "1.29", EnableKubernetesVersionAutoUpdate: true, EnableMachineImageVersionAutoUpdate: false, }, - DNS: DNSConfig{ + DNS: internal.DNSConfig{ SecretName: "dns-secret", DomainPrefix: "dev.mydomain.com", ProviderType: "aws-route53", }, - Provider: ProviderConfig{ - AWS: AWSConfig{ + Provider: internal.ProviderConfig{ + AWS: internal.AWSConfig{ EnableIMDSv2: true, }, }, @@ -128,7 +129,7 @@ func Test_ConverterConfig_Load_Err(t *testing.T) { failingReaderGetter := func() (io.Reader, error) { return nil, errTestReaderGetterFailed } - var cfg ConverterConfig + var cfg internal.ConverterConfig if err := cfg.Load(failingReaderGetter); err != errTestReaderGetterFailed { t.Error("ConverterConfig load should fail") } @@ -183,17 +184,17 @@ func Test_ConverterConfig_Load_OK(t *testing.T) { readerGetter := func() (io.Reader, error) { return testReader, nil } - var cfg ConverterConfig + var cfg internal.ConverterConfig if err := cfg.Load(readerGetter); err != nil { t.Errorf("ConverterConfig load failed: %s", err) } - expected := ConverterConfig{ - Kubernetes: KubernetesConfig{ + expected := internal.ConverterConfig{ + Kubernetes: internal.KubernetesConfig{ DefaultVersion: "0.1.2.3", EnableKubernetesVersionAutoUpdate: true, EnableMachineImageVersionAutoUpdate: false, - DefaultOperatorOidc: OidcProvider{ + DefaultOperatorOidc: internal.OidcProvider{ ClientID: "test-clientID", GroupsClaim: "test-group", IssuerURL: "test-issuer-url", @@ -201,7 +202,7 @@ func Test_ConverterConfig_Load_OK(t *testing.T) { UsernameClaim: "test-username-claim", UsernamePrefix: "-", }, - DefaultSharedIASTenant: OidcProvider{ + DefaultSharedIASTenant: internal.OidcProvider{ ClientID: "test-clientID", GroupsClaim: "test-group", IssuerURL: "test-issuer-url", @@ -210,24 +211,24 @@ func Test_ConverterConfig_Load_OK(t *testing.T) { UsernamePrefix: "-", }, }, - DNS: DNSConfig{ + DNS: internal.DNSConfig{ SecretName: "test-secret-name", DomainPrefix: "test-domain-prefix", ProviderType: "test-provider-type", }, - Provider: ProviderConfig{ - AWS: AWSConfig{ + Provider: internal.ProviderConfig{ + AWS: internal.AWSConfig{ EnableIMDSv2: true, }, }, - MachineImage: MachineImageConfig{ + MachineImage: internal.MachineImageConfig{ DefaultName: "test-image-name", DefaultVersion: "0.1.2.3.4", }, - Gardener: GardenerConfig{ + Gardener: internal.GardenerConfig{ ProjectName: "test-project", }, - AuditLog: AuditLogConfig{ + AuditLog: internal.AuditLogConfig{ PolicyConfigMapName: "test-policy", TenantConfigPath: "test-path", }, From 233f13fb04efffef6e3329a961582e5b5fb5b20b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 1 Oct 2024 13:13:11 +0200 Subject: [PATCH 27/36] NewOidcExtender uses InfrastructureManagerConfig.OidcProvider --- config/manager/metrics.yaml | 2 +- internal/gardener/shoot/converter.go | 7 +------ internal/gardener/shoot/extender/oidc.go | 15 ++++++++------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/config/manager/metrics.yaml b/config/manager/metrics.yaml index c75da51c..77f3605d 100644 --- a/config/manager/metrics.yaml +++ b/config/manager/metrics.yaml @@ -1,4 +1,4 @@ -apiVersion: v1 +x`apiVersion: v1 kind: Service metadata: labels: diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index 2c197c5e..c920014a 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -23,12 +23,7 @@ func NewConverter(config internal.ConverterConfig) Converter { extender.NewKubernetesExtender(config.Kubernetes.DefaultVersion), extender.NewProviderExtender(config.Provider.AWS.EnableIMDSv2, config.MachineImage.DefaultName, config.MachineImage.DefaultVersion), extender.NewDNSExtender(config.DNS.SecretName, config.DNS.DomainPrefix, config.DNS.ProviderType), - extender.NewOidcExtender(config.Kubernetes.DefaultOperatorOidc.ClientID, - config.Kubernetes.DefaultOperatorOidc.GroupsClaim, - config.Kubernetes.DefaultOperatorOidc.IssuerURL, - config.Kubernetes.DefaultOperatorOidc.UsernameClaim, - config.Kubernetes.DefaultOperatorOidc.UsernamePrefix, - config.Kubernetes.DefaultOperatorOidc.SigningAlgs), + extender.NewOidcExtender(config.Kubernetes.DefaultOperatorOidc), extender.ExtendWithCloudProfile, extender.ExtendWithNetworkFilter, extender.ExtendWithCertConfig, diff --git a/internal/gardener/shoot/extender/oidc.go b/internal/gardener/shoot/extender/oidc.go index c670a83a..39117eac 100644 --- a/internal/gardener/shoot/extender/oidc.go +++ b/internal/gardener/shoot/extender/oidc.go @@ -3,6 +3,7 @@ package extender import ( gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "k8s.io/utils/ptr" ) @@ -14,7 +15,7 @@ func shouldDefaultOidcConfig(config gardener.OIDCConfig) bool { return config.ClientID == nil && config.IssuerURL == nil } -func NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePrefix string, signingAlgs []string) func(runtime imv1.Runtime, shoot *gardener.Shoot) error { +func NewOidcExtender(oidcProvider internal.OidcProvider) func(runtime imv1.Runtime, shoot *gardener.Shoot) error { return func(runtime imv1.Runtime, shoot *gardener.Shoot) error { if CanEnableExtension(runtime) { setOIDCExtension(shoot) @@ -23,12 +24,12 @@ func NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePr oidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.OidcConfig if shouldDefaultOidcConfig(oidcConfig) { oidcConfig = gardener.OIDCConfig{ - ClientID: &clientID, - GroupsClaim: &groupsClaim, - IssuerURL: &issuerURL, - SigningAlgs: signingAlgs, - UsernameClaim: &usernameClaim, - UsernamePrefix: &usernamePrefix, + ClientID: &oidcProvider.ClientID, + GroupsClaim: &oidcProvider.GroupsClaim, + IssuerURL: &oidcProvider.IssuerURL, + SigningAlgs: oidcProvider.SigningAlgs, + UsernameClaim: &oidcProvider.UsernameClaim, + UsernamePrefix: &oidcProvider.UsernamePrefix, } } setKubeAPIServerOIDCConfig(shoot, oidcConfig) From 25a113356d946ecf3fecbb89215c5c438574f82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 1 Oct 2024 15:13:11 +0200 Subject: [PATCH 28/36] InfrastructureManagerConfig.Converter refactoring --- cmd/main.go | 4 +- internal/InfrastructureManagerConfig.go | 2 +- .../controller/runtime/fsm/runtime_fsm.go | 4 +- .../runtime/fsm/runtime_fsm_configure_oidc.go | 2 +- .../runtime/fsm/runtime_fsm_create_shoot.go | 2 +- .../fsm/runtime_fsm_create_shoot_dry_run.go | 2 +- .../runtime/fsm/runtime_fsm_patch_shoot.go | 4 +- .../runtime/fsm/runtime_fsm_persist_shoot.go | 2 +- .../fsm/runtime_fsm_persist_shoot_test.go | 2 +- .../controller/runtime/fsm/utilz_for_test.go | 4 +- internal/controller/runtime/suite_test.go | 50 +++++------ internal/gardener/shoot/converter.go | 1 + internal/gardener/shoot/converter_test.go | 86 ++++++++++--------- internal/gardener/shoot/extender/oidc_test.go | 27 +++--- 14 files changed, 100 insertions(+), 92 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 612a145e..91b53790 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -20,7 +20,6 @@ import ( "encoding/json" "flag" "fmt" - "github.com/kyma-project/infrastructure-manager/internal" "io" "os" "time" @@ -30,6 +29,7 @@ import ( gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "github.com/go-playground/validator/v10" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" kubeconfig_controller "github.com/kyma-project/infrastructure-manager/internal/controller/kubeconfig" "github.com/kyma-project/infrastructure-manager/internal/controller/metrics" @@ -177,7 +177,7 @@ func main() { os.Exit(1) } - err = validateAuditLogConfiguration(converterConfig.Converter.AuditLog.TenantConfigPath) + err = validateAuditLogConfiguration(converterConfig.ConverterConfig.AuditLog.TenantConfigPath) if err != nil { setupLog.Error(err, "invalid Audit Log configuration") os.Exit(1) diff --git a/internal/InfrastructureManagerConfig.go b/internal/InfrastructureManagerConfig.go index 030a9445..246f4344 100644 --- a/internal/InfrastructureManagerConfig.go +++ b/internal/InfrastructureManagerConfig.go @@ -6,7 +6,7 @@ import ( ) type InfrastructureManagerConfig struct { - Converter ConverterConfig `json:"converter" validate:"required"` + ConverterConfig ConverterConfig `json:"converter" validate:"required"` DefaultSharedIASTenant OidcProvider `json:"defaultSharedIASTenant" validate:"required"` } diff --git a/internal/controller/runtime/fsm/runtime_fsm.go b/internal/controller/runtime/fsm/runtime_fsm.go index b5ef9e38..4c324b59 100644 --- a/internal/controller/runtime/fsm/runtime_fsm.go +++ b/internal/controller/runtime/fsm/runtime_fsm.go @@ -3,7 +3,6 @@ package fsm import ( "context" "fmt" - "github.com/kyma-project/infrastructure-manager/internal" "io" "reflect" "runtime" @@ -11,6 +10,7 @@ import ( "github.com/go-logr/logr" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" @@ -108,6 +108,6 @@ func NewFsm(log logr.Logger, cfg RCCfg, k8s K8s) Fsm { RCCfg: cfg, log: log, K8s: k8s, - AuditLogging: auditlogging.NewAuditLogging(cfg.InfrastructureManagerConfig.Converter.AuditLog.TenantConfigPath, cfg.InfrastructureManagerConfig.Converter.AuditLog.PolicyConfigMapName, k8s.ShootClient), + AuditLogging: auditlogging.NewAuditLogging(cfg.InfrastructureManagerConfig.ConverterConfig.AuditLog.TenantConfigPath, cfg.InfrastructureManagerConfig.ConverterConfig.AuditLog.PolicyConfigMapName, k8s.ShootClient), } } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 3776a52d..5e1a4023 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,11 +3,11 @@ package fsm import ( "context" "fmt" - "github.com/kyma-project/infrastructure-manager/internal" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go index 8ad2a957..8bed7950 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go @@ -11,7 +11,7 @@ import ( func sFnCreateShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create shoot state") - newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) + newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object") return updateStatePendingWithErrorAndStop( diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go b/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go index 3962b27d..80fd7bd3 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go @@ -10,7 +10,7 @@ import ( func sFnCreateShootDryRun(_ context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create shoot [dry-run]") - newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) + newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object [dry-run]") return updateStatePendingWithErrorAndStop( diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index 592194dd..3829c549 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -2,10 +2,10 @@ package fsm import ( "context" - "github.com/kyma-project/infrastructure-manager/internal" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" @@ -15,7 +15,7 @@ import ( func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Patch shoot state") - updatedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) + updatedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object, exiting with no retry") return updateStatePendingWithErrorAndStop(&s.instance, imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonConversionError, "Runtime conversion error") diff --git a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go index bf3e9c58..d473f0e9 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go @@ -42,7 +42,7 @@ func sFnDumpShootSpec(_ context.Context, m *fsm, s *systemState) (stateFn, *ctrl // To make comparison easier we don't store object obtained from the cluster as it contains additional fields that are not relevant for the comparison. // We use object created by the converter instead (the Provisioner uses the same approach) - convertedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.Converter) + convertedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) if err != nil { return updateStatusAndStopWithError(err) } diff --git a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go index 942285ee..567df824 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go @@ -3,11 +3,11 @@ package fsm import ( "bytes" "context" - "github.com/kyma-project/infrastructure-manager/internal" "io" "time" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm/testing" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive diff --git a/internal/controller/runtime/fsm/utilz_for_test.go b/internal/controller/runtime/fsm/utilz_for_test.go index d2358311..98c97900 100644 --- a/internal/controller/runtime/fsm/utilz_for_test.go +++ b/internal/controller/runtime/fsm/utilz_for_test.go @@ -3,10 +3,10 @@ package fsm import ( "context" "fmt" - "github.com/kyma-project/infrastructure-manager/internal" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/kyma-project/infrastructure-manager/internal" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -46,7 +46,7 @@ var ( withConverterConfig = func(config internal.ConverterConfig) fakeFSMOpt { return func(fsm *fsm) error { - fsm.ConverterConfig = config + fsm.InfrastructureManagerConfig.ConverterConfig = config return nil } } diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index 27c3fc64..42b0222c 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -19,7 +19,6 @@ package runtime import ( "context" "encoding/json" - "github.com/kyma-project/infrastructure-manager/internal" "path/filepath" "testing" "time" @@ -27,6 +26,7 @@ import ( gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" @@ -109,7 +109,7 @@ var _ = BeforeSuite(func() { customTracker = NewCustomTracker(tracker, []*gardener_api.Shoot{}, []*gardener_api.Seed{}) gardenerTestClient = fake.NewClientBuilder().WithScheme(clientScheme).WithObjectTracker(customTracker).Build() - runtimeReconciler = NewRuntimeReconciler(mgr, gardenerTestClient, logger, fsm.RCCfg{Finalizer: infrastructuremanagerv1.Finalizer, ConverterConfig: fixConverterConfigForTests()}) + runtimeReconciler = NewRuntimeReconciler(mgr, gardenerTestClient, logger, fsm.RCCfg{Finalizer: infrastructuremanagerv1.Finalizer, InfrastructureManagerConfig: fixConverterConfigForTests()}) Expect(runtimeReconciler).NotTo(BeNil()) err = runtimeReconciler.SetupWithManager(mgr) Expect(err).To(BeNil()) @@ -176,8 +176,8 @@ func setupGardenerClientWithSequence(shoots []*gardener_api.Shoot, seeds []*gard func getBaseShootForTestingSequence() gardener_api.Shoot { runtimeStub := CreateRuntimeStub("test-resource") - converterConfig := fixConverterConfigForTests() - converter := gardener_shoot.NewConverter(converterConfig) + infrastructureManagerConfig := fixConverterConfigForTests() + converter := gardener_shoot.NewConverter(infrastructureManagerConfig.ConverterConfig) convertedShoot, err := converter.ToShoot(*runtimeStub) if err != nil { panic(err) @@ -332,28 +332,30 @@ func setupSeedObjectOnCluster(client client.Client) error { return client.Create(context.Background(), seed) } -func fixConverterConfigForTests() internal.ConverterConfig { - return internal.ConverterConfig{ - Kubernetes: internal.KubernetesConfig{ - DefaultVersion: "1.29", - }, +func fixConverterConfigForTests() internal.InfrastructureManagerConfig { + return internal.InfrastructureManagerConfig{ + ConverterConfig: internal.ConverterConfig{ + Kubernetes: internal.KubernetesConfig{ + DefaultVersion: "1.29", + }, - DNS: internal.DNSConfig{ - SecretName: "aws-route53-secret-dev", - DomainPrefix: "dev.kyma.ondemand.com", - ProviderType: "aws-route53", - }, - Provider: internal.ProviderConfig{ - AWS: internal.AWSConfig{ - EnableIMDSv2: true, + DNS: internal.DNSConfig{ + SecretName: "aws-route53-secret-dev", + DomainPrefix: "dev.kyma.ondemand.com", + ProviderType: "aws-route53", + }, + Provider: internal.ProviderConfig{ + AWS: internal.AWSConfig{ + EnableIMDSv2: true, + }, + }, + Gardener: internal.GardenerConfig{ + ProjectName: "kyma-dev", + }, + AuditLog: internal.AuditLogConfig{ + PolicyConfigMapName: "policy-config-map", + TenantConfigPath: filepath.Join("testdata", "auditConfig.json"), }, - }, - Gardener: internal.GardenerConfig{ - ProjectName: "kyma-dev", - }, - AuditLog: internal.AuditLogConfig{ - PolicyConfigMapName: "policy-config-map", - TenantConfigPath: filepath.Join("testdata", "auditConfig.json"), }, } } diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index c920014a..8c41f194 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -2,6 +2,7 @@ package shoot import ( "fmt" + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal" diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index e1b9faba..50a341c4 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -2,7 +2,6 @@ package shoot import ( "fmt" - "github.com/kyma-project/infrastructure-manager/internal" "io" "strings" "testing" @@ -10,6 +9,7 @@ import ( gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/go-playground/validator/v10" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/hyperscaler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -129,7 +129,7 @@ func Test_ConverterConfig_Load_Err(t *testing.T) { failingReaderGetter := func() (io.Reader, error) { return nil, errTestReaderGetterFailed } - var cfg internal.ConverterConfig + var cfg internal.InfrastructureManagerConfig if err := cfg.Load(failingReaderGetter); err != errTestReaderGetterFailed { t.Error("ConverterConfig load should fail") } @@ -184,53 +184,55 @@ func Test_ConverterConfig_Load_OK(t *testing.T) { readerGetter := func() (io.Reader, error) { return testReader, nil } - var cfg internal.ConverterConfig + var cfg internal.InfrastructureManagerConfig if err := cfg.Load(readerGetter); err != nil { t.Errorf("ConverterConfig load failed: %s", err) } - expected := internal.ConverterConfig{ - Kubernetes: internal.KubernetesConfig{ - DefaultVersion: "0.1.2.3", - EnableKubernetesVersionAutoUpdate: true, - EnableMachineImageVersionAutoUpdate: false, - DefaultOperatorOidc: internal.OidcProvider{ - ClientID: "test-clientID", - GroupsClaim: "test-group", - IssuerURL: "test-issuer-url", - SigningAlgs: []string{"test-alg"}, - UsernameClaim: "test-username-claim", - UsernamePrefix: "-", + expected := internal.InfrastructureManagerConfig{ + DefaultSharedIASTenant: internal.OidcProvider{ + ClientID: "test-clientID", + GroupsClaim: "test-group", + IssuerURL: "test-issuer-url", + SigningAlgs: []string{"test-alg"}, + UsernameClaim: "test-username-claim", + UsernamePrefix: "-", + }, + ConverterConfig: internal.ConverterConfig{ + Kubernetes: internal.KubernetesConfig{ + DefaultVersion: "0.1.2.3", + EnableKubernetesVersionAutoUpdate: true, + EnableMachineImageVersionAutoUpdate: false, + DefaultOperatorOidc: internal.OidcProvider{ + ClientID: "test-clientID", + GroupsClaim: "test-group", + IssuerURL: "test-issuer-url", + SigningAlgs: []string{"test-alg"}, + UsernameClaim: "test-username-claim", + UsernamePrefix: "-", + }, }, - DefaultSharedIASTenant: internal.OidcProvider{ - ClientID: "test-clientID", - GroupsClaim: "test-group", - IssuerURL: "test-issuer-url", - SigningAlgs: []string{"test-alg"}, - UsernameClaim: "test-username-claim", - UsernamePrefix: "-", + DNS: internal.DNSConfig{ + SecretName: "test-secret-name", + DomainPrefix: "test-domain-prefix", + ProviderType: "test-provider-type", }, - }, - DNS: internal.DNSConfig{ - SecretName: "test-secret-name", - DomainPrefix: "test-domain-prefix", - ProviderType: "test-provider-type", - }, - Provider: internal.ProviderConfig{ - AWS: internal.AWSConfig{ - EnableIMDSv2: true, + Provider: internal.ProviderConfig{ + AWS: internal.AWSConfig{ + EnableIMDSv2: true, + }, + }, + MachineImage: internal.MachineImageConfig{ + DefaultName: "test-image-name", + DefaultVersion: "0.1.2.3.4", + }, + Gardener: internal.GardenerConfig{ + ProjectName: "test-project", + }, + AuditLog: internal.AuditLogConfig{ + PolicyConfigMapName: "test-policy", + TenantConfigPath: "test-path", }, - }, - MachineImage: internal.MachineImageConfig{ - DefaultName: "test-image-name", - DefaultVersion: "0.1.2.3.4", - }, - Gardener: internal.GardenerConfig{ - ProjectName: "test-project", - }, - AuditLog: internal.AuditLogConfig{ - PolicyConfigMapName: "test-policy", - TenantConfigPath: "test-path", }, } assert.Equal(t, expected, cfg) diff --git a/internal/gardener/shoot/extender/oidc_test.go b/internal/gardener/shoot/extender/oidc_test.go index 6b93e1c1..c84edfae 100644 --- a/internal/gardener/shoot/extender/oidc_test.go +++ b/internal/gardener/shoot/extender/oidc_test.go @@ -5,6 +5,7 @@ import ( gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -35,12 +36,14 @@ func TestOidcExtender(t *testing.T) { } { t.Run(testCase.name, func(t *testing.T) { // given - clientID := "client-id" - groupsClaim := "groups" - issuerURL := "https://my.cool.tokens.com" - usernameClaim := "sub" - usernamePrefix := "-" - signingAlgs := []string{"RS256"} + defaultOidc := internal.OidcProvider{ + ClientID: "client-id", + GroupsClaim: "groups", + IssuerURL: "https://my.cool.tokens.com", + SigningAlgs: []string{"RS256"}, + UsernameClaim: "sub", + UsernamePrefix: "-", + } shoot := fixEmptyGardenerShoot("test", "kcp-system") runtimeShoot := imv1.Runtime{ @@ -54,11 +57,11 @@ func TestOidcExtender(t *testing.T) { Kubernetes: imv1.Kubernetes{ KubeAPIServer: imv1.APIServer{ OidcConfig: gardener.OIDCConfig{ - ClientID: &clientID, - GroupsClaim: &groupsClaim, - IssuerURL: &issuerURL, - SigningAlgs: signingAlgs, - UsernameClaim: &usernameClaim, + ClientID: &defaultOidc.ClientID, + GroupsClaim: &defaultOidc.GroupsClaim, + IssuerURL: &defaultOidc.IssuerURL, + SigningAlgs: defaultOidc.SigningAlgs, + UsernameClaim: &defaultOidc.UsernameClaim, }, }, }, @@ -67,7 +70,7 @@ func TestOidcExtender(t *testing.T) { } // when - extender := NewOidcExtender(clientID, groupsClaim, issuerURL, usernameClaim, usernamePrefix, signingAlgs) + extender := NewOidcExtender(defaultOidc) err := extender(runtimeShoot, &shoot) // then From b764bcd0bd4e1cd0034df1c3be89ec0715f0b28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Tue, 1 Oct 2024 16:50:27 +0200 Subject: [PATCH 29/36] deletes OpenIDConnect CRs using label selector --- .../runtime/fsm/runtime_fsm_configure_oidc.go | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 5e1a4023..350e4338 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -12,6 +12,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + k8s_client "sigs.k8s.io/controller-runtime/pkg/client" ) func defaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { @@ -92,19 +93,9 @@ func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) } func deleteExistingKymaOpenIDConnectResources(ctx context.Context, client client.Client) (err error) { - oidcList := &authenticationv1alpha1.OpenIDConnectList{} - if err = client.List(ctx, oidcList); err != nil { - return err - } - - for _, oidc := range oidcList.Items { - if _, ok := oidc.Labels[imv1.LabelKymaManagedBy]; ok { - err = client.Delete(ctx, &oidc) - if err != nil { - return err - } - } - } + err = client.DeleteAllOf(ctx, &authenticationv1alpha1.OpenIDConnect{}, k8s_client.MatchingLabels(map[string]string{ + imv1.LabelKymaManagedBy: "infrastructure-manager", + })) return err } From af160bf187d99eaaf3672f6057bea89caa426ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 2 Oct 2024 08:21:47 +0200 Subject: [PATCH 30/36] fixes Test_ConverterConfig_Load_OK --- internal/gardener/shoot/converter_test.go | 96 +++++++++++++---------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index 50a341c4..26f73206 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -135,49 +135,61 @@ func Test_ConverterConfig_Load_Err(t *testing.T) { } } -var testReader io.Reader = strings.NewReader(`{ - "kubernetes": { - "defaultVersion": "0.1.2.3", - "enableKubernetesVersionAutoUpdate": true, - "enableMachineImageVersionAutoUpdate": false, - "defaultOperatorOidc": { - "clientID": "test-clientID", - "groupsClaim": "test-group", - "issuerURL": "test-issuer-url", - "signingAlgs": ["test-alg"], - "usernameClaim": "test-username-claim", - "usernamePrefix": "-" - }, - "defaultSharedIASTenant": { - "clientID": "test-clientID", - "groupsClaim": "test-group", - "issuerURL": "test-issuer-url", - "signingAlgs": ["test-alg"], - "usernameClaim": "test-username-claim", - "usernamePrefix": "-" - } - }, - "dns": { - "secretName": "test-secret-name", - "domainPrefix": "test-domain-prefix", - "providerType": "test-provider-type" - }, - "provider": { - "aws": { - "enableIMDSv2": true - } - }, - "machineImage": { - "defaultName": "test-image-name", - "defaultVersion": "0.1.2.3.4" +var testReader io.Reader = strings.NewReader( + ` +{ + "defaultSharedIASTenant" : { + "clientID": "test-clientID", + "groupsClaim": "test-group", + "issuerURL": "test-issuer-url", + "signingAlgs": ["test-alg"], + "usernameClaim": "test-username-claim", + "usernamePrefix": "-" }, - "gardener": { - "projectName": "test-project" - }, - "auditLogging": { - "policyConfigMapName": "test-policy", - "tenantConfigPath": "test-path" - } + "converter": { + "kubernetes": { + "defaultVersion": "0.1.2.3", + "enableKubernetesVersionAutoUpdate": true, + "enableMachineImageVersionAutoUpdate": false, + "defaultOperatorOidc": { + "clientID": "test-clientID", + "groupsClaim": "test-group", + "issuerURL": "test-issuer-url", + "signingAlgs": ["test-alg"], + "usernameClaim": "test-username-claim", + "usernamePrefix": "-" + }, + "defaultSharedIASTenant": { + "clientID": "test-clientID", + "groupsClaim": "test-group", + "issuerURL": "test-issuer-url", + "signingAlgs": ["test-alg"], + "usernameClaim": "test-username-claim", + "usernamePrefix": "-" + } + }, + "dns": { + "secretName": "test-secret-name", + "domainPrefix": "test-domain-prefix", + "providerType": "test-provider-type" + }, + "provider": { + "aws": { + "enableIMDSv2": true + } + }, + "machineImage": { + "defaultName": "test-image-name", + "defaultVersion": "0.1.2.3.4" + }, + "gardener": { + "projectName": "test-project" + }, + "auditLogging": { + "policyConfigMapName": "test-policy", + "tenantConfigPath": "test-path" + } +} }`) func Test_ConverterConfig_Load_OK(t *testing.T) { From 44723b0d8d7b0362f36a533443a8af2849ec703f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 2 Oct 2024 08:34:44 +0200 Subject: [PATCH 31/36] fixes metrics.yaml --- config/manager/metrics.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/manager/metrics.yaml b/config/manager/metrics.yaml index 77f3605d..c75da51c 100644 --- a/config/manager/metrics.yaml +++ b/config/manager/metrics.yaml @@ -1,4 +1,4 @@ -x`apiVersion: v1 +apiVersion: v1 kind: Service metadata: labels: From e1ae536dc308318205f5334037f98287cfdc93e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 2 Oct 2024 12:11:14 +0200 Subject: [PATCH 32/36] adds oidc fsm testcase for disabled extension --- .../fsm/runtime_fsm_configure_oidc_test.go | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go new file mode 100644 index 00000000..094d8488 --- /dev/null +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go @@ -0,0 +1,62 @@ +package fsm + +import ( + "context" + "fmt" + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "testing" +) + +func TestOidcState(t *testing.T) { + t.Run("Should switch state to ApplyClusterRoleBindings when extension is disabled", func(t *testing.T) { + // given + ctx := context.Background() + fsm := &fsm{} + + runtimeStub := runtimeForTest() + shootStub := shootForTest() + oidcService := gardener.Extension{ + Type: "OidcExtensionType", + Disabled: ptr.To(true), + } + shootStub.Spec.Extensions = append(shootStub.Spec.Extensions, oidcService) + + systemState := &systemState{ + instance: runtimeStub, + shoot: shootStub, + } + + expectedRuntimeConditions := []metav1.Condition{ + { + Type: string(imv1.ConditionTypeOidcConfigured), + Reason: string(imv1.ConditionReasonOidcConfigured), + Status: "True", + Message: "OIDC extension disabled", + }, + } + + //when + stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + + //then + require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") + assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) + }) + +} + +// sets the time to its zero value for comparison purposes +func assertEqualConditions(t *testing.T, expectedConditions []metav1.Condition, actualConditions []metav1.Condition, msgAndArgs ...interface{}) bool { + for i, _ := range actualConditions { + time := metav1.Time{} + actualConditions[i].LastTransitionTime = time + fmt.Print("a") + } + + return assert.Equal(t, expectedConditions, actualConditions) +} From 3294aa45ba266c913a0d041d629439568f53c664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 2 Oct 2024 12:27:35 +0200 Subject: [PATCH 33/36] moves KIM config from internal package to internal/config --- cmd/main.go | 12 ++-- .../config.go} | 14 ++-- .../controller/runtime/fsm/runtime_fsm.go | 6 +- .../runtime/fsm/runtime_fsm_configure_oidc.go | 46 ++++++------ .../runtime/fsm/runtime_fsm_create_shoot.go | 2 +- .../fsm/runtime_fsm_create_shoot_dry_run.go | 2 +- .../runtime/fsm/runtime_fsm_patch_shoot.go | 6 +- .../runtime/fsm/runtime_fsm_persist_shoot.go | 2 +- .../fsm/runtime_fsm_persist_shoot_test.go | 4 +- .../controller/runtime/fsm/utilz_for_test.go | 6 +- internal/controller/runtime/suite_test.go | 22 +++--- internal/gardener/shoot/converter.go | 6 +- internal/gardener/shoot/converter_test.go | 70 ++++++++++--------- internal/gardener/shoot/extender/oidc.go | 4 +- internal/gardener/shoot/extender/oidc_test.go | 4 +- 15 files changed, 107 insertions(+), 99 deletions(-) rename internal/{InfrastructureManagerConfig.go => config/config.go} (86%) diff --git a/cmd/main.go b/cmd/main.go index 91b53790..f89543c2 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -20,6 +20,7 @@ import ( "encoding/json" "flag" "fmt" + "github.com/kyma-project/infrastructure-manager/internal/config" "io" "os" "time" @@ -29,7 +30,6 @@ import ( gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "github.com/go-playground/validator/v10" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" kubeconfig_controller "github.com/kyma-project/infrastructure-manager/internal/controller/kubeconfig" "github.com/kyma-project/infrastructure-manager/internal/controller/metrics" @@ -165,7 +165,7 @@ func main() { getReader := func() (io.Reader, error) { return os.Open(converterConfigFilepath) } - var converterConfig internal.InfrastructureManagerConfig + var converterConfig config.Config if err = converterConfig.Load(getReader); err != nil { setupLog.Error(err, "unable to load converter configuration") os.Exit(1) @@ -184,10 +184,10 @@ func main() { } cfg := fsm.RCCfg{ - Finalizer: infrastructuremanagerv1.Finalizer, - ShootNamesapace: gardenerNamespace, - InfrastructureManagerConfig: converterConfig, - AuditLogMandatory: auditLogMandatory, + Finalizer: infrastructuremanagerv1.Finalizer, + ShootNamesapace: gardenerNamespace, + Config: converterConfig, + AuditLogMandatory: auditLogMandatory, } if shootSpecDumpEnabled { cfg.PVCPath = "/testdata/kim" diff --git a/internal/InfrastructureManagerConfig.go b/internal/config/config.go similarity index 86% rename from internal/InfrastructureManagerConfig.go rename to internal/config/config.go index 246f4344..0aa029d8 100644 --- a/internal/InfrastructureManagerConfig.go +++ b/internal/config/config.go @@ -1,13 +1,17 @@ -package internal +package config import ( "encoding/json" "io" ) -type InfrastructureManagerConfig struct { - ConverterConfig ConverterConfig `json:"converter" validate:"required"` - DefaultSharedIASTenant OidcProvider `json:"defaultSharedIASTenant" validate:"required"` +type Config struct { + ConverterConfig ConverterConfig `json:"converter" validate:"required"` + ClusterConfig ClusterConfig `json:"cluster" validate:"required"` +} + +type ClusterConfig struct { + DefaultSharedIASTenant OidcProvider `json:"defaultSharedIASTenant" validate:"required"` } type ProviderConfig struct { @@ -65,7 +69,7 @@ type ConverterConfig struct { type ReaderGetter = func() (io.Reader, error) -func (c *InfrastructureManagerConfig) Load(f ReaderGetter) error { +func (c *Config) Load(f ReaderGetter) error { r, err := f() if err != nil { return err diff --git a/internal/controller/runtime/fsm/runtime_fsm.go b/internal/controller/runtime/fsm/runtime_fsm.go index 4c324b59..67e9b2a6 100644 --- a/internal/controller/runtime/fsm/runtime_fsm.go +++ b/internal/controller/runtime/fsm/runtime_fsm.go @@ -3,6 +3,7 @@ package fsm import ( "context" "fmt" + "github.com/kyma-project/infrastructure-manager/internal/config" "io" "reflect" "runtime" @@ -10,7 +11,6 @@ import ( "github.com/go-logr/logr" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" @@ -34,7 +34,7 @@ type RCCfg struct { PVCPath string ShootNamesapace string AuditLogMandatory bool - internal.InfrastructureManagerConfig + config.Config } func (f stateFn) String() string { @@ -108,6 +108,6 @@ func NewFsm(log logr.Logger, cfg RCCfg, k8s K8s) Fsm { RCCfg: cfg, log: log, K8s: k8s, - AuditLogging: auditlogging.NewAuditLogging(cfg.InfrastructureManagerConfig.ConverterConfig.AuditLog.TenantConfigPath, cfg.InfrastructureManagerConfig.ConverterConfig.AuditLog.PolicyConfigMapName, k8s.ShootClient), + AuditLogging: auditlogging.NewAuditLogging(cfg.Config.ConverterConfig.AuditLog.TenantConfigPath, cfg.Config.ConverterConfig.AuditLog.PolicyConfigMapName, k8s.ShootClient), } } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 350e4338..14a4a856 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,11 +3,11 @@ package fsm import ( "context" "fmt" + "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -15,28 +15,6 @@ import ( k8s_client "sigs.k8s.io/controller-runtime/pkg/client" ) -func defaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { - additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig - - if additionalOidcConfig == nil { - additionalOidcConfig = &[]gardener.OIDCConfig{} - defaultOIDCConfig := createDefaultOIDCConfig(cfg.DefaultSharedIASTenant) - *additionalOidcConfig = append(*additionalOidcConfig, defaultOIDCConfig) - runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig - } -} - -func createDefaultOIDCConfig(defaultSharedIASTenant internal.OidcProvider) gardener.OIDCConfig { - return gardener.OIDCConfig{ - ClientID: &defaultSharedIASTenant.ClientID, - GroupsClaim: &defaultSharedIASTenant.GroupsClaim, - IssuerURL: &defaultSharedIASTenant.IssuerURL, - SigningAlgs: defaultSharedIASTenant.SigningAlgs, - UsernameClaim: &defaultSharedIASTenant.UsernameClaim, - UsernamePrefix: &defaultSharedIASTenant.UsernamePrefix, - } -} - func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Configure OIDC state") @@ -70,6 +48,28 @@ func sFnConfigureOidc(ctx context.Context, m *fsm, s *systemState) (stateFn, *ct return switchState(sFnApplyClusterRoleBindings) } +func defaultAdditionalOidcIfNotPresent(runtime *imv1.Runtime, cfg RCCfg) { + additionalOidcConfig := runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig + + if additionalOidcConfig == nil { + additionalOidcConfig = &[]gardener.OIDCConfig{} + defaultOIDCConfig := createDefaultOIDCConfig(cfg.ClusterConfig.DefaultSharedIASTenant) + *additionalOidcConfig = append(*additionalOidcConfig, defaultOIDCConfig) + runtime.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig + } +} + +func createDefaultOIDCConfig(defaultSharedIASTenant config.OidcProvider) gardener.OIDCConfig { + return gardener.OIDCConfig{ + ClientID: &defaultSharedIASTenant.ClientID, + GroupsClaim: &defaultSharedIASTenant.GroupsClaim, + IssuerURL: &defaultSharedIASTenant.IssuerURL, + SigningAlgs: defaultSharedIASTenant.SigningAlgs, + UsernameClaim: &defaultSharedIASTenant.UsernameClaim, + UsernamePrefix: &defaultSharedIASTenant.UsernamePrefix, + } +} + func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { srscClient := m.ShootClient.SubResource("adminkubeconfig") shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go index 8bed7950..3cacb929 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go @@ -11,7 +11,7 @@ import ( func sFnCreateShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create shoot state") - newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) + newShoot, err := convertShoot(&s.instance, m.Config.ConverterConfig) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object") return updateStatePendingWithErrorAndStop( diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go b/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go index 80fd7bd3..93cdc662 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_shoot_dry_run.go @@ -10,7 +10,7 @@ import ( func sFnCreateShootDryRun(_ context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create shoot [dry-run]") - newShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) + newShoot, err := convertShoot(&s.instance, m.Config.ConverterConfig) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object [dry-run]") return updateStatePendingWithErrorAndStop( diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index 3829c549..334d5667 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -2,10 +2,10 @@ package fsm import ( "context" + "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" @@ -15,7 +15,7 @@ import ( func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Patch shoot state") - updatedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) + updatedShoot, err := convertShoot(&s.instance, m.Config.ConverterConfig) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object, exiting with no retry") return updateStatePendingWithErrorAndStop(&s.instance, imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonConversionError, "Runtime conversion error") @@ -52,7 +52,7 @@ func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn return updateStatusAndRequeueAfter(gardenerRequeueDuration) } -func convertShoot(instance *imv1.Runtime, cfg internal.ConverterConfig) (gardener.Shoot, error) { +func convertShoot(instance *imv1.Runtime, cfg config.ConverterConfig) (gardener.Shoot, error) { if err := instance.ValidateRequiredLabels(); err != nil { return gardener.Shoot{}, err } diff --git a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go index d473f0e9..21b67fdf 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot.go @@ -42,7 +42,7 @@ func sFnDumpShootSpec(_ context.Context, m *fsm, s *systemState) (stateFn, *ctrl // To make comparison easier we don't store object obtained from the cluster as it contains additional fields that are not relevant for the comparison. // We use object created by the converter instead (the Provisioner uses the same approach) - convertedShoot, err := convertShoot(&s.instance, m.InfrastructureManagerConfig.ConverterConfig) + convertedShoot, err := convertShoot(&s.instance, m.Config.ConverterConfig) if err != nil { return updateStatusAndStopWithError(err) } diff --git a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go index 567df824..df2aa9cc 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go @@ -3,11 +3,11 @@ package fsm import ( "bytes" "context" + "github.com/kyma-project/infrastructure-manager/internal/config" "io" "time" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm/testing" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive @@ -30,7 +30,7 @@ var _ = Describe("KIM sFnPersist", func() { expectedRuntime.Spec.Shoot.Provider.Type = "aws" It("should persist shoot data", func() { - next, _, err := sFnDumpShootSpec(testCtx, must(newFakeFSM, withStorageWriter(testWriterGetter), withConverterConfig(internal.ConverterConfig{})), &systemState{shoot: &testing.ShootNoDNS, instance: *expectedRuntime}) + next, _, err := sFnDumpShootSpec(testCtx, must(newFakeFSM, withStorageWriter(testWriterGetter), withConverterConfig(config.ConverterConfig{})), &systemState{shoot: &testing.ShootNoDNS, instance: *expectedRuntime}) Expect(err).To(BeNil()) Expect(next).To(haveName("sFnUpdateStatus")) diff --git a/internal/controller/runtime/fsm/utilz_for_test.go b/internal/controller/runtime/fsm/utilz_for_test.go index 98c97900..8edf893b 100644 --- a/internal/controller/runtime/fsm/utilz_for_test.go +++ b/internal/controller/runtime/fsm/utilz_for_test.go @@ -3,10 +3,10 @@ package fsm import ( "context" "fmt" + "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" - "github.com/kyma-project/infrastructure-manager/internal" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,9 +44,9 @@ var ( } } - withConverterConfig = func(config internal.ConverterConfig) fakeFSMOpt { + withConverterConfig = func(config config.ConverterConfig) fakeFSMOpt { return func(fsm *fsm) error { - fsm.InfrastructureManagerConfig.ConverterConfig = config + fsm.Config.ConverterConfig = config return nil } } diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index 42b0222c..a176fdb6 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -19,6 +19,7 @@ package runtime import ( "context" "encoding/json" + "github.com/kyma-project/infrastructure-manager/internal/config" "path/filepath" "testing" "time" @@ -26,7 +27,6 @@ import ( gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" @@ -109,7 +109,7 @@ var _ = BeforeSuite(func() { customTracker = NewCustomTracker(tracker, []*gardener_api.Shoot{}, []*gardener_api.Seed{}) gardenerTestClient = fake.NewClientBuilder().WithScheme(clientScheme).WithObjectTracker(customTracker).Build() - runtimeReconciler = NewRuntimeReconciler(mgr, gardenerTestClient, logger, fsm.RCCfg{Finalizer: infrastructuremanagerv1.Finalizer, InfrastructureManagerConfig: fixConverterConfigForTests()}) + runtimeReconciler = NewRuntimeReconciler(mgr, gardenerTestClient, logger, fsm.RCCfg{Finalizer: infrastructuremanagerv1.Finalizer, Config: fixConverterConfigForTests()}) Expect(runtimeReconciler).NotTo(BeNil()) err = runtimeReconciler.SetupWithManager(mgr) Expect(err).To(BeNil()) @@ -332,27 +332,27 @@ func setupSeedObjectOnCluster(client client.Client) error { return client.Create(context.Background(), seed) } -func fixConverterConfigForTests() internal.InfrastructureManagerConfig { - return internal.InfrastructureManagerConfig{ - ConverterConfig: internal.ConverterConfig{ - Kubernetes: internal.KubernetesConfig{ +func fixConverterConfigForTests() config.Config { + return config.Config{ + ConverterConfig: config.ConverterConfig{ + Kubernetes: config.KubernetesConfig{ DefaultVersion: "1.29", }, - DNS: internal.DNSConfig{ + DNS: config.DNSConfig{ SecretName: "aws-route53-secret-dev", DomainPrefix: "dev.kyma.ondemand.com", ProviderType: "aws-route53", }, - Provider: internal.ProviderConfig{ - AWS: internal.AWSConfig{ + Provider: config.ProviderConfig{ + AWS: config.AWSConfig{ EnableIMDSv2: true, }, }, - Gardener: internal.GardenerConfig{ + Gardener: config.GardenerConfig{ ProjectName: "kyma-dev", }, - AuditLog: internal.AuditLogConfig{ + AuditLog: config.AuditLogConfig{ PolicyConfigMapName: "policy-config-map", TenantConfigPath: filepath.Join("testdata", "auditConfig.json"), }, diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index 8c41f194..aaff7373 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -2,10 +2,10 @@ package shoot import ( "fmt" + "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -14,10 +14,10 @@ type Extend func(imv1.Runtime, *gardener.Shoot) error type Converter struct { extenders []Extend - config internal.ConverterConfig + config config.ConverterConfig } -func NewConverter(config internal.ConverterConfig) Converter { +func NewConverter(config config.ConverterConfig) Converter { extenders := []Extend{ extender.ExtendWithAnnotations, extender.ExtendWithLabels, diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index 26f73206..3c3c18bf 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -2,6 +2,7 @@ package shoot import ( "fmt" + "github.com/kyma-project/infrastructure-manager/internal/config" "io" "strings" "testing" @@ -9,7 +10,6 @@ import ( gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/go-playground/validator/v10" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/hyperscaler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -38,20 +38,20 @@ func TestConverter(t *testing.T) { }) } -func fixConverterConfig() internal.ConverterConfig { - return internal.ConverterConfig{ - Kubernetes: internal.KubernetesConfig{ +func fixConverterConfig() config.ConverterConfig { + return config.ConverterConfig{ + Kubernetes: config.KubernetesConfig{ DefaultVersion: "1.29", EnableKubernetesVersionAutoUpdate: true, EnableMachineImageVersionAutoUpdate: false, }, - DNS: internal.DNSConfig{ + DNS: config.DNSConfig{ SecretName: "dns-secret", DomainPrefix: "dev.mydomain.com", ProviderType: "aws-route53", }, - Provider: internal.ProviderConfig{ - AWS: internal.AWSConfig{ + Provider: config.ProviderConfig{ + AWS: config.AWSConfig{ EnableIMDSv2: true, }, }, @@ -129,7 +129,7 @@ func Test_ConverterConfig_Load_Err(t *testing.T) { failingReaderGetter := func() (io.Reader, error) { return nil, errTestReaderGetterFailed } - var cfg internal.InfrastructureManagerConfig + var cfg config.Config if err := cfg.Load(failingReaderGetter); err != errTestReaderGetterFailed { t.Error("ConverterConfig load should fail") } @@ -138,13 +138,15 @@ func Test_ConverterConfig_Load_Err(t *testing.T) { var testReader io.Reader = strings.NewReader( ` { - "defaultSharedIASTenant" : { - "clientID": "test-clientID", - "groupsClaim": "test-group", - "issuerURL": "test-issuer-url", - "signingAlgs": ["test-alg"], - "usernameClaim": "test-username-claim", - "usernamePrefix": "-" + "cluster": { + "defaultSharedIASTenant" : { + "clientID": "test-clientID", + "groupsClaim": "test-group", + "issuerURL": "test-issuer-url", + "signingAlgs": ["test-alg"], + "usernameClaim": "test-username-claim", + "usernamePrefix": "-" + } }, "converter": { "kubernetes": { @@ -196,26 +198,28 @@ func Test_ConverterConfig_Load_OK(t *testing.T) { readerGetter := func() (io.Reader, error) { return testReader, nil } - var cfg internal.InfrastructureManagerConfig + var cfg config.Config if err := cfg.Load(readerGetter); err != nil { t.Errorf("ConverterConfig load failed: %s", err) } - expected := internal.InfrastructureManagerConfig{ - DefaultSharedIASTenant: internal.OidcProvider{ - ClientID: "test-clientID", - GroupsClaim: "test-group", - IssuerURL: "test-issuer-url", - SigningAlgs: []string{"test-alg"}, - UsernameClaim: "test-username-claim", - UsernamePrefix: "-", + expected := config.Config{ + ClusterConfig: config.ClusterConfig{ + DefaultSharedIASTenant: config.OidcProvider{ + ClientID: "test-clientID", + GroupsClaim: "test-group", + IssuerURL: "test-issuer-url", + SigningAlgs: []string{"test-alg"}, + UsernameClaim: "test-username-claim", + UsernamePrefix: "-", + }, }, - ConverterConfig: internal.ConverterConfig{ - Kubernetes: internal.KubernetesConfig{ + ConverterConfig: config.ConverterConfig{ + Kubernetes: config.KubernetesConfig{ DefaultVersion: "0.1.2.3", EnableKubernetesVersionAutoUpdate: true, EnableMachineImageVersionAutoUpdate: false, - DefaultOperatorOidc: internal.OidcProvider{ + DefaultOperatorOidc: config.OidcProvider{ ClientID: "test-clientID", GroupsClaim: "test-group", IssuerURL: "test-issuer-url", @@ -224,24 +228,24 @@ func Test_ConverterConfig_Load_OK(t *testing.T) { UsernamePrefix: "-", }, }, - DNS: internal.DNSConfig{ + DNS: config.DNSConfig{ SecretName: "test-secret-name", DomainPrefix: "test-domain-prefix", ProviderType: "test-provider-type", }, - Provider: internal.ProviderConfig{ - AWS: internal.AWSConfig{ + Provider: config.ProviderConfig{ + AWS: config.AWSConfig{ EnableIMDSv2: true, }, }, - MachineImage: internal.MachineImageConfig{ + MachineImage: config.MachineImageConfig{ DefaultName: "test-image-name", DefaultVersion: "0.1.2.3.4", }, - Gardener: internal.GardenerConfig{ + Gardener: config.GardenerConfig{ ProjectName: "test-project", }, - AuditLog: internal.AuditLogConfig{ + AuditLog: config.AuditLogConfig{ PolicyConfigMapName: "test-policy", TenantConfigPath: "test-path", }, diff --git a/internal/gardener/shoot/extender/oidc.go b/internal/gardener/shoot/extender/oidc.go index 39117eac..bdd7a8a0 100644 --- a/internal/gardener/shoot/extender/oidc.go +++ b/internal/gardener/shoot/extender/oidc.go @@ -3,7 +3,7 @@ package extender import ( gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" + "github.com/kyma-project/infrastructure-manager/internal/config" "k8s.io/utils/ptr" ) @@ -15,7 +15,7 @@ func shouldDefaultOidcConfig(config gardener.OIDCConfig) bool { return config.ClientID == nil && config.IssuerURL == nil } -func NewOidcExtender(oidcProvider internal.OidcProvider) func(runtime imv1.Runtime, shoot *gardener.Shoot) error { +func NewOidcExtender(oidcProvider config.OidcProvider) func(runtime imv1.Runtime, shoot *gardener.Shoot) error { return func(runtime imv1.Runtime, shoot *gardener.Shoot) error { if CanEnableExtension(runtime) { setOIDCExtension(shoot) diff --git a/internal/gardener/shoot/extender/oidc_test.go b/internal/gardener/shoot/extender/oidc_test.go index c84edfae..d3677a22 100644 --- a/internal/gardener/shoot/extender/oidc_test.go +++ b/internal/gardener/shoot/extender/oidc_test.go @@ -1,11 +1,11 @@ package extender import ( + "github.com/kyma-project/infrastructure-manager/internal/config" "testing" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" - "github.com/kyma-project/infrastructure-manager/internal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,7 +36,7 @@ func TestOidcExtender(t *testing.T) { } { t.Run(testCase.name, func(t *testing.T) { // given - defaultOidc := internal.OidcProvider{ + defaultOidc := config.OidcProvider{ ClientID: "client-id", GroupsClaim: "groups", IssuerURL: "https://my.cool.tokens.com", From 8e252c2608ab1c6d4e3fa5ba429d40aac7988483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 2 Oct 2024 13:22:16 +0200 Subject: [PATCH 34/36] linter fixes --- cmd/main.go | 2 +- internal/controller/runtime/fsm/runtime_fsm.go | 2 +- .../controller/runtime/fsm/runtime_fsm_configure_oidc.go | 2 +- .../runtime/fsm/runtime_fsm_configure_oidc_test.go | 8 ++++---- .../controller/runtime/fsm/runtime_fsm_patch_shoot.go | 2 +- .../runtime/fsm/runtime_fsm_persist_shoot_test.go | 2 +- internal/controller/runtime/fsm/utilz_for_test.go | 2 +- internal/controller/runtime/suite_test.go | 2 +- internal/gardener/shoot/converter.go | 2 +- internal/gardener/shoot/converter_test.go | 2 +- internal/gardener/shoot/extender/oidc_test.go | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index f89543c2..e3edef03 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -20,7 +20,6 @@ import ( "encoding/json" "flag" "fmt" - "github.com/kyma-project/infrastructure-manager/internal/config" "io" "os" "time" @@ -31,6 +30,7 @@ import ( "github.com/go-playground/validator/v10" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" + "github.com/kyma-project/infrastructure-manager/internal/config" kubeconfig_controller "github.com/kyma-project/infrastructure-manager/internal/controller/kubeconfig" "github.com/kyma-project/infrastructure-manager/internal/controller/metrics" runtime_controller "github.com/kyma-project/infrastructure-manager/internal/controller/runtime" diff --git a/internal/controller/runtime/fsm/runtime_fsm.go b/internal/controller/runtime/fsm/runtime_fsm.go index 67e9b2a6..0256d8d8 100644 --- a/internal/controller/runtime/fsm/runtime_fsm.go +++ b/internal/controller/runtime/fsm/runtime_fsm.go @@ -3,7 +3,6 @@ package fsm import ( "context" "fmt" - "github.com/kyma-project/infrastructure-manager/internal/config" "io" "reflect" "runtime" @@ -12,6 +11,7 @@ import ( "github.com/go-logr/logr" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" + "github.com/kyma-project/infrastructure-manager/internal/config" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 14a4a856..a8c063aa 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -3,11 +3,11 @@ package fsm import ( "context" "fmt" - "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/config" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go index 094d8488..a84ce4fe 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go @@ -3,13 +3,14 @@ package fsm import ( "context" "fmt" + "testing" + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" - "testing" ) func TestOidcState(t *testing.T) { @@ -40,14 +41,13 @@ func TestOidcState(t *testing.T) { }, } - //when + // when stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) - //then + // then require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) - } // sets the time to its zero value for comparison purposes diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index 334d5667..10c1f0d1 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -2,10 +2,10 @@ package fsm import ( "context" - "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/config" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" diff --git a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go index df2aa9cc..4ceda6ea 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_persist_shoot_test.go @@ -3,11 +3,11 @@ package fsm import ( "bytes" "context" - "github.com/kyma-project/infrastructure-manager/internal/config" "io" "time" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/kyma-project/infrastructure-manager/internal/config" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm/testing" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive diff --git a/internal/controller/runtime/fsm/utilz_for_test.go b/internal/controller/runtime/fsm/utilz_for_test.go index 8edf893b..d159c441 100644 --- a/internal/controller/runtime/fsm/utilz_for_test.go +++ b/internal/controller/runtime/fsm/utilz_for_test.go @@ -3,10 +3,10 @@ package fsm import ( "context" "fmt" - "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/kyma-project/infrastructure-manager/internal/config" . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index a176fdb6..5060d8c9 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -19,7 +19,6 @@ package runtime import ( "context" "encoding/json" - "github.com/kyma-project/infrastructure-manager/internal/config" "path/filepath" "testing" "time" @@ -28,6 +27,7 @@ import ( gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/auditlogging" + "github.com/kyma-project/infrastructure-manager/internal/config" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" gardener_shoot "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot" . "github.com/onsi/ginkgo/v2" //nolint:revive diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index aaff7373..3b1f43a5 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -2,10 +2,10 @@ package shoot import ( "fmt" - "github.com/kyma-project/infrastructure-manager/internal/config" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/config" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/extender" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index 3c3c18bf..1b5ecc75 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -2,7 +2,6 @@ package shoot import ( "fmt" - "github.com/kyma-project/infrastructure-manager/internal/config" "io" "strings" "testing" @@ -10,6 +9,7 @@ import ( gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/go-playground/validator/v10" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/config" "github.com/kyma-project/infrastructure-manager/internal/gardener/shoot/hyperscaler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/internal/gardener/shoot/extender/oidc_test.go b/internal/gardener/shoot/extender/oidc_test.go index d3677a22..0bca15c9 100644 --- a/internal/gardener/shoot/extender/oidc_test.go +++ b/internal/gardener/shoot/extender/oidc_test.go @@ -1,11 +1,11 @@ package extender import ( - "github.com/kyma-project/infrastructure-manager/internal/config" "testing" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/kyma-project/infrastructure-manager/internal/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" From 080bc57d2acb6011e610c195ea372166ef2e7d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Fri, 4 Oct 2024 08:11:00 +0200 Subject: [PATCH 35/36] unit tests for oidc fsm --- .../runtime_fsm_configure_auditlog_test.go | 1 + .../runtime/fsm/runtime_fsm_configure_oidc.go | 1 - .../fsm/runtime_fsm_configure_oidc_test.go | 253 +++++++++++++++++- 3 files changed, 248 insertions(+), 7 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go index cf48b935..0cc1a885 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go @@ -244,6 +244,7 @@ func TestAuditLogState(t *testing.T) { auditLog := &mocks.AuditLogging{} shoot := shootForTest() instance := runtimeForTest() + // instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig systemState := &systemState{ instance: instance, shoot: shoot, diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index a8c063aa..50118c62 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -73,7 +73,6 @@ func createDefaultOIDCConfig(defaultSharedIASTenant config.OidcProvider) gardene func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { srscClient := m.ShootClient.SubResource("adminkubeconfig") shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) - if shootClientError != nil { return shootClientError } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go index a84ce4fe..9145dfe5 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go @@ -2,19 +2,22 @@ package fsm import ( "context" - "fmt" "testing" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" + authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" ) func TestOidcState(t *testing.T) { - t.Run("Should switch state to ApplyClusterRoleBindings when extension is disabled", func(t *testing.T) { + t.Run("Should switch state to ApplyClusterRoleBindings when OIDC extension is disabled", func(t *testing.T) { // given ctx := context.Background() fsm := &fsm{} @@ -22,7 +25,7 @@ func TestOidcState(t *testing.T) { runtimeStub := runtimeForTest() shootStub := shootForTest() oidcService := gardener.Extension{ - Type: "OidcExtensionType", + Type: "shoot-oidc-service", Disabled: ptr.To(true), } shootStub.Spec.Extensions = append(shootStub.Spec.Extensions, oidcService) @@ -48,15 +51,253 @@ func TestOidcState(t *testing.T) { require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) + + t.Run("Should configure OIDC using defaults", func(t *testing.T) { + // given + ctx := context.Background() + + // start of fake client setup + scheme, err := newOIDCTestScheme() + require.NoError(t, err) + var fakeClient = fake.NewClientBuilder(). + WithScheme(scheme). + Build() + fsm := &fsm{K8s: K8s{ + ShootClient: fakeClient, + Client: fakeClient, + }} + GetShootClient = func( + _ context.Context, + _ client.SubResourceClient, + _ *gardener.Shoot) (client.Client, error) { + return fakeClient, nil + } + // end of fake client setup + + runtimeStub := runtimeForTest() + shootStub := shootForTest() + oidcService := gardener.Extension{ + Type: "shoot-oidc-service", + Disabled: ptr.To(false), + } + shootStub.Spec.Extensions = append(shootStub.Spec.Extensions, oidcService) + + systemState := &systemState{ + instance: runtimeStub, + shoot: shootStub, + } + + expectedRuntimeConditions := []metav1.Condition{ + { + Type: string(imv1.ConditionTypeOidcConfigured), + Reason: string(imv1.ConditionReasonOidcConfigured), + Status: "True", + Message: "OIDC configuration completed", + }, + } + + // when + stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + + // then + require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") + + var openIdConnects authenticationv1alpha1.OpenIDConnectList + + err = fakeClient.List(ctx, &openIdConnects) + require.NoError(t, err) + assert.Len(t, openIdConnects.Items, 1) + assert.Equal(t, "kyma-oidc-0", openIdConnects.Items[0].Name) + assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) + }) + + t.Run("Should configure OIDC based on Runtime CR configuration", func(t *testing.T) { + // given + ctx := context.Background() + + // start of fake client setup + scheme, err := newOIDCTestScheme() + require.NoError(t, err) + var fakeClient = fake.NewClientBuilder(). + WithScheme(scheme). + Build() + fsm := &fsm{K8s: K8s{ + ShootClient: fakeClient, + Client: fakeClient, + }} + GetShootClient = func( + _ context.Context, + _ client.SubResourceClient, + _ *gardener.Shoot) (client.Client, error) { + return fakeClient, nil + } + // end of fake client setup + + runtimeStub := runtimeForTest() + additionalOidcConfig := &[]gardener.OIDCConfig{} + *additionalOidcConfig = append(*additionalOidcConfig, createOidcConfig("runtime-cr-config0")) + *additionalOidcConfig = append(*additionalOidcConfig, createOidcConfig("runtime-cr-config1")) + runtimeStub.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig + + shootStub := shootForTest() + oidcService := gardener.Extension{ + Type: "shoot-oidc-service", + Disabled: ptr.To(false), + } + shootStub.Spec.Extensions = append(shootStub.Spec.Extensions, oidcService) + + systemState := &systemState{ + instance: runtimeStub, + shoot: shootStub, + } + + expectedRuntimeConditions := []metav1.Condition{ + { + Type: string(imv1.ConditionTypeOidcConfigured), + Reason: string(imv1.ConditionReasonOidcConfigured), + Status: "True", + Message: "OIDC configuration completed", + }, + } + + // when + stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + + // then + require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") + + var openIdConnects authenticationv1alpha1.OpenIDConnectList + + err = fakeClient.List(ctx, &openIdConnects) + require.NoError(t, err) + assert.Len(t, openIdConnects.Items, 2) + assert.Equal(t, "kyma-oidc-0", openIdConnects.Items[0].Name) + assert.Equal(t, "runtime-cr-config0", openIdConnects.Items[0].Spec.ClientID) + assert.Equal(t, "runtime-cr-config1", openIdConnects.Items[1].Spec.ClientID) + assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) + }) + + t.Run("Should first delete existing OpenIDConnect CRs then recreate them", func(t *testing.T) { + // given + ctx := context.Background() + + // start of fake client setup + scheme, err := newOIDCTestScheme() + require.NoError(t, err) + var fakeClient = fake.NewClientBuilder(). + WithScheme(scheme). + Build() + fsm := &fsm{K8s: K8s{ + ShootClient: fakeClient, + Client: fakeClient, + }} + GetShootClient = func( + _ context.Context, + _ client.SubResourceClient, + _ *gardener.Shoot) (client.Client, error) { + return fakeClient, nil + } + // end of fake client setup + + kymaOpenIDConnectCR := createOpenIDConnectCR("old-kyma-oidc", "operator.kyma-project.io/managed-by", "infrastructure-manager") + err = fakeClient.Create(ctx, kymaOpenIDConnectCR) + require.NoError(t, err) + + existingOpenIDConnectCR := createOpenIDConnectCR("old-non-kyma-oidc", "customer-label", "should-not-be-deleted") + err = fakeClient.Create(ctx, existingOpenIDConnectCR) + require.NoError(t, err) + + runtimeStub := runtimeForTest() + shootStub := shootForTest() + oidcService := gardener.Extension{ + Type: "shoot-oidc-service", + Disabled: ptr.To(false), + } + shootStub.Spec.Extensions = append(shootStub.Spec.Extensions, oidcService) + + systemState := &systemState{ + instance: runtimeStub, + shoot: shootStub, + } + + expectedRuntimeConditions := []metav1.Condition{ + { + Type: string(imv1.ConditionTypeOidcConfigured), + Reason: string(imv1.ConditionReasonOidcConfigured), + Status: "True", + Message: "OIDC configuration completed", + }, + } + + // when + stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + + // then + require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") + + var openIdConnect authenticationv1alpha1.OpenIDConnect + key := client.ObjectKey{ + Name: "old-kyma-oidc", + } + err = fakeClient.Get(ctx, key, &openIdConnect) + require.Error(t, err) + + key = client.ObjectKey{ + Name: "old-non-kyma-oidc", + } + err = fakeClient.Get(ctx, key, &openIdConnect) + require.NoError(t, err) + assert.Equal(t, openIdConnect.Name, "old-non-kyma-oidc") + + var openIdConnects authenticationv1alpha1.OpenIDConnectList + err = fakeClient.List(ctx, &openIdConnects) + require.NoError(t, err) + assert.Len(t, openIdConnects.Items, 2) + assert.Equal(t, "kyma-oidc-0", openIdConnects.Items[0].Name) + assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) + }) +} + +func newOIDCTestScheme() (*runtime.Scheme, error) { + schema := runtime.NewScheme() + + for _, fn := range []func(*runtime.Scheme) error{ + authenticationv1alpha1.AddToScheme, + } { + if err := fn(schema); err != nil { + return nil, err + } + } + return schema, nil } // sets the time to its zero value for comparison purposes func assertEqualConditions(t *testing.T, expectedConditions []metav1.Condition, actualConditions []metav1.Condition, msgAndArgs ...interface{}) bool { for i, _ := range actualConditions { - time := metav1.Time{} - actualConditions[i].LastTransitionTime = time - fmt.Print("a") + actualConditions[i].LastTransitionTime = metav1.Time{} } return assert.Equal(t, expectedConditions, actualConditions) } + +func createOidcConfig(clientId string) gardener.OIDCConfig { + return gardener.OIDCConfig{ + ClientID: ptr.To(clientId), + GroupsClaim: ptr.To("groups"), + IssuerURL: ptr.To("https://my.cool.tokens.com"), + SigningAlgs: []string{"RS256"}, + UsernameClaim: ptr.To("sub"), + UsernamePrefix: ptr.To("-"), + } +} + +func createOpenIDConnectCR(name, labelKey, labelValue string) *authenticationv1alpha1.OpenIDConnect { + return &authenticationv1alpha1.OpenIDConnect{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + labelKey: labelValue, + }, + }, + } +} From f22f47ba9b9fb8896d0fb629c4328e9f084fabf5 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Thu, 10 Oct 2024 14:50:53 +0200 Subject: [PATCH 36/36] Code review remarks: tests check all fields of the OpenOIDC CR --- .../runtime_fsm_configure_auditlog_test.go | 1 - .../runtime/fsm/runtime_fsm_configure_oidc.go | 23 +++++--- .../fsm/runtime_fsm_configure_oidc_test.go | 57 +++++++++++++++---- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go index 0cc1a885..cf48b935 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_auditlog_test.go @@ -244,7 +244,6 @@ func TestAuditLogState(t *testing.T) { auditLog := &mocks.AuditLogging{} shoot := shootForTest() instance := runtimeForTest() - // instance.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig systemState := &systemState{ instance: instance, shoot: shoot, diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 50118c62..217d5297 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -109,6 +109,14 @@ func isOidcExtensionEnabled(shoot gardener.Shoot) bool { } func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig, oidcID int) *authenticationv1alpha1.OpenIDConnect { + toSupportedSigningAlgs := func(signingAlgs []string) []authenticationv1alpha1.SigningAlgorithm { + var supportedSigningAlgs []authenticationv1alpha1.SigningAlgorithm + for _, alg := range signingAlgs { + supportedSigningAlgs = append(supportedSigningAlgs, authenticationv1alpha1.SigningAlgorithm(alg)) + } + return supportedSigningAlgs + } + cr := &authenticationv1alpha1.OpenIDConnect{ TypeMeta: metav1.TypeMeta{ Kind: "OpenIDConnect", @@ -121,13 +129,14 @@ func createOpenIDConnectResource(additionalOidcConfig gardener.OIDCConfig, oidcI }, }, Spec: authenticationv1alpha1.OIDCAuthenticationSpec{ - IssuerURL: *additionalOidcConfig.IssuerURL, - ClientID: *additionalOidcConfig.ClientID, - UsernameClaim: additionalOidcConfig.UsernameClaim, - UsernamePrefix: additionalOidcConfig.UsernamePrefix, - GroupsClaim: additionalOidcConfig.GroupsClaim, - GroupsPrefix: additionalOidcConfig.GroupsPrefix, - RequiredClaims: additionalOidcConfig.RequiredClaims, + IssuerURL: *additionalOidcConfig.IssuerURL, + ClientID: *additionalOidcConfig.ClientID, + UsernameClaim: additionalOidcConfig.UsernameClaim, + UsernamePrefix: additionalOidcConfig.UsernamePrefix, + GroupsClaim: additionalOidcConfig.GroupsClaim, + GroupsPrefix: additionalOidcConfig.GroupsPrefix, + RequiredClaims: additionalOidcConfig.RequiredClaims, + SupportedSigningAlgs: toSupportedSigningAlgs(additionalOidcConfig.SigningAlgs), }, } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go index 9145dfe5..6808c234 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go @@ -2,6 +2,7 @@ package fsm import ( "context" + "github.com/kyma-project/infrastructure-manager/internal/config" "testing" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" @@ -65,7 +66,15 @@ func TestOidcState(t *testing.T) { fsm := &fsm{K8s: K8s{ ShootClient: fakeClient, Client: fakeClient, - }} + }, + RCCfg: RCCfg{ + Config: config.Config{ + ClusterConfig: config.ClusterConfig{ + DefaultSharedIASTenant: createConverterOidcConfig("defaut-client-id"), + }, + }, + }, + } GetShootClient = func( _ context.Context, _ client.SubResourceClient, @@ -107,7 +116,8 @@ func TestOidcState(t *testing.T) { err = fakeClient.List(ctx, &openIdConnects) require.NoError(t, err) assert.Len(t, openIdConnects.Items, 1) - assert.Equal(t, "kyma-oidc-0", openIdConnects.Items[0].Name) + + assertOIDCCRD(t, "kyma-oidc-0", "defaut-client-id", openIdConnects.Items[0]) assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -135,8 +145,8 @@ func TestOidcState(t *testing.T) { runtimeStub := runtimeForTest() additionalOidcConfig := &[]gardener.OIDCConfig{} - *additionalOidcConfig = append(*additionalOidcConfig, createOidcConfig("runtime-cr-config0")) - *additionalOidcConfig = append(*additionalOidcConfig, createOidcConfig("runtime-cr-config1")) + *additionalOidcConfig = append(*additionalOidcConfig, createGardenerOidcConfig("runtime-cr-config0")) + *additionalOidcConfig = append(*additionalOidcConfig, createGardenerOidcConfig("runtime-cr-config1")) runtimeStub.Spec.Shoot.Kubernetes.KubeAPIServer.AdditionalOidcConfig = additionalOidcConfig shootStub := shootForTest() @@ -172,8 +182,8 @@ func TestOidcState(t *testing.T) { require.NoError(t, err) assert.Len(t, openIdConnects.Items, 2) assert.Equal(t, "kyma-oidc-0", openIdConnects.Items[0].Name) - assert.Equal(t, "runtime-cr-config0", openIdConnects.Items[0].Spec.ClientID) - assert.Equal(t, "runtime-cr-config1", openIdConnects.Items[1].Spec.ClientID) + assertOIDCCRD(t, "kyma-oidc-0", "runtime-cr-config0", openIdConnects.Items[0]) + assertOIDCCRD(t, "kyma-oidc-1", "runtime-cr-config1", openIdConnects.Items[1]) assertEqualConditions(t, expectedRuntimeConditions, systemState.instance.Status.Conditions) }) @@ -272,15 +282,15 @@ func newOIDCTestScheme() (*runtime.Scheme, error) { } // sets the time to its zero value for comparison purposes -func assertEqualConditions(t *testing.T, expectedConditions []metav1.Condition, actualConditions []metav1.Condition, msgAndArgs ...interface{}) bool { - for i, _ := range actualConditions { +func assertEqualConditions(t *testing.T, expectedConditions []metav1.Condition, actualConditions []metav1.Condition) bool { + for i := range actualConditions { actualConditions[i].LastTransitionTime = metav1.Time{} } return assert.Equal(t, expectedConditions, actualConditions) } -func createOidcConfig(clientId string) gardener.OIDCConfig { +func createGardenerOidcConfig(clientId string) gardener.OIDCConfig { return gardener.OIDCConfig{ ClientID: ptr.To(clientId), GroupsClaim: ptr.To("groups"), @@ -291,7 +301,18 @@ func createOidcConfig(clientId string) gardener.OIDCConfig { } } -func createOpenIDConnectCR(name, labelKey, labelValue string) *authenticationv1alpha1.OpenIDConnect { +func createConverterOidcConfig(clientId string) config.OidcProvider { + return config.OidcProvider{ + ClientID: clientId, + GroupsClaim: "groups", + IssuerURL: "https://my.cool.tokens.com", + SigningAlgs: []string{"RS256"}, + UsernameClaim: "sub", + UsernamePrefix: "-", + } +} + +func createOpenIDConnectCR(name string, labelKey, labelValue string) *authenticationv1alpha1.OpenIDConnect { return &authenticationv1alpha1.OpenIDConnect{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -301,3 +322,19 @@ func createOpenIDConnectCR(name, labelKey, labelValue string) *authenticationv1a }, } } + +func assertOIDCCRD(t *testing.T, expectedName, expectedClientID string, actual authenticationv1alpha1.OpenIDConnect) { + assert.Equal(t, expectedName, actual.Name) + assert.Equal(t, expectedClientID, actual.Spec.ClientID) + assert.Equal(t, ptr.To("groups"), actual.Spec.GroupsClaim) + assert.Nil(t, actual.Spec.GroupsPrefix) + assert.Equal(t, "https://my.cool.tokens.com", actual.Spec.IssuerURL) + assert.Equal(t, []authenticationv1alpha1.SigningAlgorithm{"RS256"}, actual.Spec.SupportedSigningAlgs) + assert.Equal(t, ptr.To("sub"), actual.Spec.UsernameClaim) + assert.Equal(t, ptr.To("-"), actual.Spec.UsernamePrefix) + assert.Equal(t, map[string]string(nil), actual.Spec.RequiredClaims) + assert.Equal(t, 0, len(actual.Spec.ExtraClaims)) + assert.Equal(t, 0, len(actual.Spec.CABundle)) + assert.Equal(t, authenticationv1alpha1.JWKSSpec{}, actual.Spec.JWKS) + assert.Nil(t, actual.Spec.MaxTokenExpirationSeconds) +}