Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions cmd/activator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package main

import (
"context"
"crypto/tls"
"errors"
"fmt"
"log"
Expand Down Expand Up @@ -47,6 +46,7 @@ import (
pkglogging "knative.dev/pkg/logging"
"knative.dev/pkg/logging/logkey"
pkgnet "knative.dev/pkg/network"
knativetls "knative.dev/pkg/network/tls"
k8sruntime "knative.dev/pkg/observability/runtime/k8s"
"knative.dev/pkg/signals"
"knative.dev/pkg/system"
Expand Down Expand Up @@ -292,7 +292,7 @@ func main() {
"profile": pprof.Server,
}

errCh := make(chan error, len(servers))
errCh := make(chan error, len(servers)+1)
for name, server := range servers {
go func(name string, s *http.Server) {
// Don't forward ErrServerClosed as that indicates we're already shutting down.
Expand All @@ -306,17 +306,21 @@ func main() {
// At this moment activator with TLS does not disable HTTP.
// See also https://github.com/knative/serving/issues/12808.
if tlsEnabled {
name, server := "https", pkgnet.NewServer(":"+strconv.Itoa(networking.BackendHTTPSPort), ah)
go func(name string, s *http.Server) {
s.TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS13,
GetCertificate: certCache.GetCertificate,
}
tlsCfg, err := knativetls.DefaultConfigFromEnv("ACTIVATOR_")
if err != nil {
logger.Fatalw("Failed to read TLS configuration from environment", zap.Error(err))
}

server := pkgnet.NewServer(":"+strconv.Itoa(networking.BackendHTTPSPort), ah)
servers["https"] = server
go func(s *http.Server) {
s.TLSConfig = tlsCfg
s.TLSConfig.GetCertificate = certCache.GetCertificate
// Don't forward ErrServerClosed as that indicates we're already shutting down.
if err := s.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
errCh <- fmt.Errorf("%s server failed: %w", name, err)
errCh <- fmt.Errorf("https server failed: %w", err)
}
}(name, server)
}(server)
}

// Wait for the signal to drain.
Expand Down
21 changes: 20 additions & 1 deletion config/core/configmaps/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ metadata:
app.kubernetes.io/component: controller
app.kubernetes.io/version: devel
annotations:
knative.dev/example-checksum: "b99000ec"
knative.dev/example-checksum: "555b4826"
data:
# This is the Go import path for the binary that is containerized
# and substituted here.
Expand Down Expand Up @@ -92,6 +92,25 @@ data:
# If omitted, or empty, no rootCA is added to the golang rootCAs
queue-sidecar-rootca: ""

# Sets the minimum TLS version for the queue proxy sidecar's TLS server.
# Accepted values: "1.2", "1.3". Default is "1.3" if not specified.
queue-sidecar-tls-min-version: ""

# Sets the maximum TLS version for the queue proxy sidecar's TLS server.
# Accepted values: "1.2", "1.3". If omitted, the Go default is used.
queue-sidecar-tls-max-version: ""

# Sets the cipher suites for the queue proxy sidecar's TLS server.
# Comma-separated list of cipher suite names (e.g. "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256").
# If omitted, the Go default cipher suites are used.
# Note: cipher suites are not configurable in TLS 1.3.
queue-sidecar-tls-cipher-suites: ""

# Sets the elliptic curve preferences for the queue proxy sidecar's TLS server.
# Comma-separated list of curve names (e.g. "X25519,CurveP256").
# If omitted, the Go default curves are used.
queue-sidecar-tls-curve-preferences: ""

# If set, it automatically configures pod anti-affinity requirements for all Knative services.
# It employs the `preferredDuringSchedulingIgnoredDuringExecution` weighted pod affinity term,
# aligning with the Knative revision label. It yields the configuration below in all workloads' deployments:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ require (
knative.dev/caching v0.0.0-20260120130310-f1fc03b7f5ee
knative.dev/hack v0.0.0-20260120115810-bf6758cba446
knative.dev/networking v0.0.0-20260120131110-a7cdca238a0d
knative.dev/pkg v0.0.0-20260120122510-4a022ed9999a
knative.dev/pkg v0.0.0-20260319144603-18c5d580ae64
sigs.k8s.io/randfill v1.0.0
sigs.k8s.io/yaml v1.6.0
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,8 @@ knative.dev/hack v0.0.0-20260120115810-bf6758cba446 h1:Y8raYHIuAL9/gUKGYD9/dD+Eq
knative.dev/hack v0.0.0-20260120115810-bf6758cba446/go.mod h1:L5RzHgbvam0u8QFHfzCX6MKxu/a/gIGEdaRBqNiVbl0=
knative.dev/networking v0.0.0-20260120131110-a7cdca238a0d h1:QQ5QeH5MZlYdu6gRGGjmEBQ/CVoatiXKnVIrUoKlj4U=
knative.dev/networking v0.0.0-20260120131110-a7cdca238a0d/go.mod h1:mZD2edO8op3zI6yLOn1yoz8xqbyZfrrDOJCbYElMEKs=
knative.dev/pkg v0.0.0-20260120122510-4a022ed9999a h1:9f29OTA7w/iVIX6PS6yveVVzNbcUS74eQfchVe8o2/4=
knative.dev/pkg v0.0.0-20260120122510-4a022ed9999a/go.mod h1:Tz3GoxcNC5vH3Zo//cW3mnHL474u+Y1wbsUIZ11p8No=
knative.dev/pkg v0.0.0-20260319144603-18c5d580ae64 h1:TiwrcgUKNePfdAbaJT9W4P57lsKjiZnjJ0wVC6XrL0U=
knative.dev/pkg v0.0.0-20260319144603-18c5d580ae64/go.mod h1:Tz3GoxcNC5vH3Zo//cW3mnHL474u+Y1wbsUIZ11p8No=
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM=
Expand Down
23 changes: 23 additions & 0 deletions pkg/deployment/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ const (
queueSidecarTokenAudiencesKey = "queue-sidecar-token-audiences"
queueSidecarRooCAKey = "queue-sidecar-rootca"

// queueSidecar TLS configuration keys.
queueSidecarTLSMinVersionKey = "queue-sidecar-tls-min-version"
queueSidecarTLSMaxVersionKey = "queue-sidecar-tls-max-version"
queueSidecarTLSCipherSuitesKey = "queue-sidecar-tls-cipher-suites"
queueSidecarTLSCurvePreferencesKey = "queue-sidecar-tls-curve-preferences"

defaultAffinityTypeKey = "default-affinity-type"
defaultAffinityTypeValue = PreferSpreadRevisionOverNodes

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

cm.AsString(queueSidecarTLSMinVersionKey, &nc.QueueSidecarTLSMinVersion),
cm.AsString(queueSidecarTLSMaxVersionKey, &nc.QueueSidecarTLSMaxVersion),
cm.AsString(queueSidecarTLSCipherSuitesKey, &nc.QueueSidecarTLSCipherSuites),
cm.AsString(queueSidecarTLSCurvePreferencesKey, &nc.QueueSidecarTLSCurvePreferences),

cm.AsString(RuntimeClassNameKey, &runtimeClassNames),

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

// QueueSidecarTLSMinVersion is the minimum TLS version for the queue proxy sidecar (e.g. "1.2", "1.3").
QueueSidecarTLSMinVersion string

// QueueSidecarTLSMaxVersion is the maximum TLS version for the queue proxy sidecar (e.g. "1.2", "1.3").
QueueSidecarTLSMaxVersion string

// QueueSidecarTLSCipherSuites is a comma-separated list of cipher suites for the queue proxy sidecar.
QueueSidecarTLSCipherSuites string

// QueueSidecarTLSCurvePreferences is a comma-separated list of elliptic curves for the queue proxy sidecar.
QueueSidecarTLSCurvePreferences string

// DefaultAffinityType is a string that controls what affinity rules will be automatically
// applied to the PodSpec of all Knative services.
DefaultAffinityType AffinityType
Expand Down
22 changes: 22 additions & 0 deletions pkg/deployment/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,28 @@ kata:
podIsAlwaysSchedulableKey: "true",
QueueSidecarImageKey: defaultSidecarImage,
},
}, {
name: "controller configuration with queue sidecar TLS settings",
wantConfig: &Config{
RegistriesSkippingTagResolving: sets.New("kind.local", "ko.local", "dev.local"),
DigestResolutionTimeout: digestResolutionTimeoutDefault,
QueueSidecarImage: defaultSidecarImage,
QueueSidecarCPURequest: &QueueSidecarCPURequestDefault,
QueueSidecarTokenAudiences: sets.New(""),
ProgressDeadline: ProgressDeadlineDefault,
DefaultAffinityType: defaultAffinityTypeValue,
QueueSidecarTLSMinVersion: "1.2",
QueueSidecarTLSMaxVersion: "1.3",
QueueSidecarTLSCipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
QueueSidecarTLSCurvePreferences: "X25519,CurveP256",
},
data: map[string]string{
QueueSidecarImageKey: defaultSidecarImage,
queueSidecarTLSMinVersionKey: "1.2",
queueSidecarTLSMaxVersionKey: "1.3",
queueSidecarTLSCipherSuitesKey: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
queueSidecarTLSCurvePreferencesKey: "X25519,CurveP256",
},
}}

for _, tt := range configTests {
Expand Down
59 changes: 30 additions & 29 deletions pkg/queue/sharedmain/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package sharedmain

import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
Expand All @@ -31,6 +30,7 @@ import (

netproxy "knative.dev/networking/pkg/http/proxy"
pkghandler "knative.dev/pkg/network/handlers"
knativetls "knative.dev/pkg/network/tls"
"knative.dev/serving/pkg/activator"

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

tlsServers := make(map[string]*http.Server)
var tlsServer *http.Server
var certWatcher *certificate.CertWatcher
var err error

if tlsEnabled {
tlsServers["main"] = mainServer(":"+env.QueueServingTLSPort, mainHandler)
// Keep admin server on HTTP even with TLS enabled since it's only accessed locally by kubelet

certWatcher, err = certificate.NewCertWatcher(certPath, keyPath, 1*time.Minute, logger)
if err != nil {
logger.Fatal("failed to create certWatcher", zap.Error(err))
}
defer certWatcher.Stop()
}

logger.Info("Starting queue-proxy")

errCh := make(chan error)
for name, server := range httpServers {
go func(name string, s *http.Server) {
Expand All @@ -288,20 +275,34 @@ func Main(opts ...Option) error {
}
}(name, server)
}
for name, server := range tlsServers {
go func(name string, s *http.Server) {
logger.Info("Starting tls server ", name, s.Addr)
s.TLSConfig = &tls.Config{
GetCertificate: certWatcher.GetCertificate,
MinVersion: tls.VersionTLS13,
}

if tlsEnabled {
tlsServer = mainServer(":"+env.QueueServingTLSPort, mainHandler)
// Keep admin server on HTTP even with TLS enabled since it's only accessed locally by kubelet

certWatcher, err = certificate.NewCertWatcher(certPath, keyPath, 1*time.Minute, logger)
if err != nil {
logger.Fatal("failed to create certWatcher", zap.Error(err))
}
defer certWatcher.Stop()

tlsCfg, err := knativetls.DefaultConfigFromEnv("QUEUE_PROXY_")
if err != nil {
logger.Fatalw("Failed to read TLS configuration from environment", zap.Error(err))
}
go func() {
logger.Info("Starting tls server main ", tlsServer.Addr)
tlsServer.TLSConfig = tlsCfg
tlsServer.TLSConfig.GetCertificate = certWatcher.GetCertificate
// Don't forward ErrServerClosed as that indicates we're already shutting down.
if err := s.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
errCh <- fmt.Errorf("%s server failed to serve: %w", name, err)
if err := tlsServer.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
errCh <- fmt.Errorf("main tls server failed to serve: %w", err)
}
}(name, server)
}()
}

logger.Info("Starting queue-proxy")

// Blocks until we actually receive a TERM signal or one of the servers
// exits unexpectedly. We fold both signals together because we only want
// to act on the first of those to reach here.
Expand All @@ -320,10 +321,10 @@ func Main(opts ...Option) error {
logger.Errorw("Failed to shutdown server", zap.String("server", name), zap.Error(err))
}
}
for name, srv := range tlsServers {
logger.Info("Shutting down server: ", name)
if err := srv.Shutdown(context.Background()); err != nil {
logger.Errorw("Failed to shutdown server", zap.String("server", name), zap.Error(err))
if tlsServer != nil {
logger.Info("Shutting down server: main tls")
if err := tlsServer.Shutdown(context.Background()); err != nil {
logger.Errorw("Failed to shutdown server", zap.String("server", "main tls"), zap.Error(err))
}
}

Expand Down
29 changes: 9 additions & 20 deletions pkg/reconciler/revision/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package revision

import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
Expand All @@ -30,6 +29,7 @@ import (
"github.com/google/go-containerregistry/pkg/v1/remote"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/kubernetes"
knativetls "knative.dev/pkg/network/tls"
)

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

tlsMinVersionEnvKey = "TAG_TO_DIGEST_TLS_MIN_VERSION"
tlsEnvPrefix = "TAG_TO_DIGEST_"
)

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

cfg, err := knativetls.DefaultConfigFromEnv(tlsEnvPrefix)
if err != nil {
return nil, err
}

transport := http.DefaultTransport.(*http.Transport).Clone()
transport.MaxIdleConns = maxIdleConns
transport.MaxIdleConnsPerHost = maxIdleConnsPerHost
//nolint:gosec // quay.io still required 1.2 - bump if they've moved up
transport.TLSClientConfig = &tls.Config{
MinVersion: tlsMinVersionFromEnv(tls.VersionTLS12),
RootCAs: pool,
}
transport.TLSClientConfig = cfg
transport.TLSClientConfig.RootCAs = pool

return transport, nil
}

func tlsMinVersionFromEnv(defaultTLSMinVersion uint16) uint16 {
switch tlsMinVersion := os.Getenv(tlsMinVersionEnvKey); tlsMinVersion {
case "1.2":
return tls.VersionTLS12
case "1.3":
return tls.VersionTLS13
case "":
return defaultTLSMinVersion
default:
panic(fmt.Sprintf("the environment variable %q has to be either '1.2' or '1.3'", tlsMinVersionEnvKey))
}
}

// Resolve resolves the image references that use tags to digests.
func (r *digestResolver) Resolve(
ctx context.Context,
Expand Down
Loading
Loading