-
Notifications
You must be signed in to change notification settings - Fork 23
tls ca distribution to OIDC login users + easier login #180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
57bc799
controller: add LoginService for simplified CLI login
mangelajo a182a94
operator: add LoginConfig type to CRD
mangelajo cbc17be
operator: add login endpoint reconciliation
mangelajo 6035fbd
helm: add login endpoint templates and values
mangelajo ae07a91
cli: support simplified jmp login [user@]endpoint syntax
mangelajo ab686f0
e2e: add login endpoint tests
mangelajo 1dbb06e
operator: make CA_BUNDLE_PEM required when cert-manager enabled
mangelajo b711487
e2e: add NodePort support for login service
mangelajo d863d84
helm: remove unused login.endpoint field
mangelajo 87ce428
e2e: add LOGIN_ENDPOINT to setup environment
mangelajo ba905f7
operator: fix NodePort port assignment for all endpoints
mangelajo 6fbf37e
operator: fix CA bundle not being set in login service
mangelajo 540d02f
login: base64 encode CA bundle in auth config response
mangelajo 81a64c1
cli: improve jmp login UX for simplified login format
mangelajo 4ef5f8b
e2e: add assertions to verify CA certificate in config files
mangelajo 414bd16
e2e: fix --name "" parsing issue in login test
mangelajo 1211491
easy-login: remove unnecessary info from login page
mangelajo 5017256
easy-login: fix bats tests
mangelajo 2bb8553
login: add LOGIN_ENDPOINT for landing page display
mangelajo fc392da
helm: simplify LOGIN_ENDPOINT to only use endpoint field
mangelajo 0a32196
cli: auto-set default client after OIDC login
mangelajo ac8a5d3
e2e: verify simplified login sets client as default
mangelajo 0bc3dc8
easy-login: fix login default-user and check
mangelajo 2f3d841
easy-login: allow explicit tls secrets for login
mangelajo 367a1d0
easy-login: auto-create login endpoint when not specified
mangelajo 9dccef2
easy-login: fix helm linting
mangelajo c382b0d
easy-login: avoid e2e test issues by table column wrapping
mangelajo b263407
easy-login: fix broken nodeport router replicas
mangelajo 0783ecb
easy-login: address review comments
mangelajo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,10 +27,13 @@ import ( | |
| // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) | ||
| // to ensure that exec-entrypoint and run can make use of them. | ||
| apiserverinstall "k8s.io/apiserver/pkg/apis/apiserver/install" | ||
| apiserverv1beta1 "k8s.io/apiserver/pkg/apis/apiserver/v1beta1" | ||
| _ "k8s.io/client-go/plugin/pkg/client/auth" | ||
|
|
||
| corev1 "k8s.io/api/core/v1" | ||
| "k8s.io/apimachinery/pkg/runtime" | ||
| utilruntime "k8s.io/apimachinery/pkg/util/runtime" | ||
| "k8s.io/apimachinery/pkg/util/yaml" | ||
| clientgoscheme "k8s.io/client-go/kubernetes/scheme" | ||
| ctrl "sigs.k8s.io/controller-runtime" | ||
| "sigs.k8s.io/controller-runtime/pkg/cache" | ||
|
|
@@ -47,6 +50,7 @@ import ( | |
| "github.com/jumpstarter-dev/jumpstarter-controller/internal/controller" | ||
| "github.com/jumpstarter-dev/jumpstarter-controller/internal/oidc" | ||
| "github.com/jumpstarter-dev/jumpstarter-controller/internal/service" | ||
| "github.com/jumpstarter-dev/jumpstarter-controller/internal/service/login" | ||
|
|
||
| // +kubebuilder:scaffold:imports | ||
|
|
||
|
|
@@ -298,6 +302,16 @@ func main() { | |
| os.Exit(1) | ||
| } | ||
|
|
||
| // Setup Login Service for simplified CLI login | ||
| loginService := login.NewServiceFromEnv() | ||
| // Extract OIDC configuration from the loaded config for the login service | ||
| oidcConfigs := extractOIDCConfigs(mgr.GetAPIReader(), watchNamespace) | ||
| loginService.SetOIDCConfig(oidcConfigs) | ||
| if err = loginService.SetupWithManager(mgr); err != nil { | ||
| setupLog.Error(err, "unable to create service", "service", "Login") | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { | ||
| setupLog.Error(err, "unable to set up health check") | ||
| os.Exit(1) | ||
|
|
@@ -313,3 +327,52 @@ func main() { | |
| os.Exit(1) | ||
| } | ||
| } | ||
|
|
||
| // extractOIDCConfigs reads the OIDC configuration from the ConfigMap | ||
| func extractOIDCConfigs(reader client.Reader, namespace string) []login.OIDCConfig { | ||
| var configmap corev1.ConfigMap | ||
| if err := reader.Get(context.Background(), client.ObjectKey{ | ||
| Namespace: namespace, | ||
| Name: "jumpstarter-controller", | ||
| }, &configmap); err != nil { | ||
| setupLog.Error(err, "unable to read configmap for OIDC config") | ||
| return nil | ||
| } | ||
|
|
||
| // Try new config format first | ||
| rawConfig, ok := configmap.Data["config"] | ||
| if ok { | ||
| var cfg config.Config | ||
| if err := yaml.UnmarshalStrict([]byte(rawConfig), &cfg); err == nil { | ||
| return jwtAuthenticatorsToOIDCConfigs(cfg.Authentication.JWT) | ||
| } | ||
| } | ||
|
|
||
| // Fall back to legacy authentication format | ||
| rawAuth, ok := configmap.Data["authentication"] | ||
| if ok { | ||
| var auth config.Authentication | ||
| if err := yaml.Unmarshal([]byte(rawAuth), &auth); err == nil { | ||
| return jwtAuthenticatorsToOIDCConfigs(auth.JWT) | ||
| } | ||
| } | ||
|
|
||
|
Comment on lines
+351
to
+359
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need the legacy format anymore, remove this. |
||
| return nil | ||
| } | ||
|
|
||
| // jwtAuthenticatorsToOIDCConfigs converts JWT authenticators to login OIDC configs | ||
| func jwtAuthenticatorsToOIDCConfigs(authenticators []apiserverv1beta1.JWTAuthenticator) []login.OIDCConfig { | ||
| var configs []login.OIDCConfig | ||
| for _, auth := range authenticators { | ||
| // Skip internal OIDC provider (localhost) | ||
| if auth.Issuer.URL == "https://localhost:8085" { | ||
| continue | ||
| } | ||
| configs = append(configs, login.OIDCConfig{ | ||
| Issuer: auth.Issuer.URL, | ||
| ClientID: "jumpstarter-cli", // Default client ID for CLI | ||
| Audiences: auth.Issuer.Audiences, | ||
| }) | ||
| } | ||
| return configs | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
...roller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| {{ if and .Values.login.enabled .Values.login.ingress.enabled }} | ||
| apiVersion: networking.k8s.io/v1 | ||
| kind: Ingress | ||
| metadata: | ||
| labels: | ||
| component: login | ||
| {{- if .Values.login.ingress.labels }} | ||
| {{- toYaml .Values.login.ingress.labels | nindent 4 }} | ||
| {{- end }} | ||
| {{- if .Values.login.ingress.annotations }} | ||
| annotations: | ||
| {{- toYaml .Values.login.ingress.annotations | nindent 4 }} | ||
| {{- end }} | ||
| name: jumpstarter-login-ing | ||
| namespace: {{ default .Release.Namespace .Values.namespace }} | ||
| spec: | ||
| {{- if .Values.login.ingress.class }} | ||
| ingressClassName: {{ .Values.login.ingress.class }} | ||
| {{- end }} | ||
| rules: | ||
| - host: {{ .Values.login.hostname | default (printf "login.%s" .Values.global.baseDomain) | required "a global.baseDomain or a login.hostname must be provided" }} | ||
| http: | ||
| paths: | ||
| - path: / | ||
| pathType: Prefix | ||
| backend: | ||
| service: | ||
| name: jumpstarter-login | ||
| port: | ||
| number: 8086 | ||
| tls: | ||
| - hosts: | ||
| - {{ .Values.login.hostname | default (printf "login.%s" .Values.global.baseDomain) }} | ||
| {{- /* Use login.tls.secretName (new), fallback to login.ingress.tls.secretName (legacy), then default */}} | ||
| secretName: {{ .Values.login.tls.secretName | default .Values.login.ingress.tls.secretName | default "jumpstarter-login-tls" }} | ||
| {{ end }} |
38 changes: 38 additions & 0 deletions
38
controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| {{ if and .Values.login.enabled .Values.login.route.enabled }} | ||
| apiVersion: route.openshift.io/v1 | ||
| kind: Route | ||
| metadata: | ||
| labels: | ||
| component: login | ||
| {{- if .Values.login.route.labels }} | ||
| {{- toYaml .Values.login.route.labels | nindent 4 }} | ||
| {{- end }} | ||
| {{- if .Values.login.route.annotations }} | ||
| annotations: | ||
| {{- toYaml .Values.login.route.annotations | nindent 4 }} | ||
| {{- end }} | ||
| name: jumpstarter-login-route | ||
| namespace: {{ default .Release.Namespace .Values.namespace }} | ||
| spec: | ||
| {{ if .Values.login.hostname }} | ||
| host: {{ .Values.login.hostname }} | ||
| {{ else }} | ||
| host: login.{{ .Values.global.baseDomain | required "a global.baseDomain or a login.hostname must be provided"}} | ||
| {{ end }} | ||
| port: | ||
| targetPort: 8086 | ||
| tls: | ||
| # Edge termination - TLS terminated at the router, plain HTTP to backend | ||
| termination: edge | ||
| insecureEdgeTerminationPolicy: Redirect | ||
| {{- if .Values.login.tls.secretName }} | ||
| # Reference TLS certificate from secret (OpenShift 4.14+) | ||
| externalCertificate: | ||
| name: {{ .Values.login.tls.secretName }} | ||
| {{- end }} | ||
| to: | ||
| kind: Service | ||
| name: jumpstarter-login | ||
| weight: 100 | ||
| wildcardPolicy: None | ||
| {{ end }} |
26 changes: 26 additions & 0 deletions
26
...roller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| {{ if .Values.login.enabled }} | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| labels: | ||
| control-plane: controller-manager | ||
| app.kubernetes.io/name: jumpstarter-controller | ||
| component: login | ||
| name: jumpstarter-login | ||
| namespace: {{ default .Release.Namespace .Values.namespace }} | ||
| spec: | ||
| {{ if .Values.login.nodeport.enabled }} | ||
| type: NodePort | ||
| {{ end }} | ||
|
|
||
| ports: | ||
| - name: login | ||
| port: 8086 | ||
| protocol: TCP | ||
| targetPort: 8086 | ||
| {{ if .Values.login.nodeport.enabled }} | ||
| nodePort: {{ .Values.login.nodeport.port }} | ||
| {{ end }} | ||
| selector: | ||
| control-plane: controller-manager | ||
| {{ end }} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears that the login service reads the OIDC configuration from the jumpstarter-controller ConfigMap only once at startup and does not refresh it afterward. If the configuration is updated later (for example a new issuer or audience), what will happen? It looks like /v1/auth/config would remain stale until the controller is restarted. We may need to add a watch mechanism to detect and apply ConfigMap changes dynamically (or some kind of documentation to perform a restart).
but It’s also possible that I’m missing an existing refresh path here, so please let me know if this is relevent :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right. This is a problem already with the general OIDC config I believe. I agree that a watching mechanism should help here. Address the previous bug (OIDC auth is not being refreshed for configmap changes), but also, that now we don't expose updated information on the endpoint. I will add the watcher! thank you :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I am having issues with this part, since it was a known issue, I will open a bug, and let's fix afterwards as a bug.
Opened: #196
I hope it sounds ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, fine by me.