From 4d799f17295ed6538da2ff79902b5c174f9c85e9 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Thu, 2 Oct 2025 17:09:41 -0400 Subject: [PATCH] Add support for TLS profiles Use Mozilla's profiles to define TLS profiles for operator-controller and catalogd. These are configured via command-line options, and can be customized. The idea is that downstream, cluster-olm-operator will be able to glean the appropriate configuration, and provide that to the components. There is a semi-automatic method to update the profiles, if that ever happens (`make update-tls-profiles`). This adds `gojq` via bingo, which is a golang implementation of jq for the update-tls-profiles target. Signed-off-by: Todd Short --- .bingo/Variables.mk | 6 + .bingo/gojq.mod | 5 + .bingo/gojq.sum | 17 ++ .bingo/variables.env | 2 + Makefile | 6 +- cmd/catalogd/main.go | 10 +- cmd/operator-controller/main.go | 10 + go.mod | 2 +- hack/tools/update-tls-profiles.sh | 69 +++++++ ...mv1-system-catalogd-controller-manager.yml | 7 + ...operator-controller-controller-manager.yml | 3 + internal/shared/util/tlsprofiles/flags.go | 189 ++++++++++++++++++ .../shared/util/tlsprofiles/mozilla_data.go | 87 ++++++++ .../shared/util/tlsprofiles/tlsprofiles.go | 91 +++++++++ .../util/tlsprofiles/tlsprofiles_test.go | 160 +++++++++++++++ manifests/experimental-e2e.yaml | 5 + manifests/standard-e2e.yaml | 5 + 17 files changed, 671 insertions(+), 3 deletions(-) create mode 100644 .bingo/gojq.mod create mode 100644 .bingo/gojq.sum create mode 100755 hack/tools/update-tls-profiles.sh create mode 100644 internal/shared/util/tlsprofiles/flags.go create mode 100644 internal/shared/util/tlsprofiles/mozilla_data.go create mode 100644 internal/shared/util/tlsprofiles/tlsprofiles.go create mode 100644 internal/shared/util/tlsprofiles/tlsprofiles_test.go diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk index bb7a73d3bf..280913c462 100644 --- a/.bingo/Variables.mk +++ b/.bingo/Variables.mk @@ -41,6 +41,12 @@ $(CRD_REF_DOCS): $(BINGO_DIR)/crd-ref-docs.mod @echo "(re)installing $(GOBIN)/crd-ref-docs-v0.1.0" @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=crd-ref-docs.mod -o=$(GOBIN)/crd-ref-docs-v0.1.0 "github.com/elastic/crd-ref-docs" +GOJQ := $(GOBIN)/gojq-v0.12.17 +$(GOJQ): $(BINGO_DIR)/gojq.mod + @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. + @echo "(re)installing $(GOBIN)/gojq-v0.12.17" + @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=gojq.mod -o=$(GOBIN)/gojq-v0.12.17 "github.com/itchyny/gojq/cmd/gojq" + GOLANGCI_LINT := $(GOBIN)/golangci-lint-v2.1.6 $(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. diff --git a/.bingo/gojq.mod b/.bingo/gojq.mod new file mode 100644 index 0000000000..004aae3b13 --- /dev/null +++ b/.bingo/gojq.mod @@ -0,0 +1,5 @@ +module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT + +go 1.24.4 + +require github.com/itchyny/gojq v0.12.17 // cmd/gojq diff --git a/.bingo/gojq.sum b/.bingo/gojq.sum new file mode 100644 index 0000000000..e87b5b0e34 --- /dev/null +++ b/.bingo/gojq.sum @@ -0,0 +1,17 @@ +github.com/itchyny/gojq v0.12.17 h1:8av8eGduDb5+rvEdaOO+zQUjA04MS0m3Ps8HiD+fceg= +github.com/itchyny/gojq v0.12.17/go.mod h1:WBrEMkgAfAGO1LUcGOckBl5O726KPp+OlkKug0I/FEY= +github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= +github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/.bingo/variables.env b/.bingo/variables.env index b814c363ef..b1e721562f 100644 --- a/.bingo/variables.env +++ b/.bingo/variables.env @@ -16,6 +16,8 @@ CRD_DIFF="${GOBIN}/crd-diff-v0.2.0" CRD_REF_DOCS="${GOBIN}/crd-ref-docs-v0.1.0" +GOJQ="${GOBIN}/gojq-v0.12.17" + GOLANGCI_LINT="${GOBIN}/golangci-lint-v2.1.6" GORELEASER="${GOBIN}/goreleaser-v1.26.2" diff --git a/Makefile b/Makefile index 364b44e650..aeef28afce 100644 --- a/Makefile +++ b/Makefile @@ -178,7 +178,7 @@ generate: $(CONTROLLER_GEN) #EXHELP Generate code containing DeepCopy, DeepCopyI $(CONTROLLER_GEN) --load-build-tags=$(GO_BUILD_TAGS) object:headerFile="hack/boilerplate.go.txt" paths="./..." .PHONY: verify -verify: k8s-pin kind-verify-versions fmt generate manifests crd-ref-docs #HELP Verify all generated code is up-to-date. Runs k8s-pin instead of just tidy. +verify: k8s-pin kind-verify-versions fmt generate manifests update-tls-profiles crd-ref-docs #HELP Verify all generated code is up-to-date. Runs k8s-pin instead of just tidy. git diff --exit-code .PHONY: fix-lint @@ -189,6 +189,10 @@ fix-lint: $(GOLANGCI_LINT) #EXHELP Fix lint issues fmt: #EXHELP Formats code go fmt ./... +.PHONY: update-tls-profiles +update-tls-profiles: $(GOJQ) #EXHELP Update TLS profiles from the Mozilla wiki + env JQ=$(GOJQ) hack/tools/update-tls-profiles.sh + .PHONY: verify-crd-compatibility CRD_DIFF_ORIGINAL_REF := git://main?path= CRD_DIFF_UPDATED_REF := file:// diff --git a/cmd/catalogd/main.go b/cmd/catalogd/main.go index e5f1678a00..36f7b16752 100644 --- a/cmd/catalogd/main.go +++ b/cmd/catalogd/main.go @@ -64,6 +64,7 @@ import ( imageutil "github.com/operator-framework/operator-controller/internal/shared/util/image" "github.com/operator-framework/operator-controller/internal/shared/util/pullsecretcache" sautil "github.com/operator-framework/operator-controller/internal/shared/util/sa" + "github.com/operator-framework/operator-controller/internal/shared/util/tlsprofiles" "github.com/operator-framework/operator-controller/internal/shared/version" ) @@ -142,6 +143,7 @@ func init() { klog.InitFlags(flag.CommandLine) flags.AddGoFlagSet(flag.CommandLine) features.CatalogdFeatureGate.AddFlag(flags) + tlsprofiles.AddFlags(flags) utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(ocv1.AddToScheme(scheme)) @@ -216,12 +218,18 @@ func run(ctx context.Context) error { // For details, see: https://github.com/kubernetes/kubernetes/issues/121197 config.NextProtos = []string{"http/1.1"} } + tlsProfile, err := tlsprofiles.GetTLSConfigFunc() + if err != nil { + setupLog.Error(err, "failed to get TLS profile") + return err + } // Create webhook server and configure TLS webhookServer := crwebhook.NewServer(crwebhook.Options{ Port: cfg.webhookPort, TLSOpts: []func(*tls.Config){ tlsOpts, + tlsProfile, }, }) @@ -233,7 +241,7 @@ func run(ctx context.Context) error { metricsServerOptions.SecureServing = true metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization - metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, tlsOpts) + metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, tlsOpts, tlsProfile) } else { // Note that the metrics server is not serving if the BindAddress is set to "0". // Therefore, the metrics server is disabled by default. It is only enabled diff --git a/cmd/operator-controller/main.go b/cmd/operator-controller/main.go index 85f2e823d1..c253bcd2bf 100644 --- a/cmd/operator-controller/main.go +++ b/cmd/operator-controller/main.go @@ -82,6 +82,7 @@ import ( imageutil "github.com/operator-framework/operator-controller/internal/shared/util/image" "github.com/operator-framework/operator-controller/internal/shared/util/pullsecretcache" sautil "github.com/operator-framework/operator-controller/internal/shared/util/sa" + "github.com/operator-framework/operator-controller/internal/shared/util/tlsprofiles" "github.com/operator-framework/operator-controller/internal/shared/version" ) @@ -166,6 +167,9 @@ func init() { //add feature gate flags to flagset features.OperatorControllerFeatureGate.AddFlag(flags) + //add TLS flags + tlsprofiles.AddFlags(flags) + ctrl.SetLogger(klog.NewKlogr()) } func validateMetricsFlags() error { @@ -274,6 +278,12 @@ func run() error { // the risks. More info https://github.com/golang/go/issues/63417 config.NextProtos = []string{"http/1.1"} }) + tlsProfile, err := tlsprofiles.GetTLSConfigFunc() + if err != nil { + setupLog.Error(err, "failed to get TLS profile") + return err + } + metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, tlsProfile) } else { // Note that the metrics server is not serving if the BindAddress is set to "0". // Therefore, the metrics server is disabled by default. It is only enabled diff --git a/go.mod b/go.mod index ef5de2715f..5cf79f5da6 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/prometheus/client_golang v1.23.2 github.com/prometheus/common v0.66.1 github.com/spf13/cobra v1.10.1 + github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 go.podman.io/image/v5 v5.37.0 golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b @@ -199,7 +200,6 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smallstep/pkcs7 v0.2.1 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.10 // indirect github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect github.com/stoewer/go-strcase v1.3.1 // indirect github.com/stretchr/objx v0.5.2 // indirect diff --git a/hack/tools/update-tls-profiles.sh b/hack/tools/update-tls-profiles.sh new file mode 100755 index 0000000000..54d0b18277 --- /dev/null +++ b/hack/tools/update-tls-profiles.sh @@ -0,0 +1,69 @@ +#!/bin/env bash + +set -e + +if [ -z "${JQ}" ]; then + echo "JQ not defined" + exit 1 +fi + +OUTPUT=internal/shared/util/tlsprofiles/mozilla_data.go +INPUT=https://ssl-config.mozilla.org/guidelines/latest.json + +TMPFILE="$(mktemp)" +trap 'rm -rf "$TMPFILE"' EXIT + +curl -L -s ${INPUT} > ${TMPFILE} + +version=$(${JQ} -r '.version' ${TMPFILE}) + +cat > ${OUTPUT} <> ${OUTPUT} <> ${OUTPUT} + ${JQ} -r ".configurations.$1.ciphers.go[] | . |= \"tls.\" + . + \",\"" ${TMPFILE} >> ${OUTPUT} + + cat >> ${OUTPUT} <> ${OUTPUT} + + version=$(${JQ} -r ".configurations.$1.tls_versions[0]" ${TMPFILE}) + version=${version/TLSv1./tls.VersionTLS1} + version=${version/TLSv1/tls.VersionTLS10} + + cat >> ${OUTPUT} <