diff --git a/api/v1/ytsaurus_types.go b/api/v1/ytsaurus_types.go index 451c5ed5b..f89754003 100644 --- a/api/v1/ytsaurus_types.go +++ b/api/v1/ytsaurus_types.go @@ -808,6 +808,8 @@ type ClusterFeatures struct { HTTPProxyHaveChytAddress bool `json:"httpProxyHaveChytAddress,omitempty"` // HTTP proxies have "https" address. Use HTTPS for all communications. HTTPProxyHaveHTTPSAddress bool `json:"httpProxyHaveHttpsAddress,omitempty"` + // Validate that only secure transports are allowed for cluster connections. + SecureClusterTransports bool `json:"secureClusterTransports,omitempty"` } // CommonSpec is a set of fields shared between `YtsaurusSpec` and `Remote*NodesSpec`. diff --git a/api/v1/ytsaurus_webhook.go b/api/v1/ytsaurus_webhook.go index 55fa9122d..f05b12eea 100644 --- a/api/v1/ytsaurus_webhook.go +++ b/api/v1/ytsaurus_webhook.go @@ -68,10 +68,53 @@ func (r *Ytsaurus) SetupWebhookWithManager(mgr ctrl.Manager) error { ////////////////////////////////////////////////// +func (r *baseValidator) validateTransportSecurity(spec *RPCTransportSpec, commonSpec *CommonSpec, path *field.Path) field.ErrorList { + var allErrors field.ErrorList + + features := ptr.Deref(commonSpec.ClusterFeatures, ClusterFeatures{}) + + if spec == nil { + spec = commonSpec.NativeTransport + } + + if spec == nil { + if features.SecureClusterTransports { + allErrors = append(allErrors, field.Required(path, "Secure cluster transport demands TLS setup")) + } + return allErrors + } + + secretPath := path.Child("tlsSecret") + clientSecretPath := path.Child("tlsClientSecret") + if spec.TLSSecret == nil && (spec.TLSRequired || !spec.TLSInsecure) { + allErrors = append(allErrors, field.Required(secretPath, "TLS certificate for native transport is required")) + } + if spec.TLSClientSecret == nil && (spec.TLSRequired && !spec.TLSInsecure) { + allErrors = append(allErrors, field.Required(clientSecretPath, "Client TLS certificate for native transport is required")) + } + + if features.SecureClusterTransports { + if !spec.TLSRequired { + allErrors = append(allErrors, field.Forbidden(path.Child("tlsRequired"), "Secure cluster transport demands TLS-only native transport")) + } + if spec.TLSInsecure { + allErrors = append(allErrors, field.Forbidden(path.Child("tlsInsecure"), "Secure cluster transport demands TLS certificate validation")) + } + if spec.TLSSecret == nil { + allErrors = append(allErrors, field.Required(secretPath, "Secure cluster transport demands TLS certificate for native transport")) + } + if spec.TLSClientSecret == nil { + allErrors = append(allErrors, field.Required(clientSecretPath, "Secure cluster transport demands client TLS certificate for native transport")) + } + } + + return allErrors +} + func (r *ytsaurusValidator) validateDiscovery(newYtsaurus *Ytsaurus) field.ErrorList { var allErrors field.ErrorList - allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.Discovery.InstanceSpec, field.NewPath("spec").Child("discovery"))...) + allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.Discovery.InstanceSpec, &newYtsaurus.Spec.CommonSpec, field.NewPath("spec").Child("discovery"))...) return allErrors } @@ -79,7 +122,7 @@ func (r *ytsaurusValidator) validateDiscovery(newYtsaurus *Ytsaurus) field.Error func (r *ytsaurusValidator) validateMasterSpec(newYtsaurus *Ytsaurus, mastersSpec, oldMastersSpec *MastersSpec, path *field.Path) field.ErrorList { var allErrors field.ErrorList - allErrors = append(allErrors, r.validateInstanceSpec(mastersSpec.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(mastersSpec.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) allErrors = append(allErrors, r.validateHostAddresses(newYtsaurus, mastersSpec, path)...) if FindFirstLocation(mastersSpec.Locations, LocationTypeMasterChangelogs) == nil { @@ -177,7 +220,7 @@ func (r *ytsaurusValidator) validateHTTPProxies(newYtsaurus *Ytsaurus) field.Err } httpRoles[hp.Role] = true - allErrors = append(allErrors, r.validateInstanceSpec(hp.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(hp.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if features.HTTPProxyHaveHTTPSAddress && hp.Transport.HTTPSSecret == nil { allErrors = append(allErrors, field.Required( @@ -185,6 +228,13 @@ func (r *ytsaurusValidator) validateHTTPProxies(newYtsaurus *Ytsaurus) field.Err "Cluster feature httpProxyHaveHttpsAddress requires HTTPS for all HTTP proxies", )) } + + if features.SecureClusterTransports && !hp.Transport.DisableHTTP { + allErrors = append(allErrors, field.Forbidden( + path.Child("transport").Child("disableHttp"), + "Secure cluster transport demands HTTPS-only proxies", + )) + } } if !hasDefaultHTTPProxy { @@ -199,6 +249,7 @@ func (r *ytsaurusValidator) validateHTTPProxies(newYtsaurus *Ytsaurus) field.Err func (r *ytsaurusValidator) validateRPCProxies(newYtsaurus *Ytsaurus) field.ErrorList { var allErrors field.ErrorList + features := ptr.Deref(newYtsaurus.Spec.ClusterFeatures, ClusterFeatures{}) rpcRoles := make(map[string]bool) for i, rp := range newYtsaurus.Spec.RPCProxies { path := field.NewPath("spec").Child("rpcProxies").Index(i) @@ -207,7 +258,24 @@ func (r *ytsaurusValidator) validateRPCProxies(newYtsaurus *Ytsaurus) field.Erro } rpcRoles[rp.Role] = true - allErrors = append(allErrors, r.validateInstanceSpec(rp.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(rp.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) + + transportPath := path.Child("transport") + if rp.Transport.TLSRequired && rp.Transport.TLSSecret == nil { + allErrors = append(allErrors, field.Required(transportPath.Child("tlsSecret"), "TLS-only RPC proxy requires certificate")) + } + + if features.SecureClusterTransports { + if !rp.Transport.TLSRequired { + allErrors = append(allErrors, field.Required(transportPath.Child("tlsRequired"), "Secure cluster transport demands TLS-only RPC proxies")) + } + if rp.Transport.TLSInsecure { + allErrors = append(allErrors, field.Forbidden(transportPath.Child("tlsInsecure"), "Secure cluster transport demands TLS certificate validation")) + } + if rp.Transport.TLSSecret == nil { + allErrors = append(allErrors, field.Required(transportPath.Child("tlsSecret"), "Secure cluster transport demands RPC proxy certificate")) + } + } } return allErrors @@ -224,7 +292,7 @@ func (r *ytsaurusValidator) validateTCPProxies(newYtsaurus *Ytsaurus) field.Erro } tcpRoles[rp.Role] = true - allErrors = append(allErrors, r.validateInstanceSpec(rp.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(rp.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) } return allErrors @@ -242,7 +310,7 @@ func (r *ytsaurusValidator) validateDataNodes(newYtsaurus *Ytsaurus) field.Error } names[dn.Name] = true - allErrors = append(allErrors, r.validateInstanceSpec(dn.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(dn.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if FindFirstLocation(dn.Locations, LocationTypeChunkStore) == nil { allErrors = append(allErrors, field.NotFound(path.Child("locations"), LocationTypeChunkStore)) @@ -311,7 +379,7 @@ func (r *ytsaurusValidator) validateExecNodes(newYtsaurus *Ytsaurus) field.Error } names[en.Name] = true - allErrors = append(allErrors, r.validateInstanceSpec(en.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(en.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if FindFirstLocation(en.Locations, LocationTypeChunkCache) == nil { allErrors = append(allErrors, field.NotFound(path.Child("locations"), LocationTypeChunkCache)) @@ -344,7 +412,7 @@ func (r *ytsaurusValidator) validateSchedulers(newYtsaurus *Ytsaurus) field.Erro if newYtsaurus.Spec.Schedulers != nil { path := field.NewPath("spec").Child("schedulers") - allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.Schedulers.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.Schedulers.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if newYtsaurus.Spec.ControllerAgents == nil { allErrors = append(allErrors, field.Required(field.NewPath("spec").Child("controllerAgents"), @@ -360,7 +428,7 @@ func (r *ytsaurusValidator) validateControllerAgents(newYtsaurus *Ytsaurus) fiel if newYtsaurus.Spec.ControllerAgents != nil { path := field.NewPath("spec").Child("controllerAgents") - allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.ControllerAgents.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.ControllerAgents.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if newYtsaurus.Spec.Schedulers == nil { allErrors = append(allErrors, field.Required(field.NewPath("spec").Child("schedulers"), @@ -383,7 +451,7 @@ func (r *ytsaurusValidator) validateTabletNodes(newYtsaurus *Ytsaurus) field.Err } names[tn.Name] = true - allErrors = append(allErrors, r.validateInstanceSpec(tn.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(tn.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) } return allErrors @@ -413,7 +481,7 @@ func (r *ytsaurusValidator) validateQueryTrackers(newYtsaurus *Ytsaurus) field.E if newYtsaurus.Spec.QueryTrackers != nil { path := field.NewPath("spec").Child("queryTrackers") - allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.QueryTrackers.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.QueryTrackers.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if len(newYtsaurus.Spec.TabletNodes) == 0 { allErrors = append(allErrors, field.Required(field.NewPath("spec").Child("tabletNodes"), @@ -434,7 +502,7 @@ func (r *ytsaurusValidator) validateQueueAgents(newYtsaurus *Ytsaurus) field.Err if newYtsaurus.Spec.QueueAgents != nil { path := field.NewPath("spec").Child("queueAgents") - allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.QueueAgents.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.QueueAgents.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if len(newYtsaurus.Spec.TabletNodes) == 0 { allErrors = append(allErrors, field.Required(field.NewPath("spec").Child("tabletNodes"), @@ -462,7 +530,7 @@ func (r *ytsaurusValidator) validateYQLAgents(newYtsaurus *Ytsaurus) field.Error if newYtsaurus.Spec.YQLAgents != nil { path := field.NewPath("spec").Child("YQLAgents") - allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.YQLAgents.InstanceSpec, path)...) + allErrors = append(allErrors, r.validateInstanceSpec(newYtsaurus.Spec.YQLAgents.InstanceSpec, &newYtsaurus.Spec.CommonSpec, path)...) if newYtsaurus.Spec.QueryTrackers == nil { allErrors = append(allErrors, field.Required(field.NewPath("spec").Child("queryTrackers"), @@ -493,7 +561,7 @@ func (r *ytsaurusValidator) validateUi(newYtsaurus *Ytsaurus) field.ErrorList { return allErrors } -func (r *baseValidator) validateInstanceSpec(instanceSpec InstanceSpec, path *field.Path) field.ErrorList { +func (r *baseValidator) validateInstanceSpec(instanceSpec InstanceSpec, commonSpec *CommonSpec, path *field.Path) field.ErrorList { var allErrors field.ErrorList allErrors = append(allErrors, v1validation.ValidateLabels(instanceSpec.PodLabels, path.Child("podLabels"))...) @@ -504,6 +572,8 @@ func (r *baseValidator) validateInstanceSpec(instanceSpec InstanceSpec, path *fi "EnableAntiAffinity is deprecated, use Affinity instead")) } + allErrors = append(allErrors, r.validateTransportSecurity(instanceSpec.NativeTransport, commonSpec, path.Child("nativeTransport"))...) + if instanceSpec.Locations != nil { for locationIdx, location := range instanceSpec.Locations { inVolumeMount := false @@ -554,7 +624,25 @@ func (r *baseValidator) validateCommonSpec(spec *CommonSpec) field.ErrorList { var allErrors field.ErrorList path := field.NewPath("spec") + if features := spec.ClusterFeatures; features != nil { + if features.SecureClusterTransports { + if !features.RPCProxyHavePublicAddress { + allErrors = append(allErrors, field.Required( + path.Child("clusterFeatures").Child("rpcProxyHavePublicAddress"), + "Secure cluster transport demands public address for RPC proxies", + )) + } + if !features.HTTPProxyHaveHTTPSAddress { + allErrors = append(allErrors, field.Required( + path.Child("clusterFeatures").Child("httpProxyHaveHttpsAddress"), + "Secure cluster transport demands HTTPS for HTTP proxies", + )) + } + } + } + allErrors = append(allErrors, validation.ValidateAnnotations(spec.ExtraPodAnnotations, path.Child("extraPodAnnotations"))...) + allErrors = append(allErrors, r.validateTransportSecurity(spec.NativeTransport, spec, path.Child("nativeTransport"))...) return allErrors } diff --git a/config/crd/bases/cluster.ytsaurus.tech_offshoredatagateways.yaml b/config/crd/bases/cluster.ytsaurus.tech_offshoredatagateways.yaml index f56b68a44..04e150c54 100644 --- a/config/crd/bases/cluster.ytsaurus.tech_offshoredatagateways.yaml +++ b/config/crd/bases/cluster.ytsaurus.tech_offshoredatagateways.yaml @@ -771,6 +771,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/config/crd/bases/cluster.ytsaurus.tech_remotedatanodes.yaml b/config/crd/bases/cluster.ytsaurus.tech_remotedatanodes.yaml index 86cf507a8..33ea0b2aa 100644 --- a/config/crd/bases/cluster.ytsaurus.tech_remotedatanodes.yaml +++ b/config/crd/bases/cluster.ytsaurus.tech_remotedatanodes.yaml @@ -769,6 +769,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/config/crd/bases/cluster.ytsaurus.tech_remoteexecnodes.yaml b/config/crd/bases/cluster.ytsaurus.tech_remoteexecnodes.yaml index eb3c7f003..f1448f43e 100644 --- a/config/crd/bases/cluster.ytsaurus.tech_remoteexecnodes.yaml +++ b/config/crd/bases/cluster.ytsaurus.tech_remoteexecnodes.yaml @@ -769,6 +769,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/config/crd/bases/cluster.ytsaurus.tech_remotetabletnodes.yaml b/config/crd/bases/cluster.ytsaurus.tech_remotetabletnodes.yaml index 8fe24c539..99ff2e6db 100644 --- a/config/crd/bases/cluster.ytsaurus.tech_remotetabletnodes.yaml +++ b/config/crd/bases/cluster.ytsaurus.tech_remotetabletnodes.yaml @@ -769,6 +769,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml b/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml index 548a2a94e..1983f4539 100644 --- a/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml +++ b/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml @@ -1998,6 +1998,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/docs/api.md b/docs/api.md index f8adb3517..7aec72b8d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -335,6 +335,7 @@ _Appears in:_ | `rpcProxyHavePublicAddress` _boolean_ | RPC proxies have "public_rpc" address. Required for separated internal/public TLS CA. | | | | `httpProxyHaveChytAddress` _boolean_ | HTTP proxies have "chyt_http_server" and "chyt_https_server". Opens ports for access to chyt via HTTP proxy. | | | | `httpProxyHaveHttpsAddress` _boolean_ | HTTP proxies have "https" address. Use HTTPS for all communications. | | | +| `secureClusterTransports` _boolean_ | Validate that only secure transports are allowed for cluster connections. | | | #### ClusterNodesSpec diff --git a/pkg/testutil/spec_builders.go b/pkg/testutil/spec_builders.go index fcc44d011..0b33f2b7f 100644 --- a/pkg/testutil/spec_builders.go +++ b/pkg/testutil/spec_builders.go @@ -361,6 +361,7 @@ func (b *YtsaurusBuilder) WithAllClusterFeatures() { RPCProxyHavePublicAddress: true, HTTPProxyHaveChytAddress: true, HTTPProxyHaveHTTPSAddress: true, + SecureClusterTransports: false, // Turned off to increase coverage. } } diff --git a/test/webhooks/ytsaurus_webhooks_test.go b/test/webhooks/ytsaurus_webhooks_test.go index b6b1dccd2..b9401de1b 100644 --- a/test/webhooks/ytsaurus_webhooks_test.go +++ b/test/webhooks/ytsaurus_webhooks_test.go @@ -473,5 +473,105 @@ var _ = Describe("Test for Ytsaurus webhooks", func() { Expect(k8sClient.Create(ctx, ytsaurus)).Should(Succeed()) Expect(k8sClient.Delete(ctx, ytsaurus)).Should(Succeed()) }) + + Context("Secure cluster transports", func() { + BeforeEach(func() { + builder.WithRPCProxies() + ytsaurus.Spec.ClusterFeatures = &ytv1.ClusterFeatures{ + RPCProxyHavePublicAddress: true, + HTTPProxyHaveHTTPSAddress: true, + SecureClusterTransports: true, + } + ytsaurus.Spec.NativeTransport = &ytv1.RPCTransportSpec{ + TLSSecret: &corev1.LocalObjectReference{ + Name: "server-cert", + }, + TLSClientSecret: &corev1.LocalObjectReference{ + Name: "client-cert", + }, + TLSRequired: true, + TLSInsecure: false, + } + ytsaurus.Spec.HTTPProxies[0].Transport = ytv1.HTTPTransportSpec{ + HTTPSSecret: &corev1.LocalObjectReference{ + Name: "https-secret", + }, + DisableHTTP: true, + } + ytsaurus.Spec.RPCProxies[0].Transport = ytv1.RPCTransportSpec{ + TLSSecret: &corev1.LocalObjectReference{ + Name: "rpc-proxy-secret", + }, + TLSRequired: true, + } + + By("Checking success", func() { + ytsaurus1 := ytsaurus.DeepCopy() + Expect(k8sClient.Create(ctx, ytsaurus1)).Should(Succeed()) + Expect(k8sClient.Delete(ctx, ytsaurus1)).Should(Succeed()) + }) + }) + + AfterEach(func() { + ytsaurus1 := ytsaurus.DeepCopy() + By("Checking failure", func() { + err := k8sClient.Create(ctx, ytsaurus) + Expect(err).ShouldNot(Succeed()) + }) + By("Checking success without secure cluster", func() { + ytsaurus1.Spec.ClusterFeatures.HTTPProxyHaveHTTPSAddress = false + ytsaurus1.Spec.ClusterFeatures.SecureClusterTransports = false + Expect(k8sClient.Create(ctx, ytsaurus1)).Should(Succeed()) + Expect(k8sClient.Delete(ctx, ytsaurus1)).Should(Succeed()) + }) + }) + + DescribeTable("Failures", + func(fn func()) { + fn() + }, + Entry("no rpc public address", func() { + ytsaurus.Spec.ClusterFeatures.RPCProxyHavePublicAddress = false + }), + Entry("no https proxy address", func() { + ytsaurus.Spec.ClusterFeatures.HTTPProxyHaveHTTPSAddress = false + }), + Entry("no tls setup", func() { + ytsaurus.Spec.NativeTransport = nil + }), + Entry("tls optional", func() { + ytsaurus.Spec.NativeTransport.TLSRequired = false + }), + Entry("tls insecure", func() { + ytsaurus.Spec.NativeTransport.TLSInsecure = true + }), + Entry("no client cert", func() { + ytsaurus.Spec.NativeTransport.TLSClientSecret = nil + ytsaurus.Spec.NativeTransport.TLSInsecure = true + }), + Entry("instance tls optional", func() { + transport := *ytsaurus.Spec.NativeTransport + transport.TLSRequired = false + ytsaurus.Spec.PrimaryMasters.NativeTransport = &transport + }), + Entry("instance tls insecure", func() { + transport := *ytsaurus.Spec.NativeTransport + transport.TLSInsecure = true + ytsaurus.Spec.PrimaryMasters.NativeTransport = &transport + }), + Entry("no https", func() { + ytsaurus.Spec.HTTPProxies[0].Transport = ytv1.HTTPTransportSpec{} + }), + Entry("not https-only", func() { + ytsaurus.Spec.HTTPProxies[0].Transport.DisableHTTP = false + }), + Entry("rpc-proxy without tls", func() { + ytsaurus.Spec.RPCProxies[0].Transport = ytv1.RPCTransportSpec{} + }), + Entry("rpc-proxy not tls-only", func() { + ytsaurus.Spec.RPCProxies[0].Transport.TLSRequired = false + }), + ) + }) }) }) diff --git a/ytop-chart/templates/crds/cluster.ytsaurus.tech_offshoredatagateways.yaml b/ytop-chart/templates/crds/cluster.ytsaurus.tech_offshoredatagateways.yaml index c35912aa7..031e21355 100644 --- a/ytop-chart/templates/crds/cluster.ytsaurus.tech_offshoredatagateways.yaml +++ b/ytop-chart/templates/crds/cluster.ytsaurus.tech_offshoredatagateways.yaml @@ -776,6 +776,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotedatanodes.yaml b/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotedatanodes.yaml index 2b159ed16..35ccb1d89 100644 --- a/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotedatanodes.yaml +++ b/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotedatanodes.yaml @@ -774,6 +774,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/ytop-chart/templates/crds/cluster.ytsaurus.tech_remoteexecnodes.yaml b/ytop-chart/templates/crds/cluster.ytsaurus.tech_remoteexecnodes.yaml index a6e88b9bd..a7ed56bb2 100644 --- a/ytop-chart/templates/crds/cluster.ytsaurus.tech_remoteexecnodes.yaml +++ b/ytop-chart/templates/crds/cluster.ytsaurus.tech_remoteexecnodes.yaml @@ -774,6 +774,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotetabletnodes.yaml b/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotetabletnodes.yaml index c63a02296..7c6281aea 100644 --- a/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotetabletnodes.yaml +++ b/ytop-chart/templates/crds/cluster.ytsaurus.tech_remotetabletnodes.yaml @@ -774,6 +774,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let diff --git a/ytop-chart/templates/crds/cluster.ytsaurus.tech_ytsaurus.yaml b/ytop-chart/templates/crds/cluster.ytsaurus.tech_ytsaurus.yaml index dd49bce71..7bf363c37 100644 --- a/ytop-chart/templates/crds/cluster.ytsaurus.tech_ytsaurus.yaml +++ b/ytop-chart/templates/crds/cluster.ytsaurus.tech_ytsaurus.yaml @@ -2003,6 +2003,10 @@ spec: rpcProxyHavePublicAddress: description: RPC proxies have "public_rpc" address. type: boolean + secureClusterTransports: + description: Validate that only secure transports are allowed + for cluster connections. + type: boolean type: object configOverrides: description: LocalObjectReference contains enough information to let