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] 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)