Skip to content
Open
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
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions pkg/reconciler/autoscaling/kpa/kpa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 42 additions & 0 deletions pkg/reconciler/autoscaling/kpa/kpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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 {
Expand Down
108 changes: 108 additions & 0 deletions test/e2e/systeminternaltls/system_internal_tls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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")
}
15 changes: 14 additions & 1 deletion vendor/knative.dev/networking/config/config-network.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
################################
Expand Down Expand Up @@ -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.
Expand Down
44 changes: 30 additions & 14 deletions vendor/knative.dev/networking/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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
}

Expand Down
3 changes: 2 additions & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Loading