Skip to content

Commit 4d92745

Browse files
authored
[release-1.21] feat: use knative.dev/pkg/network/tls for configurable TLS (#16482)
Backport of the following PRs from main to release-1.21: - #16424 feat: use knative.dev/pkg/tls for activator TLS configuration - #16425 feat: use knative.dev/pkg/tls for queue-proxy TLS configuration - #16431 feat: use knative.dev/pkg/tls for reconciler TLS configuration - #16458 Update TLS import path to knative.dev/pkg/network/tls Replace hardcoded tls.VersionTLS13 in the activator, queue-proxy, and tag-to-digest resolver with the shared knative.dev/pkg/network/tls package, allowing TLS settings (min/max version, cipher suites, curve preferences) to be configured via environment variables: - ACTIVATOR_TLS_* - QUEUE_PROXY_TLS_* - TAG_TO_DIGEST_TLS_* Add four new keys to the config-deployment ConfigMap (queue-sidecar-tls-min-version, queue-sidecar-tls-max-version, queue-sidecar-tls-cipher-suites, queue-sidecar-tls-curve-preferences) and forward them as QUEUE_PROXY_TLS_* environment variables in makeQueueContainer. The default remains TLS 1.3 when no env var is set. The tag-to-digest resolver default is bumped from TLS 1.2 to TLS 1.3. knative/pkg dependency: knative/pkg#3337 Signed-off-by: Mikhail Fedosin <mfedosin@redhat.com>
1 parent 69aa052 commit 4d92745

File tree

16 files changed

+389
-116
lines changed

16 files changed

+389
-116
lines changed

cmd/activator/main.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package main
1818

1919
import (
2020
"context"
21-
"crypto/tls"
2221
"errors"
2322
"fmt"
2423
"log"
@@ -47,6 +46,7 @@ import (
4746
pkglogging "knative.dev/pkg/logging"
4847
"knative.dev/pkg/logging/logkey"
4948
pkgnet "knative.dev/pkg/network"
49+
knativetls "knative.dev/pkg/network/tls"
5050
k8sruntime "knative.dev/pkg/observability/runtime/k8s"
5151
"knative.dev/pkg/signals"
5252
"knative.dev/pkg/system"
@@ -292,7 +292,7 @@ func main() {
292292
"profile": pprof.Server,
293293
}
294294

295-
errCh := make(chan error, len(servers))
295+
errCh := make(chan error, len(servers)+1)
296296
for name, server := range servers {
297297
go func(name string, s *http.Server) {
298298
// Don't forward ErrServerClosed as that indicates we're already shutting down.
@@ -306,17 +306,21 @@ func main() {
306306
// At this moment activator with TLS does not disable HTTP.
307307
// See also https://github.com/knative/serving/issues/12808.
308308
if tlsEnabled {
309-
name, server := "https", pkgnet.NewServer(":"+strconv.Itoa(networking.BackendHTTPSPort), ah)
310-
go func(name string, s *http.Server) {
311-
s.TLSConfig = &tls.Config{
312-
MinVersion: tls.VersionTLS13,
313-
GetCertificate: certCache.GetCertificate,
314-
}
309+
tlsCfg, err := knativetls.DefaultConfigFromEnv("ACTIVATOR_")
310+
if err != nil {
311+
logger.Fatalw("Failed to read TLS configuration from environment", zap.Error(err))
312+
}
313+
314+
server := pkgnet.NewServer(":"+strconv.Itoa(networking.BackendHTTPSPort), ah)
315+
servers["https"] = server
316+
go func(s *http.Server) {
317+
s.TLSConfig = tlsCfg
318+
s.TLSConfig.GetCertificate = certCache.GetCertificate
315319
// Don't forward ErrServerClosed as that indicates we're already shutting down.
316320
if err := s.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
317-
errCh <- fmt.Errorf("%s server failed: %w", name, err)
321+
errCh <- fmt.Errorf("https server failed: %w", err)
318322
}
319-
}(name, server)
323+
}(server)
320324
}
321325

322326
// Wait for the signal to drain.

config/core/configmaps/deployment.yaml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ metadata:
2222
app.kubernetes.io/component: controller
2323
app.kubernetes.io/version: devel
2424
annotations:
25-
knative.dev/example-checksum: "b99000ec"
25+
knative.dev/example-checksum: "555b4826"
2626
data:
2727
# This is the Go import path for the binary that is containerized
2828
# and substituted here.
@@ -92,6 +92,25 @@ data:
9292
# If omitted, or empty, no rootCA is added to the golang rootCAs
9393
queue-sidecar-rootca: ""
9494
95+
# Sets the minimum TLS version for the queue proxy sidecar's TLS server.
96+
# Accepted values: "1.2", "1.3". Default is "1.3" if not specified.
97+
queue-sidecar-tls-min-version: ""
98+
99+
# Sets the maximum TLS version for the queue proxy sidecar's TLS server.
100+
# Accepted values: "1.2", "1.3". If omitted, the Go default is used.
101+
queue-sidecar-tls-max-version: ""
102+
103+
# Sets the cipher suites for the queue proxy sidecar's TLS server.
104+
# Comma-separated list of cipher suite names (e.g. "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256").
105+
# If omitted, the Go default cipher suites are used.
106+
# Note: cipher suites are not configurable in TLS 1.3.
107+
queue-sidecar-tls-cipher-suites: ""
108+
109+
# Sets the elliptic curve preferences for the queue proxy sidecar's TLS server.
110+
# Comma-separated list of curve names (e.g. "X25519,CurveP256").
111+
# If omitted, the Go default curves are used.
112+
queue-sidecar-tls-curve-preferences: ""
113+
95114
# If set, it automatically configures pod anti-affinity requirements for all Knative services.
96115
# It employs the `preferredDuringSchedulingIgnoredDuringExecution` weighted pod affinity term,
97116
# aligning with the Knative revision label. It yields the configuration below in all workloads' deployments:

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ require (
4242
knative.dev/caching v0.0.0-20260120130310-f1fc03b7f5ee
4343
knative.dev/hack v0.0.0-20260120115810-bf6758cba446
4444
knative.dev/networking v0.0.0-20260120131110-a7cdca238a0d
45-
knative.dev/pkg v0.0.0-20260120122510-4a022ed9999a
45+
knative.dev/pkg v0.0.0-20260319144603-18c5d580ae64
4646
sigs.k8s.io/randfill v1.0.0
4747
sigs.k8s.io/yaml v1.6.0
4848
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,8 @@ knative.dev/hack v0.0.0-20260120115810-bf6758cba446 h1:Y8raYHIuAL9/gUKGYD9/dD+Eq
550550
knative.dev/hack v0.0.0-20260120115810-bf6758cba446/go.mod h1:L5RzHgbvam0u8QFHfzCX6MKxu/a/gIGEdaRBqNiVbl0=
551551
knative.dev/networking v0.0.0-20260120131110-a7cdca238a0d h1:QQ5QeH5MZlYdu6gRGGjmEBQ/CVoatiXKnVIrUoKlj4U=
552552
knative.dev/networking v0.0.0-20260120131110-a7cdca238a0d/go.mod h1:mZD2edO8op3zI6yLOn1yoz8xqbyZfrrDOJCbYElMEKs=
553-
knative.dev/pkg v0.0.0-20260120122510-4a022ed9999a h1:9f29OTA7w/iVIX6PS6yveVVzNbcUS74eQfchVe8o2/4=
554-
knative.dev/pkg v0.0.0-20260120122510-4a022ed9999a/go.mod h1:Tz3GoxcNC5vH3Zo//cW3mnHL474u+Y1wbsUIZ11p8No=
553+
knative.dev/pkg v0.0.0-20260319144603-18c5d580ae64 h1:TiwrcgUKNePfdAbaJT9W4P57lsKjiZnjJ0wVC6XrL0U=
554+
knative.dev/pkg v0.0.0-20260319144603-18c5d580ae64/go.mod h1:Tz3GoxcNC5vH3Zo//cW3mnHL474u+Y1wbsUIZ11p8No=
555555
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
556556
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
557557
sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM=

pkg/deployment/config.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ const (
7474
queueSidecarTokenAudiencesKey = "queue-sidecar-token-audiences"
7575
queueSidecarRooCAKey = "queue-sidecar-rootca"
7676

77+
// queueSidecar TLS configuration keys.
78+
queueSidecarTLSMinVersionKey = "queue-sidecar-tls-min-version"
79+
queueSidecarTLSMaxVersionKey = "queue-sidecar-tls-max-version"
80+
queueSidecarTLSCipherSuitesKey = "queue-sidecar-tls-cipher-suites"
81+
queueSidecarTLSCurvePreferencesKey = "queue-sidecar-tls-curve-preferences"
82+
7783
defaultAffinityTypeKey = "default-affinity-type"
7884
defaultAffinityTypeValue = PreferSpreadRevisionOverNodes
7985

@@ -202,6 +208,11 @@ func NewConfigFromMap(configMap map[string]string) (*Config, error) {
202208
cm.AsStringSet(queueSidecarTokenAudiencesKey, &nc.QueueSidecarTokenAudiences),
203209
cm.AsString(queueSidecarRooCAKey, &nc.QueueSidecarRootCA),
204210

211+
cm.AsString(queueSidecarTLSMinVersionKey, &nc.QueueSidecarTLSMinVersion),
212+
cm.AsString(queueSidecarTLSMaxVersionKey, &nc.QueueSidecarTLSMaxVersion),
213+
cm.AsString(queueSidecarTLSCipherSuitesKey, &nc.QueueSidecarTLSCipherSuites),
214+
cm.AsString(queueSidecarTLSCurvePreferencesKey, &nc.QueueSidecarTLSCurvePreferences),
215+
205216
cm.AsString(RuntimeClassNameKey, &runtimeClassNames),
206217

207218
cm.AsBool(podIsAlwaysSchedulableKey, &nc.PodIsAlwaysSchedulable),
@@ -308,6 +319,18 @@ type Config struct {
308319
// QueueSidecarRootCA is a root certificate to be trusted by the queue proxy sidecar qpoptions.
309320
QueueSidecarRootCA string
310321

322+
// QueueSidecarTLSMinVersion is the minimum TLS version for the queue proxy sidecar (e.g. "1.2", "1.3").
323+
QueueSidecarTLSMinVersion string
324+
325+
// QueueSidecarTLSMaxVersion is the maximum TLS version for the queue proxy sidecar (e.g. "1.2", "1.3").
326+
QueueSidecarTLSMaxVersion string
327+
328+
// QueueSidecarTLSCipherSuites is a comma-separated list of cipher suites for the queue proxy sidecar.
329+
QueueSidecarTLSCipherSuites string
330+
331+
// QueueSidecarTLSCurvePreferences is a comma-separated list of elliptic curves for the queue proxy sidecar.
332+
QueueSidecarTLSCurvePreferences string
333+
311334
// DefaultAffinityType is a string that controls what affinity rules will be automatically
312335
// applied to the PodSpec of all Knative services.
313336
DefaultAffinityType AffinityType

pkg/deployment/config_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,28 @@ kata:
472472
podIsAlwaysSchedulableKey: "true",
473473
QueueSidecarImageKey: defaultSidecarImage,
474474
},
475+
}, {
476+
name: "controller configuration with queue sidecar TLS settings",
477+
wantConfig: &Config{
478+
RegistriesSkippingTagResolving: sets.New("kind.local", "ko.local", "dev.local"),
479+
DigestResolutionTimeout: digestResolutionTimeoutDefault,
480+
QueueSidecarImage: defaultSidecarImage,
481+
QueueSidecarCPURequest: &QueueSidecarCPURequestDefault,
482+
QueueSidecarTokenAudiences: sets.New(""),
483+
ProgressDeadline: ProgressDeadlineDefault,
484+
DefaultAffinityType: defaultAffinityTypeValue,
485+
QueueSidecarTLSMinVersion: "1.2",
486+
QueueSidecarTLSMaxVersion: "1.3",
487+
QueueSidecarTLSCipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
488+
QueueSidecarTLSCurvePreferences: "X25519,CurveP256",
489+
},
490+
data: map[string]string{
491+
QueueSidecarImageKey: defaultSidecarImage,
492+
queueSidecarTLSMinVersionKey: "1.2",
493+
queueSidecarTLSMaxVersionKey: "1.3",
494+
queueSidecarTLSCipherSuitesKey: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
495+
queueSidecarTLSCurvePreferencesKey: "X25519,CurveP256",
496+
},
475497
}}
476498

477499
for _, tt := range configTests {

pkg/queue/sharedmain/main.go

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package sharedmain
1818

1919
import (
2020
"context"
21-
"crypto/tls"
2221
"encoding/json"
2322
"errors"
2423
"fmt"
@@ -31,6 +30,7 @@ import (
3130

3231
netproxy "knative.dev/networking/pkg/http/proxy"
3332
pkghandler "knative.dev/pkg/network/handlers"
33+
knativetls "knative.dev/pkg/network/tls"
3434
"knative.dev/serving/pkg/activator"
3535

3636
"github.com/kelseyhightower/envconfig"
@@ -261,23 +261,10 @@ func Main(opts ...Option) error {
261261
httpServers["profile"] = pprof.Server
262262
}
263263

264-
tlsServers := make(map[string]*http.Server)
264+
var tlsServer *http.Server
265265
var certWatcher *certificate.CertWatcher
266266
var err error
267267

268-
if tlsEnabled {
269-
tlsServers["main"] = mainServer(":"+env.QueueServingTLSPort, mainHandler)
270-
// Keep admin server on HTTP even with TLS enabled since it's only accessed locally by kubelet
271-
272-
certWatcher, err = certificate.NewCertWatcher(certPath, keyPath, 1*time.Minute, logger)
273-
if err != nil {
274-
logger.Fatal("failed to create certWatcher", zap.Error(err))
275-
}
276-
defer certWatcher.Stop()
277-
}
278-
279-
logger.Info("Starting queue-proxy")
280-
281268
errCh := make(chan error)
282269
for name, server := range httpServers {
283270
go func(name string, s *http.Server) {
@@ -288,20 +275,34 @@ func Main(opts ...Option) error {
288275
}
289276
}(name, server)
290277
}
291-
for name, server := range tlsServers {
292-
go func(name string, s *http.Server) {
293-
logger.Info("Starting tls server ", name, s.Addr)
294-
s.TLSConfig = &tls.Config{
295-
GetCertificate: certWatcher.GetCertificate,
296-
MinVersion: tls.VersionTLS13,
297-
}
278+
279+
if tlsEnabled {
280+
tlsServer = mainServer(":"+env.QueueServingTLSPort, mainHandler)
281+
// Keep admin server on HTTP even with TLS enabled since it's only accessed locally by kubelet
282+
283+
certWatcher, err = certificate.NewCertWatcher(certPath, keyPath, 1*time.Minute, logger)
284+
if err != nil {
285+
logger.Fatal("failed to create certWatcher", zap.Error(err))
286+
}
287+
defer certWatcher.Stop()
288+
289+
tlsCfg, err := knativetls.DefaultConfigFromEnv("QUEUE_PROXY_")
290+
if err != nil {
291+
logger.Fatalw("Failed to read TLS configuration from environment", zap.Error(err))
292+
}
293+
go func() {
294+
logger.Info("Starting tls server main ", tlsServer.Addr)
295+
tlsServer.TLSConfig = tlsCfg
296+
tlsServer.TLSConfig.GetCertificate = certWatcher.GetCertificate
298297
// Don't forward ErrServerClosed as that indicates we're already shutting down.
299-
if err := s.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
300-
errCh <- fmt.Errorf("%s server failed to serve: %w", name, err)
298+
if err := tlsServer.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
299+
errCh <- fmt.Errorf("main tls server failed to serve: %w", err)
301300
}
302-
}(name, server)
301+
}()
303302
}
304303

304+
logger.Info("Starting queue-proxy")
305+
305306
// Blocks until we actually receive a TERM signal or one of the servers
306307
// exits unexpectedly. We fold both signals together because we only want
307308
// to act on the first of those to reach here.
@@ -320,10 +321,10 @@ func Main(opts ...Option) error {
320321
logger.Errorw("Failed to shutdown server", zap.String("server", name), zap.Error(err))
321322
}
322323
}
323-
for name, srv := range tlsServers {
324-
logger.Info("Shutting down server: ", name)
325-
if err := srv.Shutdown(context.Background()); err != nil {
326-
logger.Errorw("Failed to shutdown server", zap.String("server", name), zap.Error(err))
324+
if tlsServer != nil {
325+
logger.Info("Shutting down server: main tls")
326+
if err := tlsServer.Shutdown(context.Background()); err != nil {
327+
logger.Errorw("Failed to shutdown server", zap.String("server", "main tls"), zap.Error(err))
327328
}
328329
}
329330

pkg/reconciler/revision/resolve.go

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package revision
1818

1919
import (
2020
"context"
21-
"crypto/tls"
2221
"crypto/x509"
2322
"errors"
2423
"fmt"
@@ -30,6 +29,7 @@ import (
3029
"github.com/google/go-containerregistry/pkg/v1/remote"
3130
"k8s.io/apimachinery/pkg/util/sets"
3231
"k8s.io/client-go/kubernetes"
32+
knativetls "knative.dev/pkg/network/tls"
3333
)
3434

3535
type digestResolver struct {
@@ -43,7 +43,7 @@ const (
4343
// https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/#trusting-tls-in-a-cluster
4444
k8sCertPath = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
4545

46-
tlsMinVersionEnvKey = "TAG_TO_DIGEST_TLS_MIN_VERSION"
46+
tlsEnvPrefix = "TAG_TO_DIGEST_"
4747
)
4848

4949
// newResolverTransport returns an http.Transport that appends the certs bundle
@@ -62,31 +62,20 @@ func newResolverTransport(path string, maxIdleConns, maxIdleConnsPerHost int) (*
6262
return nil, errors.New("failed to append k8s cert bundle to cert pool")
6363
}
6464

65+
cfg, err := knativetls.DefaultConfigFromEnv(tlsEnvPrefix)
66+
if err != nil {
67+
return nil, err
68+
}
69+
6570
transport := http.DefaultTransport.(*http.Transport).Clone()
6671
transport.MaxIdleConns = maxIdleConns
6772
transport.MaxIdleConnsPerHost = maxIdleConnsPerHost
68-
//nolint:gosec // quay.io still required 1.2 - bump if they've moved up
69-
transport.TLSClientConfig = &tls.Config{
70-
MinVersion: tlsMinVersionFromEnv(tls.VersionTLS12),
71-
RootCAs: pool,
72-
}
73+
transport.TLSClientConfig = cfg
74+
transport.TLSClientConfig.RootCAs = pool
7375

7476
return transport, nil
7577
}
7678

77-
func tlsMinVersionFromEnv(defaultTLSMinVersion uint16) uint16 {
78-
switch tlsMinVersion := os.Getenv(tlsMinVersionEnvKey); tlsMinVersion {
79-
case "1.2":
80-
return tls.VersionTLS12
81-
case "1.3":
82-
return tls.VersionTLS13
83-
case "":
84-
return defaultTLSMinVersion
85-
default:
86-
panic(fmt.Sprintf("the environment variable %q has to be either '1.2' or '1.3'", tlsMinVersionEnvKey))
87-
}
88-
}
89-
9079
// Resolve resolves the image references that use tags to digests.
9180
func (r *digestResolver) Resolve(
9281
ctx context.Context,

0 commit comments

Comments
 (0)