From 16771adae56c3468485b4bdc4d115736b9fb1f1c Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 09:15:52 -0400 Subject: [PATCH 1/8] Reduce min keepalive interval to 1s --- cmd/main.go | 8 +- .../templates/cms/controller-cm.yaml | 3 +- deploy/helm/jumpstarter/values.yaml | 60 +++++++------ internal/config/config.go | 44 ++++++++-- internal/config/grpc.go | 19 ++++ internal/config/oidc.go | 87 +++++++++++++++++++ internal/config/types.go | 28 ++++++ internal/service/controller_service.go | 3 +- internal/service/grpc.go | 15 ---- internal/service/router_service.go | 7 +- 10 files changed, 219 insertions(+), 55 deletions(-) create mode 100644 internal/config/grpc.go create mode 100644 internal/config/oidc.go create mode 100644 internal/config/types.go delete mode 100644 internal/service/grpc.go diff --git a/cmd/main.go b/cmd/main.go index d05f2920..d7514979 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -151,7 +151,7 @@ func main() { os.Exit(1) } - authenticator, prefix, err := config.LoadConfiguration( + authenticator, prefix, option, err := config.LoadConfiguration( context.Background(), mgr.GetAPIReader(), mgr.GetScheme(), @@ -211,14 +211,16 @@ func main() { ResourceKey: "jumpstarter-kind", NameKey: "jumpstarter-name", }), + ServerOption: option, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create service", "service", "Controller") os.Exit(1) } if err = (&service.RouterService{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + ServerOption: option, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create service", "service", "Router") os.Exit(1) diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml index 620f09f0..d400ab2c 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml @@ -10,4 +10,5 @@ metadata: deployment.timestamp: {{ .Values.global.timestamp | quote }} {{ end }} data: - authentication: {{- .Values.authenticationConfig | toYaml | indent 1 }} + config: | +{{ .Values.config | toYaml | indent 4 }} diff --git a/deploy/helm/jumpstarter/values.yaml b/deploy/helm/jumpstarter/values.yaml index 6b90c60c..5780400f 100644 --- a/deploy/helm/jumpstarter/values.yaml +++ b/deploy/helm/jumpstarter/values.yaml @@ -30,6 +30,7 @@ global: ## @param jumpstarter-controller.imagePullPolicy Image pull policy for the controller. ## @param jumpstarter-controller.namespace Namespace where the controller will be deployed, defaults to global.namespace. +## @param jumpstarter-controller.grpcConfig Configuration for gRPC server options ## @param jumpstarter-controller.authenticationConfig Configuration for OIDC authentication, see https://kubernetes.io/docs/reference/access-authn-authz/authentication/#using-authentication-configuration for documentation ## @section Ingress And Route parameters @@ -66,33 +67,38 @@ jumpstarter-controller: namespace: "" - authenticationConfig: | - apiVersion: jumpstarter.dev/v1alpha1 - kind: AuthenticationConfiguration - # jwt: - # - issuer: - # url: https://10.239.206.8:5556/dex - # audiences: - # - jumpstarter - # audienceMatchPolicy: MatchAny - # certificateAuthority: | - # -----BEGIN CERTIFICATE----- - # MIIB/DCCAYKgAwIBAgIIcpC2uS+SjEIwCgYIKoZIzj0EAwMwIDEeMBwGA1UEAxMV - # bWluaWNhIHJvb3QgY2EgNzI5MGI2MCAXDTI1MDIwMzE5MzMyNVoYDzIxMjUwMjAz - # MTkzMzI1WjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSA3MjkwYjYwdjAQBgcq - # hkjOPQIBBgUrgQQAIgNiAAQzezKJ4My35HPeoJvvzTjhS2uJMBYrYfrs5csxZjiy - # q8ORrHM539XhWlA6sVZODhzcF2KL4mC9xKz/yIrsws+LKsIWNHGGmIPEKFYnHBGw - # VBGeARvhpzZP/9frJXAN/8ejgYYwgYMwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW - # MBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1Ud - # DgQWBBSZRBCUuP3ta2xsfjnWIjvgvz4fojAfBgNVHSMEGDAWgBSZRBCUuP3ta2xs - # fjnWIjvgvz4fojAKBggqhkjOPQQDAwNoADBlAjADql5Ks5wh181iUa1ZBnx4XOVe - # l0l7I+mwlwJSPmkZHxruWZTx7gQU4tfDCr+UuzUCMQC2aDXRb17cphipK4gzbExv - # EDLExjhHAqMPrKDmT0jHIi7Bbos38/1tyZ/IoKjLnv0= - # -----END CERTIFICATE----- - # claimMappings: - # username: - # claim: "sub" - # prefix: "" + config: + grpc: + keepalive: + # Safety: potentially makes server vulnerable to DDoS + # https://grpc.io/docs/guides/keepalive/#how-configuring-keepalive-affects-a-call + minTime: 3s + permitWithoutStream: true + authentication: {} + # jwt: + # - issuer: + # url: https://10.239.206.8:5556/dex + # audiences: + # - jumpstarter + # audienceMatchPolicy: MatchAny + # certificateAuthority: | + # -----BEGIN CERTIFICATE----- + # MIIB/DCCAYKgAwIBAgIIcpC2uS+SjEIwCgYIKoZIzj0EAwMwIDEeMBwGA1UEAxMV + # bWluaWNhIHJvb3QgY2EgNzI5MGI2MCAXDTI1MDIwMzE5MzMyNVoYDzIxMjUwMjAz + # MTkzMzI1WjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSA3MjkwYjYwdjAQBgcq + # hkjOPQIBBgUrgQQAIgNiAAQzezKJ4My35HPeoJvvzTjhS2uJMBYrYfrs5csxZjiy + # q8ORrHM539XhWlA6sVZODhzcF2KL4mC9xKz/yIrsws+LKsIWNHGGmIPEKFYnHBGw + # VBGeARvhpzZP/9frJXAN/8ejgYYwgYMwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW + # MBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1Ud + # DgQWBBSZRBCUuP3ta2xsfjnWIjvgvz4fojAfBgNVHSMEGDAWgBSZRBCUuP3ta2xs + # fjnWIjvgvz4fojAKBggqhkjOPQQDAwNoADBlAjADql5Ks5wh181iUa1ZBnx4XOVe + # l0l7I+mwlwJSPmkZHxruWZTx7gQU4tfDCr+UuzUCMQC2aDXRb17cphipK4gzbExv + # EDLExjhHAqMPrKDmT0jHIi7Bbos38/1tyZ/IoKjLnv0= + # -----END CERTIFICATE----- + # claimMappings: + # username: + # claim: "sub" + # prefix: "" grpc: hostname: "" diff --git a/internal/config/config.go b/internal/config/config.go index c3d6b315..f6453859 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,10 +3,14 @@ package config import ( "context" "fmt" + "time" "github.com/jumpstarter-dev/jumpstarter-controller/internal/oidc" + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apiserver/pkg/authentication/authenticator" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -18,15 +22,42 @@ func LoadConfiguration( key client.ObjectKey, signer *oidc.Signer, certificateAuthority string, -) (authenticator.Token, string, error) { +) (authenticator.Token, string, grpc.ServerOption, error) { var configmap corev1.ConfigMap if err := client.Get(ctx, key, &configmap); err != nil { - return nil, "", err + return nil, "", nil, err + } + + rawConfig, ok := configmap.Data["config"] + if ok { + var config Config + err := yaml.UnmarshalStrict([]byte(rawConfig), &config) + if err != nil { + return nil, "", nil, err + } + + authenticator, prefix, err := LoadAuthenticationConfiguration( + ctx, + scheme, + config.Authentication, + signer, + certificateAuthority, + ) + if err != nil { + return nil, "", nil, err + } + + serverOptions, err := LoadGrpcConfiguration(config.Grpc) + if err != nil { + return nil, "", nil, err + } + + return authenticator, prefix, serverOptions, nil } rawAuthenticationConfiguration, ok := configmap.Data["authentication"] if !ok { - return nil, "", fmt.Errorf("LoadConfiguration: missing authentication section") + return nil, "", nil, fmt.Errorf("LoadConfiguration: missing authentication section") } authenticator, prefix, err := oidc.LoadAuthenticationConfiguration( @@ -37,8 +68,11 @@ func LoadConfiguration( certificateAuthority, ) if err != nil { - return nil, "", err + return nil, "", nil, err } - return authenticator, prefix, nil + return authenticator, prefix, grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ + MinTime: 1 * time.Second, + PermitWithoutStream: true, + }), nil } diff --git a/internal/config/grpc.go b/internal/config/grpc.go new file mode 100644 index 00000000..beae885a --- /dev/null +++ b/internal/config/grpc.go @@ -0,0 +1,19 @@ +package config + +import ( + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" + "time" +) + +func LoadGrpcConfiguration(config Grpc) (grpc.ServerOption, error) { + minTime, err := time.ParseDuration(config.Keepalive.MinTime) + if err != nil { + return nil, err + } + + return grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ + MinTime: minTime, + PermitWithoutStream: config.Keepalive.PermitWithoutStream, + }), nil +} diff --git a/internal/config/oidc.go b/internal/config/oidc.go new file mode 100644 index 00000000..47e37f76 --- /dev/null +++ b/internal/config/oidc.go @@ -0,0 +1,87 @@ +package config + +import ( + "context" + + "github.com/jumpstarter-dev/jumpstarter-controller/internal/oidc" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/apis/apiserver" + apiserverv1beta1 "k8s.io/apiserver/pkg/apis/apiserver/v1beta1" + "k8s.io/apiserver/pkg/authentication/authenticator" + tokenunion "k8s.io/apiserver/pkg/authentication/token/union" + "k8s.io/apiserver/pkg/server/dynamiccertificates" + koidc "k8s.io/apiserver/plugin/pkg/authenticator/token/oidc" +) + +func LoadAuthenticationConfiguration( + ctx context.Context, + scheme *runtime.Scheme, + config Authentication, + signer *oidc.Signer, + certificateAuthority string, +) (authenticator.Token, string, error) { + if config.Internal.Prefix == "" { + config.Internal.Prefix = "internal:" + } + + config.JWT = append(config.JWT, apiserverv1beta1.JWTAuthenticator{ + Issuer: apiserverv1beta1.Issuer{ + URL: signer.Issuer(), + CertificateAuthority: certificateAuthority, + Audiences: []string{signer.Audience()}, + }, + ClaimMappings: apiserverv1beta1.ClaimMappings{ + Username: apiserverv1beta1.PrefixedClaimOrExpression{ + Claim: "sub", + Prefix: &config.Internal.Prefix, + }, + }, + }) + + authn, err := newJWTAuthenticator( + ctx, + scheme, + config, + ) + if err != nil { + return nil, "", err + } + + return authn, config.Internal.Prefix, nil +} + +// Reference: https://github.com/kubernetes/kubernetes/blob/v1.32.1/pkg/kubeapiserver/authenticator/config.go#L244 +func newJWTAuthenticator( + ctx context.Context, + scheme *runtime.Scheme, + config Authentication, +) (authenticator.Token, error) { + var jwtAuthenticators []authenticator.Token + for _, jwtAuthenticator := range config.JWT { + var oidcCAContent koidc.CAContentProvider + if len(jwtAuthenticator.Issuer.CertificateAuthority) > 0 { + var oidcCAError error + oidcCAContent, oidcCAError = dynamiccertificates.NewStaticCAContent( + "oidc-authenticator", + []byte(jwtAuthenticator.Issuer.CertificateAuthority), + ) + if oidcCAError != nil { + return nil, oidcCAError + } + } + var jwtAuthenticatorUnversioned apiserver.JWTAuthenticator + if err := scheme.Convert(&jwtAuthenticator, &jwtAuthenticatorUnversioned, nil); err != nil { + return nil, err + } + oidcAuth, err := koidc.New(ctx, koidc.Options{ + JWTAuthenticator: jwtAuthenticatorUnversioned, + CAContentProvider: oidcCAContent, + SupportedSigningAlgs: koidc.AllValidSigningAlgorithms(), + }) + if err != nil { + return nil, err + } + jwtAuthenticators = append(jwtAuthenticators, oidcAuth) + } + return tokenunion.NewFailOnError(jwtAuthenticators...), nil +} diff --git a/internal/config/types.go b/internal/config/types.go new file mode 100644 index 00000000..28726dfe --- /dev/null +++ b/internal/config/types.go @@ -0,0 +1,28 @@ +package config + +import ( + apiserverv1beta1 "k8s.io/apiserver/pkg/apis/apiserver/v1beta1" +) + +type Config struct { + Authentication Authentication `json:"authentication"` + Grpc Grpc `json:"grpc"` +} + +type Authentication struct { + Internal Internal `json:"internal"` + JWT []apiserverv1beta1.JWTAuthenticator `json:"jwt"` +} + +type Internal struct { + Prefix string `json:"prefix"` +} + +type Grpc struct { + Keepalive Keepalive `json:"keepalive"` +} + +type Keepalive struct { + MinTime string `json:"minTime"` + PermitWithoutStream bool `json:"permitWithoutStream"` +} diff --git a/internal/service/controller_service.go b/internal/service/controller_service.go index 06a591e9..5c4497ac 100644 --- a/internal/service/controller_service.go +++ b/internal/service/controller_service.go @@ -69,6 +69,7 @@ type ControllerService struct { Authn authentication.ContextAuthenticator Authz authorizer.Authorizer Attr authorization.ContextAttributesGetter + ServerOption grpc.ServerOption listenQueues sync.Map } @@ -661,7 +662,7 @@ func (s *ControllerService) Start(ctx context.Context) error { } server := grpc.NewServer( - KeepaliveEnforcementPolicy(), + s.ServerOption, grpc.UnaryInterceptor(func( gctx context.Context, req any, diff --git a/internal/service/grpc.go b/internal/service/grpc.go deleted file mode 100644 index a56a27a0..00000000 --- a/internal/service/grpc.go +++ /dev/null @@ -1,15 +0,0 @@ -package service - -import ( - "time" - - "google.golang.org/grpc" - "google.golang.org/grpc/keepalive" -) - -func KeepaliveEnforcementPolicy() grpc.ServerOption { - return grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ - MinTime: 30 * time.Second, - PermitWithoutStream: true, - }) -} diff --git a/internal/service/router_service.go b/internal/service/router_service.go index 344b4374..067581a0 100644 --- a/internal/service/router_service.go +++ b/internal/service/router_service.go @@ -40,8 +40,9 @@ import ( type RouterService struct { pb.UnimplementedRouterServiceServer client.Client - Scheme *runtime.Scheme - pending sync.Map + Scheme *runtime.Scheme + ServerOption grpc.ServerOption + pending sync.Map } type streamContext struct { @@ -124,7 +125,7 @@ func (s *RouterService) Start(ctx context.Context) error { server := grpc.NewServer( grpc.Creds(credentials.NewServerTLSFromCert(cert)), - KeepaliveEnforcementPolicy(), + s.ServerOption, ) pb.RegisterRouterServiceServer(server, s) From a93a197b50a5073146ccc60daec4b75d8a815acd Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 09:45:27 -0400 Subject: [PATCH 2/8] Add annotations to routes --- .../jumpstarter-controller/templates/controller-route.yaml | 5 ++++- .../jumpstarter-controller/templates/router-route.yaml | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml index 3d040679..f7a781f0 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml @@ -5,6 +5,9 @@ metadata: labels: external-exposed: "true" shard: external + annotations: + haproxy.router.openshift.io/timeout: 2d + haproxy.router.openshift.io/timeout-tunnel: 2d name: jumpstarter-controller-route namespace: {{ default .Release.Namespace .Values.namespace }} spec: @@ -28,4 +31,4 @@ spec: name: jumpstarter-grpc weight: 100 wildcardPolicy: None -{{ end }} \ No newline at end of file +{{ end }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml index 9220726c..e0659fbe 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml @@ -5,6 +5,9 @@ metadata: labels: external-exposed: "true" shard: external + annotations: + haproxy.router.openshift.io/timeout: 2d + haproxy.router.openshift.io/timeout-tunnel: 2d name: jumpstarter-router-route namespace: {{ default .Release.Namespace .Values.namespace }} spec: @@ -33,4 +36,4 @@ spec: name: jumpstarter-router-grpc weight: 100 wildcardPolicy: None -{{ end }} \ No newline at end of file +{{ end }} From 63849276f4f7a073e236cf7fe1677ebf44b2acb7 Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 09:55:59 -0400 Subject: [PATCH 3/8] Rollout deployment when configmap is changed --- .../jumpstarter-controller/templates/controller-deployment.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml index 6fb8d932..0549d9fc 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml @@ -9,6 +9,8 @@ metadata: {{ if .Values.global.timestamp }} deployment.timestamp: {{ .Values.global.timestamp | quote }} {{ end }} + annotations: + configmap-sha256: {{ include (print $.Template.BasePath "/cms/controller-cm.yaml") . | sha256sum }} spec: selector: matchLabels: From b97424d8031db981873a58a9074758cc19de519a Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 10:45:08 -0400 Subject: [PATCH 4/8] Fixup values doc --- deploy/helm/jumpstarter/values.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/deploy/helm/jumpstarter/values.yaml b/deploy/helm/jumpstarter/values.yaml index 5780400f..9d80f712 100644 --- a/deploy/helm/jumpstarter/values.yaml +++ b/deploy/helm/jumpstarter/values.yaml @@ -30,8 +30,12 @@ global: ## @param jumpstarter-controller.imagePullPolicy Image pull policy for the controller. ## @param jumpstarter-controller.namespace Namespace where the controller will be deployed, defaults to global.namespace. -## @param jumpstarter-controller.grpcConfig Configuration for gRPC server options -## @param jumpstarter-controller.authenticationConfig Configuration for OIDC authentication, see https://kubernetes.io/docs/reference/access-authn-authz/authentication/#using-authentication-configuration for documentation + +## @param jumpstarter-controller.config.grpc.keepalive.minTime. The minimum amount of time a client should wait before sending a keepalive ping. +## @param jumpstarter-controller.config.grpc.keepalive.permitWithoutStream. Whether to allow keepalive pings even when there are no active streams(RPCs). + +## @param jumpstarter-controller.config.authentication.internal.prefix. Prefix to add to the subject claim of the tokens issued by the builtin authenticator. +## @param jumpstarter-controller.config.authentication.jwt. External OIDC authentication, see https://kubernetes.io/docs/reference/access-authn-authz/authentication/#using-authentication-configuration for documentation ## @section Ingress And Route parameters ## @descriptionStart This section contains parameters for the Ingress and Route configurations. @@ -74,7 +78,9 @@ jumpstarter-controller: # https://grpc.io/docs/guides/keepalive/#how-configuring-keepalive-affects-a-call minTime: 3s permitWithoutStream: true - authentication: {} + authentication: + internal: + prefix: "internal:" # jwt: # - issuer: # url: https://10.239.206.8:5556/dex From ff728655b34fa3caecefacfcb208408a320d9b0b Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 10:46:27 -0400 Subject: [PATCH 5/8] Fix lint --- internal/config/grpc.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/config/grpc.go b/internal/config/grpc.go index beae885a..dcb40097 100644 --- a/internal/config/grpc.go +++ b/internal/config/grpc.go @@ -1,9 +1,10 @@ package config import ( + "time" + "google.golang.org/grpc" "google.golang.org/grpc/keepalive" - "time" ) func LoadGrpcConfiguration(config Grpc) (grpc.ServerOption, error) { From 4818109377765616936371b2273c883f12ac326d Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 10:55:08 -0400 Subject: [PATCH 6/8] Prioritize old config format --- internal/config/config.go | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index f6453859..aaa7a05d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -28,18 +28,12 @@ func LoadConfiguration( return nil, "", nil, err } - rawConfig, ok := configmap.Data["config"] + rawAuthenticationConfiguration, ok := configmap.Data["authentication"] if ok { - var config Config - err := yaml.UnmarshalStrict([]byte(rawConfig), &config) - if err != nil { - return nil, "", nil, err - } - - authenticator, prefix, err := LoadAuthenticationConfiguration( + authenticator, prefix, err := oidc.LoadAuthenticationConfiguration( ctx, scheme, - config.Authentication, + []byte(rawAuthenticationConfiguration), signer, certificateAuthority, ) @@ -47,23 +41,27 @@ func LoadConfiguration( return nil, "", nil, err } - serverOptions, err := LoadGrpcConfiguration(config.Grpc) - if err != nil { - return nil, "", nil, err - } - - return authenticator, prefix, serverOptions, nil + return authenticator, prefix, grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ + MinTime: 1 * time.Second, + PermitWithoutStream: true, + }), nil } - rawAuthenticationConfiguration, ok := configmap.Data["authentication"] + rawConfig, ok := configmap.Data["config"] if !ok { - return nil, "", nil, fmt.Errorf("LoadConfiguration: missing authentication section") + return nil, "", nil, fmt.Errorf("LoadConfiguration: missing config section") + } + + var config Config + err := yaml.UnmarshalStrict([]byte(rawConfig), &config) + if err != nil { + return nil, "", nil, err } - authenticator, prefix, err := oidc.LoadAuthenticationConfiguration( + authenticator, prefix, err := LoadAuthenticationConfiguration( ctx, scheme, - []byte(rawAuthenticationConfiguration), + config.Authentication, signer, certificateAuthority, ) @@ -71,8 +69,10 @@ func LoadConfiguration( return nil, "", nil, err } - return authenticator, prefix, grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ - MinTime: 1 * time.Second, - PermitWithoutStream: true, - }), nil + serverOptions, err := LoadGrpcConfiguration(config.Grpc) + if err != nil { + return nil, "", nil, err + } + + return authenticator, prefix, serverOptions, nil } From 17c2c33d446d4d29d489355975eac31f5bd319ae Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 11:04:59 -0400 Subject: [PATCH 7/8] fixup! Prioritize old config format --- .../jumpstarter-controller/templates/cms/controller-cm.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml index d400ab2c..533eeff5 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml @@ -10,5 +10,8 @@ metadata: deployment.timestamp: {{ .Values.global.timestamp | quote }} {{ end }} data: + {{ if .Values.authenticationConfig }} + authentication: {{- .Values.authenticationConfig | toYaml | indent 1 }} + {{ end }} config: | {{ .Values.config | toYaml | indent 4 }} From 40d178de866ef3c924853c3063cd0661c8d58e7a Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 19 Mar 2025 13:54:36 -0400 Subject: [PATCH 8/8] Add notes about backwards compatibility --- .../jumpstarter-controller/templates/cms/controller-cm.yaml | 2 ++ internal/config/config.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml index 533eeff5..ccf834ee 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml @@ -10,6 +10,8 @@ metadata: deployment.timestamp: {{ .Values.global.timestamp | quote }} {{ end }} data: + # backwards compatibility + # TODO: remove in 0.7.0 {{ if .Values.authenticationConfig }} authentication: {{- .Values.authenticationConfig | toYaml | indent 1 }} {{ end }} diff --git a/internal/config/config.go b/internal/config/config.go index aaa7a05d..e538469d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -30,6 +30,8 @@ func LoadConfiguration( rawAuthenticationConfiguration, ok := configmap.Data["authentication"] if ok { + // backwards compatibility + // TODO: remove in 0.7.0 authenticator, prefix, err := oidc.LoadAuthenticationConfiguration( ctx, scheme,