Embed cluster CA in kubeconfig in necessary#37
Open
matejvasek wants to merge 8 commits into
Open
Conversation
The kubeconfig for GitHub Actions previously hardcoded insecure-skip-tls-verify, skipping TLS verification entirely. A new backend endpoint (GET /api/cluster/ca) reads the service account CA bundle, probes the API server's TLS certificate, and returns the CA only when the bundle actually verifies the handshake. If the bundle does not work (e.g. a mismatched intermediate after a Let's Encrypt rotation), it is omitted and the runner's system trust store handles verification instead. Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
Add a system roots probe before the SA bundle probe. If the API server's cert is already publicly trusted, the CA is not embedded in the kubeconfig. This avoids shipping public CAs that may break after intermediate rotation (e.g. Let's Encrypt) while still embedding private ones that a GitHub Actions runner would not otherwise trust. Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com> fixup: correct JSDoc on generateKubeconfig function Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Matej Vašek <matejvasek@gmail.com> fix: copy CA trust bundle into ubi9-micro runtime image ubi9-micro ships with no CA certificates, so the system roots TLS probe always failed and every cluster appeared to use a private CA. Copy the RHEL CA bundle from the go-toolset build stage so probe 1 can correctly identify publicly trusted certs. Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
Replace the global saCAPath variable and systemTLSConfig function with a clusterCAHandler struct that holds CAPath and SystemTLS as fields. Tests construct their own handler instances instead of mutating and restoring globals. Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
A missing service account CA file now returns an error instead of silently returning null. The MissingCAFile test is fixed to use a local TLS server so probe 1 always fails, ensuring the test actually exercises the file-read path. Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
Add a CLI flag to override the default CA path so init.sh can extract the cluster CA via oc and pass it to the backend. This lets the /api/cluster/ca endpoint work outside a pod where the service account mount is not available. Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Matej Vašek <matejvasek@gmail.com>
Cover the two previously untested error paths in clusterCAHandler: an empty CA file with no PEM blocks, and a CA file with a valid PEM envelope but corrupt DER content. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Matej Vašek <matejvasek@gmail.com>
Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
Collaborator
Author
|
/cc @dsimansk |
dsimansk
reviewed
Jun 11, 2026
| mux.HandleFunc("POST /api/function/create", handleFuncCreate) | ||
| mux.Handle("GET /api/cluster/ca", &clusterCAHandler{CAPath: *caPath}) | ||
| mux.Handle("/", http.FileServer(http.FS(static))) | ||
|
|
Contributor
There was a problem hiding this comment.
I'm thinking if this couldn't be controller-runtime based controller with addition of static HTTP serve on top of it. But that's broader decision. Currently it make sense as it is.
Collaborator
There was a problem hiding this comment.
Yeah, we probably move the backen to the functions operator eventually. It's not decided yet.
twoGiants
requested changes
Jun 12, 2026
twoGiants
left a comment
Collaborator
There was a problem hiding this comment.
Just a few comments so far. Review is in progress.
| mux.HandleFunc("POST /api/function/create", handleFuncCreate) | ||
| mux.Handle("GET /api/cluster/ca", &clusterCAHandler{CAPath: *caPath}) | ||
| mux.Handle("/", http.FileServer(http.FS(static))) | ||
|
|
Collaborator
There was a problem hiding this comment.
Yeah, we probably move the backen to the functions operator eventually. It's not decided yet.
Move func create handler to func_create.go and cluster CA handler to cluster_ca.go. Extract jsonOK helper to deduplicate the JSON response pattern. Use guard clause in the PEM parsing loop to reduce nesting. Signed-off-by: Matej Vašek <matejvasek@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
Collaborator
Author
|
@twoGiants I did suggested changes. |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
insecure-skip-tls-verify: truein generated kubeconfigs with proper CA certificate handlingGET /api/cluster/causes a two-probe approach: first tries system roots (public CA), then the service account CA bundle (private CA)ubi9-microruntime image (it ships with no CA infrastructure at all)Changes
Backend (
backend/main.go,backend/main_test.go)clusterCAHandlerstruct with injectableSystemTLSfor testability--kube-root-ca-pathCLI flag to override the default SA CA path for local devFrontend (
OcpClusterService.ts,OcpClusterService.test.ts)#fetchClusterCAcalls the backend via the console proxy#buildKubeconfigconditionally setscertificate-authority-datainstead ofinsecure-skip-tls-verifyDev environment (
init.sh)extract_cluster_caextracts the CA fromkube-root-ca.crtConfigMap viaoc--kube-root-ca-pathto the backend on startup and on file-watch restartContainer image (
Dockerfile)/etc/pki/tls/certs/ca-bundle.crtfromgo-toolsetbuild stage intoubi9-microTest plan
go test -v ./...(8 tests pass)yarn ci(lint + 14 suites / 127 tests + build){ca: null}{ca: "<base64>"}certificate-authority-data🤖 Generated with Claude Code