!115 fix CVE-2022-3294
From: @zh_xiaoyu Reviewed-by: @duguhaotian Signed-off-by: @duguhaotian
This commit is contained in:
commit
6265df3b29
245
0008-fix-node-address-validation.patch
Normal file
245
0008-fix-node-address-validation.patch
Normal file
@ -0,0 +1,245 @@
|
||||
From 78d552efe620879599509ff0f9b04b8764e1878f Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Sy Kim <andrewsy@google.com>
|
||||
Date: Mon, 7 Nov 2022 10:22:44 -0500
|
||||
Subject: [PATCH] fix node address validation
|
||||
|
||||
Signed-off-by: Andrew Sy Kim <andrewsy@google.com>
|
||||
---
|
||||
.../core/node/storage/storage_test.go | 171 +++++++++++++++++-
|
||||
pkg/registry/core/node/strategy.go | 8 +-
|
||||
2 files changed, 174 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/pkg/registry/core/node/storage/storage_test.go b/pkg/registry/core/node/storage/storage_test.go
|
||||
index af228b8a43a..89df2edf16b 100644
|
||||
--- a/pkg/registry/core/node/storage/storage_test.go
|
||||
+++ b/pkg/registry/core/node/storage/storage_test.go
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package storage
|
||||
|
||||
import (
|
||||
+ "fmt"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
@@ -24,11 +25,14 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
+ genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing"
|
||||
+ "k8s.io/apiserver/pkg/registry/rest"
|
||||
etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
||||
+ proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/registry/registrytest"
|
||||
)
|
||||
|
||||
@@ -40,7 +44,10 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
|
||||
DeleteCollectionWorkers: 1,
|
||||
ResourcePrefix: "nodes",
|
||||
}
|
||||
- storage, err := NewStorage(restOptions, kubeletclient.KubeletClientConfig{}, nil)
|
||||
+ storage, err := NewStorage(restOptions, kubeletclient.KubeletClientConfig{
|
||||
+ Port: 10250,
|
||||
+ PreferredAddressTypes: []string{string(api.NodeInternalIP)},
|
||||
+ }, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -156,3 +163,165 @@ func TestShortNames(t *testing.T) {
|
||||
expected := []string{"no"}
|
||||
registrytest.AssertShortNames(t, storage, expected)
|
||||
}
|
||||
+
|
||||
+func TestResourceLocation(t *testing.T) {
|
||||
+ testCases := []struct {
|
||||
+ name string
|
||||
+ node api.Node
|
||||
+ query string
|
||||
+ location string
|
||||
+ err error
|
||||
+ }{
|
||||
+ {
|
||||
+ name: "proxyable hostname with default port",
|
||||
+ node: api.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{Name: "node0"},
|
||||
+ Status: api.NodeStatus{
|
||||
+ Addresses: []api.NodeAddress{
|
||||
+ {
|
||||
+ Type: api.NodeInternalIP,
|
||||
+ Address: "10.0.0.1",
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ query: "node0",
|
||||
+ location: "10.0.0.1:10250",
|
||||
+ err: nil,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "proxyable hostname with kubelet port in query",
|
||||
+ node: api.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{Name: "node0"},
|
||||
+ Status: api.NodeStatus{
|
||||
+ Addresses: []api.NodeAddress{
|
||||
+ {
|
||||
+ Type: api.NodeInternalIP,
|
||||
+ Address: "10.0.0.1",
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ query: "node0:5000",
|
||||
+ location: "10.0.0.1:5000",
|
||||
+ err: nil,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "proxyable hostname with kubelet port in status",
|
||||
+ node: api.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{Name: "node0"},
|
||||
+ Status: api.NodeStatus{
|
||||
+ Addresses: []api.NodeAddress{
|
||||
+ {
|
||||
+ Type: api.NodeInternalIP,
|
||||
+ Address: "10.0.0.1",
|
||||
+ },
|
||||
+ },
|
||||
+ DaemonEndpoints: api.NodeDaemonEndpoints{
|
||||
+ KubeletEndpoint: api.DaemonEndpoint{
|
||||
+ Port: 5000,
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ query: "node0",
|
||||
+ location: "10.0.0.1:5000",
|
||||
+ err: nil,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "non-proxyable hostname with default port",
|
||||
+ node: api.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{Name: "node0"},
|
||||
+ Status: api.NodeStatus{
|
||||
+ Addresses: []api.NodeAddress{
|
||||
+ {
|
||||
+ Type: api.NodeInternalIP,
|
||||
+ Address: "127.0.0.1",
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ query: "node0",
|
||||
+ location: "",
|
||||
+ err: proxyutil.ErrAddressNotAllowed,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "non-proxyable hostname with kubelet port in query",
|
||||
+ node: api.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{Name: "node0"},
|
||||
+ Status: api.NodeStatus{
|
||||
+ Addresses: []api.NodeAddress{
|
||||
+ {
|
||||
+ Type: api.NodeInternalIP,
|
||||
+ Address: "127.0.0.1",
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ query: "node0:5000",
|
||||
+ location: "",
|
||||
+ err: proxyutil.ErrAddressNotAllowed,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "non-proxyable hostname with kubelet port in status",
|
||||
+ node: api.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{Name: "node0"},
|
||||
+ Status: api.NodeStatus{
|
||||
+ Addresses: []api.NodeAddress{
|
||||
+ {
|
||||
+ Type: api.NodeInternalIP,
|
||||
+ Address: "127.0.0.1",
|
||||
+ },
|
||||
+ },
|
||||
+ DaemonEndpoints: api.NodeDaemonEndpoints{
|
||||
+ KubeletEndpoint: api.DaemonEndpoint{
|
||||
+ Port: 443,
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ query: "node0",
|
||||
+ location: "",
|
||||
+ err: proxyutil.ErrAddressNotAllowed,
|
||||
+ },
|
||||
+ }
|
||||
+
|
||||
+ for _, testCase := range testCases {
|
||||
+ t.Run(testCase.name, func(t *testing.T) {
|
||||
+ storage, server := newStorage(t)
|
||||
+ defer server.Terminate(t)
|
||||
+ defer storage.Store.DestroyFunc()
|
||||
+
|
||||
+ ctx := genericapirequest.WithNamespace(genericapirequest.NewDefaultContext(), fmt.Sprintf("namespace-%s", testCase.name))
|
||||
+ key, _ := storage.KeyFunc(ctx, testCase.node.Name)
|
||||
+ if err := storage.Storage.Create(ctx, key, &testCase.node, nil, 0, false); err != nil {
|
||||
+ t.Fatalf("unexpected error: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ redirector := rest.Redirector(storage)
|
||||
+ location, _, err := redirector.ResourceLocation(ctx, testCase.query)
|
||||
+
|
||||
+ if err != nil && testCase.err != nil {
|
||||
+ if err.Error() != testCase.err.Error() {
|
||||
+ t.Fatalf("Unexpected error: %v, expected: %v", err, testCase.err)
|
||||
+ }
|
||||
+
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ if err != nil && testCase.err == nil {
|
||||
+ t.Fatalf("Unexpected error: %v, expected: %v", err, testCase.err)
|
||||
+ } else if err == nil && testCase.err != nil {
|
||||
+ t.Fatalf("Expected error but got none, err: %v", testCase.err)
|
||||
+ }
|
||||
+
|
||||
+ if location == nil {
|
||||
+ t.Errorf("Unexpected nil resource location: %v", location)
|
||||
+ }
|
||||
+
|
||||
+ if location.Host != testCase.location {
|
||||
+ t.Errorf("Unexpected host: expected %v, but got %v", testCase.location, location.Host)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
diff --git a/pkg/registry/core/node/strategy.go b/pkg/registry/core/node/strategy.go
|
||||
index bf6b6a57708..f879f327279 100644
|
||||
--- a/pkg/registry/core/node/strategy.go
|
||||
+++ b/pkg/registry/core/node/strategy.go
|
||||
@@ -249,6 +249,10 @@ func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGet
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
+ if err := proxyutil.IsProxyableHostname(ctx, &net.Resolver{}, info.Hostname); err != nil {
|
||||
+ return nil, nil, errors.NewBadRequest(err.Error())
|
||||
+ }
|
||||
+
|
||||
// We check if we want to get a default Kubelet's transport. It happens if either:
|
||||
// - no port is specified in request (Kubelet's port is default)
|
||||
// - the requested port matches the kubelet port for this node
|
||||
@@ -261,10 +265,6 @@ func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGet
|
||||
nil
|
||||
}
|
||||
|
||||
- if err := proxyutil.IsProxyableHostname(ctx, &net.Resolver{}, info.Hostname); err != nil {
|
||||
- return nil, nil, errors.NewBadRequest(err.Error())
|
||||
- }
|
||||
-
|
||||
// Otherwise, return the requested scheme and port, and the proxy transport
|
||||
return &url.URL{Scheme: schemeReq, Host: net.JoinHostPort(info.Hostname, portReq)}, proxyTransport, nil
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
Name: kubernetes
|
||||
Version: 1.24.0
|
||||
Release: 3
|
||||
Release: 4
|
||||
Summary: Container cluster management
|
||||
License: ASL 2.0
|
||||
URL: https://k8s.io/kubernetes
|
||||
@ -31,6 +31,7 @@ Patch0004: 0004-Add-an-option-for-aggregator.patch
|
||||
Patch0005: 0005-Escape-terminal-special-characters-in-kubectl-112553.patch
|
||||
Patch0006: 0006-Return-error-for-localhost-seccomp-type-with-no-loca.patch
|
||||
Patch0007: 0007-Validate-etcd-paths.patch
|
||||
Patch0008: 0008-fix-node-address-validation.patch
|
||||
|
||||
%description
|
||||
Container cluster management.
|
||||
@ -262,6 +263,12 @@ getent passwd kube >/dev/null || useradd -r -g kube -d / -s /sbin/nologin \
|
||||
%systemd_postun kubelet kube-proxy
|
||||
|
||||
%changelog
|
||||
* Tue Jul 04 2023 zhangxiaoyu <zhangxiaoyu58@huawei.com> - 1.24.0-4
|
||||
- Type:bugfix
|
||||
- CVE:NA
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2022-3294
|
||||
|
||||
* Thu Jun 29 2023 zhangxiaoyu <zhangxiaoyu58@huawei.com> - 1.24.0-3
|
||||
- Type:bugfix
|
||||
- CVE:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user