From c0ae49185df0df89c8400385c91817aceac75b6f Mon Sep 17 00:00:00 2001 From: Vincent Link Date: Mon, 20 Oct 2025 16:35:11 +0200 Subject: [PATCH 1/2] tmp: use local networking repo --- go.mod | 2 + .../networking/config/config-network.yaml | 15 ++++++- .../networking/pkg/config/config.go | 44 +++++++++++++------ vendor/modules.txt | 3 +- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index e57c441f10ca..fb1340e27311 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module knative.dev/serving go 1.24.0 +replace knative.dev/networking => ../networking + require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20210609063737-0067dc6dcea2 github.com/cert-manager/cert-manager v1.16.3 diff --git a/vendor/knative.dev/networking/config/config-network.yaml b/vendor/knative.dev/networking/config/config-network.yaml index 7d5c93945d44..c6ecbeea75ba 100644 --- a/vendor/knative.dev/networking/config/config-network.yaml +++ b/vendor/knative.dev/networking/config/config-network.yaml @@ -22,7 +22,7 @@ metadata: app.kubernetes.io/component: networking app.kubernetes.io/version: devel annotations: - knative.dev/example-checksum: "0573e07d" + knative.dev/example-checksum: "e93fd63e" data: _example: | ################################ @@ -149,6 +149,19 @@ data: # for now. Use with caution. system-internal-tls: "Disabled" + # system-internal-tls-allow-serve-mode controls whether Serve mode is allowed + # when system-internal-tls is enabled. By default, enabling system-internal-tls + # forces all traffic to use Proxy mode because not all Knative ingress implementations + # support Serve mode with TLS enabled. Set this to "Enabled" only if your ingress + # implementation supports direct TLS connections to application containers in Serve mode. + # + # Possible values for this flag are: + # - Disabled (default): system-internal-tls forces Proxy mode for compatibility. + # - Enabled: Serve mode is allowed even with TLS enabled (requires ingress support). + # NOTE: This flag is in an alpha state and is mostly here to enable internal testing + # for now. Use with caution. + system-internal-tls-allow-serve-mode: "Disabled" + # Controls the behavior of the HTTP endpoint for the Knative ingress. # It requires auto-tls to be enabled. # - Enabled: The Knative ingress will be able to serve HTTP connection. diff --git a/vendor/knative.dev/networking/pkg/config/config.go b/vendor/knative.dev/networking/pkg/config/config.go index b9fca8585c24..2827fb3c3a37 100644 --- a/vendor/knative.dev/networking/pkg/config/config.go +++ b/vendor/knative.dev/networking/pkg/config/config.go @@ -140,6 +140,12 @@ const ( // SystemInternalTLSKey is the name of the configuration whether // traffic between Knative system components is encrypted or not. SystemInternalTLSKey = "system-internal-tls" + + // SystemInternalTLSAllowServeModeKey is the name of the configuration that + // specifies whether Serve mode is allowed when system-internal-tls is enabled. + // When false (default), system-internal-tls forces Proxy mode. + // When true, Serve mode is allowed even with TLS enabled. + SystemInternalTLSAllowServeModeKey = "system-internal-tls-allow-serve-mode" ) // CertificateType indicates the type of Knative Certificate. @@ -303,26 +309,32 @@ type Config struct { // SystemInternalTLS specifies whether knative internal traffic is encrypted or not. SystemInternalTLS EncryptionConfig + // SystemInternalTLSAllowServeMode specifies whether Serve mode is allowed + // when SystemInternalTLS is enabled. When false (default), enabling TLS + // forces Proxy mode. When true, Serve mode is permitted even with TLS enabled. + SystemInternalTLSAllowServeMode bool + // ClusterLocalDomainTLS specifies whether cluster-local traffic is encrypted or not. ClusterLocalDomainTLS EncryptionConfig } func defaultConfig() *Config { return &Config{ - DefaultIngressClass: IstioIngressClassName, - DefaultCertificateClass: CertManagerCertificateClassName, - DomainTemplate: DefaultDomainTemplate, - TagTemplate: DefaultTagTemplate, - AutoTLS: false, - ExternalDomainTLS: false, - NamespaceWildcardCertSelector: nil, - HTTPProtocol: HTTPEnabled, - AutocreateClusterDomainClaims: false, - DefaultExternalScheme: "http", - MeshCompatibilityMode: MeshCompatibilityModeAuto, - InternalEncryption: false, - SystemInternalTLS: EncryptionDisabled, - ClusterLocalDomainTLS: EncryptionDisabled, + DefaultIngressClass: IstioIngressClassName, + DefaultCertificateClass: CertManagerCertificateClassName, + DomainTemplate: DefaultDomainTemplate, + TagTemplate: DefaultTagTemplate, + AutoTLS: false, + ExternalDomainTLS: false, + NamespaceWildcardCertSelector: nil, + HTTPProtocol: HTTPEnabled, + AutocreateClusterDomainClaims: false, + DefaultExternalScheme: "http", + MeshCompatibilityMode: MeshCompatibilityModeAuto, + InternalEncryption: false, + SystemInternalTLS: EncryptionDisabled, + SystemInternalTLSAllowServeMode: false, + ClusterLocalDomainTLS: EncryptionDisabled, } } @@ -455,6 +467,10 @@ func NewConfigFromMap(data map[string]string) (*Config, error) { ClusterLocalDomainTLSKey, data[ClusterLocalDomainTLSKey]) } + if val, ok := data[SystemInternalTLSAllowServeModeKey]; ok { + nc.SystemInternalTLSAllowServeMode = strings.EqualFold(val, "enabled") + } + return nc, nil } diff --git a/vendor/modules.txt b/vendor/modules.txt index a9c18790a800..22ce693e050a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1475,7 +1475,7 @@ knative.dev/caching/pkg/client/listers/caching/v1alpha1 # knative.dev/hack v0.0.0-20251021013703-4fae78067103 ## explicit; go 1.24 knative.dev/hack -# knative.dev/networking v0.0.0-20251021092443-0bde19154dce +# knative.dev/networking v0.0.0-20251021092443-0bde19154dce => ../networking ## explicit; go 1.24.0 knative.dev/networking/config knative.dev/networking/pkg @@ -1662,3 +1662,4 @@ sigs.k8s.io/structured-merge-diff/v4/value ## explicit; go 1.22 sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 +# knative.dev/networking => ../networking From 3099645b33f57c81a3abd36c683b499de97b176b Mon Sep 17 00:00:00 2001 From: Vincent Link Date: Tue, 21 Oct 2025 14:29:36 +0200 Subject: [PATCH 2/2] Allow serve mode with system-internal-tls When system-internal-tls is enabled, the KPA reconciler now checks the SystemInternalTLSAllowServeMode flag to determine whether to use serve mode or force proxy mode. This allows configurations where internal TLS is enabled but serve mode is still desired. --- pkg/reconciler/autoscaling/kpa/kpa.go | 5 +- pkg/reconciler/autoscaling/kpa/kpa_test.go | 42 +++++++ .../system_internal_tls_test.go | 108 ++++++++++++++++++ 3 files changed, 153 insertions(+), 2 deletions(-) diff --git a/pkg/reconciler/autoscaling/kpa/kpa.go b/pkg/reconciler/autoscaling/kpa/kpa.go index 6a54b8e18855..a18fd2ff08cc 100644 --- a/pkg/reconciler/autoscaling/kpa/kpa.go +++ b/pkg/reconciler/autoscaling/kpa/kpa.go @@ -124,12 +124,13 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, pa *autoscalingv1alpha1. } mode := nv1alpha1.SKSOperationModeProxy + netCfg := config.FromContext(ctx).Network switch { - // When activator CA is enabled, force activator always in path. + // When activator CA is enabled, force activator always in path unless explicitly allowed. // TODO: This is a temporary state and to be fixed. // See also issues/11906 and issues/12797. - case config.FromContext(ctx).Network.SystemInternalTLSEnabled(): + case netCfg.SystemInternalTLSEnabled() && !netCfg.SystemInternalTLSAllowServeMode: mode = nv1alpha1.SKSOperationModeProxy // If the want == -1 and PA is inactive that implies the autoscaler diff --git a/pkg/reconciler/autoscaling/kpa/kpa_test.go b/pkg/reconciler/autoscaling/kpa/kpa_test.go index bb9187d9d39e..d2e196976adc 100644 --- a/pkg/reconciler/autoscaling/kpa/kpa_test.go +++ b/pkg/reconciler/autoscaling/kpa/kpa_test.go @@ -135,6 +135,14 @@ func activatorCertsNetConfig() *netcfg.Config { return nc } +func activatorCertsWithServeModeNetConfig() *netcfg.Config { + nc, _ := netcfg.NewConfigFromMap(map[string]string{ + netcfg.SystemInternalTLSKey: "enabled", + netcfg.SystemInternalTLSAllowServeModeKey: "enabled", + }) + return nc +} + func defaultConfig() *config.Config { ac, _ := asconfig.NewConfigFromMap(defaultConfigMapData()) deploymentConfig, _ := deployment.NewConfigFromMap(map[string]string{ @@ -1192,6 +1200,40 @@ func TestReconcile(t *testing.T) { WantUpdates: []clientgotesting.UpdateActionImpl{{ Object: defaultProxySKS, }}, + }, { + Name: "TLS enabled with allows-serve-mode true, switch to Serve mode", + Key: key, + Ctx: context.WithValue(context.WithValue(context.Background(), netConfigKey{}, activatorCertsWithServeModeNetConfig()), deciderKey{}, + decider(testNamespace, testRevision, defaultScale, /* desiredScale */ + 1 /* ebc */)), + Objects: []runtime.Object{ + kpa(testNamespace, testRevision, WithPASKSReady, WithTraffic, markScaleTargetInitialized, + WithPAMetricsService(privateSvc), withScales(1, defaultScale), + WithPAStatusService(testRevision), WithObservedGeneration(1)), + defaultProxySKS, + metric(testNamespace, testRevision), + defaultDeployment, + defaultReady, + }, + WantUpdates: []clientgotesting.UpdateActionImpl{{ + Object: defaultSKS, + }}, + }, { + Name: "TLS enabled with allows-serve-mode true, already in Serve mode", + Key: key, + Ctx: context.WithValue(context.WithValue(context.Background(), netConfigKey{}, activatorCertsWithServeModeNetConfig()), deciderKey{}, + decider(testNamespace, testRevision, defaultScale, /* desiredScale */ + 1 /* ebc */)), + Objects: []runtime.Object{ + kpa(testNamespace, testRevision, WithPASKSReady, WithTraffic, markScaleTargetInitialized, + WithPAMetricsService(privateSvc), withScales(1, defaultScale), + WithPAStatusService(testRevision), WithObservedGeneration(1)), + defaultSKS, + metric(testNamespace, testRevision), + defaultDeployment, + defaultReady, + }, + // No update - already in Serve mode }} table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler { diff --git a/test/e2e/systeminternaltls/system_internal_tls_test.go b/test/e2e/systeminternaltls/system_internal_tls_test.go index c19b539da2a8..dcf32d6934aa 100644 --- a/test/e2e/systeminternaltls/system_internal_tls_test.go +++ b/test/e2e/systeminternaltls/system_internal_tls_test.go @@ -32,7 +32,9 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" "knative.dev/networking/pkg/apis/networking" + nv1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1" "knative.dev/networking/pkg/certificates" "knative.dev/networking/pkg/config" "knative.dev/pkg/system" @@ -373,3 +375,109 @@ func TestGracefulShutdownWithTLS(t *testing.T) { t.Log("All requests completed successfully - PreStop hook worked correctly with TLS enabled") } + +// TestSystemInternalTLSWithServeMode tests that when system-internal-tls-allow-serve-mode is enabled, +// the SKS transitions to Serve mode and traffic works correctly with TLS. +func TestSystemInternalTLSWithServeMode(t *testing.T) { + if !test.ServingFlags.EnableAlphaFeatures { + t.Skip("Alpha features not enabled") + } + + if !strings.Contains(test.ServingFlags.IngressClass, "kourier") { + t.Skip("Skip this test for non-kourier ingress as we only need to check one ingress with TLS support.") + } + + clients := test.Setup(t) + + // Enable system-internal-tls-allow-serve-mode + t.Log("Enabling system-internal-tls-allow-serve-mode") + systemNS := os.Getenv(system.NamespaceEnvKey) + cm, err := clients.KubeClient.CoreV1().ConfigMaps(systemNS).Get( + context.Background(), "config-network", v1.GetOptions{}) + if err != nil { + t.Fatalf("Failed to get config-network ConfigMap: %v", err) + } + + originalData := cm.Data["system-internal-tls-allow-serve-mode"] + if cm.Data == nil { + cm.Data = make(map[string]string) + } + cm.Data["system-internal-tls-allow-serve-mode"] = "enabled" + _, err = clients.KubeClient.CoreV1().ConfigMaps(systemNS).Update( + context.Background(), cm, v1.UpdateOptions{}) + if err != nil { + t.Fatalf("Failed to update config-network ConfigMap: %v", err) + } + + // Restore original config on cleanup + test.EnsureCleanup(t, func() { + cm, err := clients.KubeClient.CoreV1().ConfigMaps(systemNS).Get( + context.Background(), "config-network", v1.GetOptions{}) + if err != nil { + t.Logf("Warning: Failed to get config-network ConfigMap during cleanup: %v", err) + return + } + if originalData == "" { + delete(cm.Data, "system-internal-tls-allow-serve-mode") + } else { + cm.Data["system-internal-tls-allow-serve-mode"] = originalData + } + if _, err := clients.KubeClient.CoreV1().ConfigMaps(systemNS).Update( + context.Background(), cm, v1.UpdateOptions{}); err != nil { + t.Logf("Warning: Failed to restore config-network ConfigMap: %v", err) + } + }) + + names := test.ResourceNames{ + Service: test.ObjectNameForTest(t), + Image: test.HelloWorld, + } + + test.EnsureTearDown(t, clients, &names) + + t.Log("Creating a new Service with min-scale=1 and target-burst-capacity=0") + resources, err := v1test.CreateServiceReady(t, clients, &names, + rtesting.WithConfigAnnotations(map[string]string{ + // These annotations ensure the service will be in Serve mode: + // - min-scale=1 ensures want > 0 + // - target-burst-capacity=0 ensures excess burst capacity >= 0 + autoscaling.MinScaleAnnotationKey: "1", + autoscaling.TargetBurstCapacityKey: "0", + })) + if err != nil { + t.Fatalf("Failed to create initial Service: %v: %v", names.Service, err) + } + + // Wait for SKS to be in Serve mode + t.Log("Waiting for SKS to transition to Serve mode") + var sksMode nv1alpha1.ServerlessServiceOperationMode + if err := wait.PollUntilContextTimeout(context.Background(), time.Second, time.Minute, true, func(context.Context) (bool, error) { + sks, err := clients.NetworkingClient.ServerlessServices.Get( + context.Background(), resources.Revision.Name, v1.GetOptions{}) + if err != nil { + return false, nil //nolint:nilerr + } + sksMode = sks.Spec.Mode + t.Logf("Current SKS mode: %s", sksMode) + return sksMode == nv1alpha1.SKSOperationModeServe, nil + }); err != nil { + t.Fatalf("SKS did not transition to Serve mode (current mode: %s): %v", sksMode, err) + } + + t.Log("SKS is in Serve mode, verifying service works correctly") + url := resources.Route.Status.URL.URL() + if _, err := pkgTest.CheckEndpointState( + context.Background(), + clients.KubeClient, + t.Logf, + url, + spoof.MatchesAllOf(spoof.IsStatusOK, spoof.MatchesBody(test.HelloWorldText)), + "HelloWorldText", + test.ServingFlags.ResolvableDomain, + test.AddRootCAtoTransport(context.Background(), t.Logf, clients, test.ServingFlags.HTTPS), + ); err != nil { + t.Fatalf("The endpoint %s didn't serve the expected text %q: %v", url, test.HelloWorldText, err) + } + + t.Log("Service works correctly in Serve mode with system-internal-tls enabled") +}