diff options
4 files changed, 381 insertions, 0 deletions
diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch new file mode 100644 index 00000000..dd70627d --- /dev/null +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch | |||
| @@ -0,0 +1,179 @@ | |||
| 1 | From 68750fefd3df76b7b008ef7b18e8acd18d5c2f2e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Joel Smith <joesmith@redhat.com> | ||
| 3 | Date: Thu, 14 May 2020 20:09:58 -0600 | ||
| 4 | Subject: [PATCH] Include pod /etc/hosts in ephemeral storage calculation for | ||
| 5 | eviction | ||
| 6 | |||
| 7 | CVE: CVE-2020-8557 | ||
| 8 | Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16] | ||
| 9 | Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com> | ||
| 10 | --- | ||
| 11 | src/import/pkg/kubelet/eviction/BUILD | 1 + | ||
| 12 | src/import/pkg/kubelet/eviction/eviction_manager.go | 7 ++++++- | ||
| 13 | src/import/pkg/kubelet/eviction/helpers.go | 9 ++++++++- | ||
| 14 | src/import/pkg/kubelet/kubelet.go | 3 ++- | ||
| 15 | src/import/pkg/kubelet/kubelet_pods.go | 7 ++++++- | ||
| 16 | src/import/pkg/kubelet/kubelet_test.go | 3 ++- | ||
| 17 | src/import/pkg/kubelet/runonce_test.go | 3 ++- | ||
| 18 | 7 files changed, 27 insertions(+), 6 deletions(-) | ||
| 19 | |||
| 20 | diff --git a/src/import/pkg/kubelet/eviction/BUILD b/src/import/pkg/kubelet/eviction/BUILD | ||
| 21 | index 2209b26d7d4..e8c2241e075 100644 | ||
| 22 | --- a/src/import/pkg/kubelet/eviction/BUILD | ||
| 23 | +++ b/src/import/pkg/kubelet/eviction/BUILD | ||
| 24 | @@ -66,6 +66,7 @@ go_library( | ||
| 25 | "//staging/src/k8s.io/api/core/v1:go_default_library", | ||
| 26 | "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", | ||
| 27 | "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", | ||
| 28 | + "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", | ||
| 29 | "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library", | ||
| 30 | "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", | ||
| 31 | "//staging/src/k8s.io/client-go/tools/record:go_default_library", | ||
| 32 | diff --git a/src/import/pkg/kubelet/eviction/eviction_manager.go b/src/import/pkg/kubelet/eviction/eviction_manager.go | ||
| 33 | index 4ef2a89dce6..ca218cb942f 100644 | ||
| 34 | --- a/src/import/pkg/kubelet/eviction/eviction_manager.go | ||
| 35 | +++ b/src/import/pkg/kubelet/eviction/eviction_manager.go | ||
| 36 | @@ -26,6 +26,7 @@ import ( | ||
| 37 | |||
| 38 | v1 "k8s.io/api/core/v1" | ||
| 39 | "k8s.io/apimachinery/pkg/api/resource" | ||
| 40 | + "k8s.io/apimachinery/pkg/types" | ||
| 41 | "k8s.io/apimachinery/pkg/util/clock" | ||
| 42 | utilfeature "k8s.io/apiserver/pkg/util/feature" | ||
| 43 | "k8s.io/client-go/tools/record" | ||
| 44 | @@ -90,6 +91,8 @@ type managerImpl struct { | ||
| 45 | thresholdNotifiers []ThresholdNotifier | ||
| 46 | // thresholdsLastUpdated is the last time the thresholdNotifiers were updated. | ||
| 47 | thresholdsLastUpdated time.Time | ||
| 48 | + // etcHostsPath is a function that will get the etc-hosts file's path for a pod given its UID | ||
| 49 | + etcHostsPath func(podUID types.UID) string | ||
| 50 | } | ||
| 51 | |||
| 52 | // ensure it implements the required interface | ||
| 53 | @@ -106,6 +109,7 @@ func NewManager( | ||
| 54 | recorder record.EventRecorder, | ||
| 55 | nodeRef *v1.ObjectReference, | ||
| 56 | clock clock.Clock, | ||
| 57 | + etcHostsPath func(types.UID) string, | ||
| 58 | ) (Manager, lifecycle.PodAdmitHandler) { | ||
| 59 | manager := &managerImpl{ | ||
| 60 | clock: clock, | ||
| 61 | @@ -121,6 +125,7 @@ func NewManager( | ||
| 62 | thresholdsFirstObservedAt: thresholdsObservedAt{}, | ||
| 63 | dedicatedImageFs: nil, | ||
| 64 | thresholdNotifiers: []ThresholdNotifier{}, | ||
| 65 | + etcHostsPath: etcHostsPath, | ||
| 66 | } | ||
| 67 | return manager, manager | ||
| 68 | } | ||
| 69 | @@ -503,7 +508,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat | ||
| 70 | } else { | ||
| 71 | fsStatsSet = []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource} | ||
| 72 | } | ||
| 73 | - podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet) | ||
| 74 | + podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet, m.etcHostsPath(pod.UID)) | ||
| 75 | if err != nil { | ||
| 76 | klog.Errorf("eviction manager: error getting pod disk usage %v", err) | ||
| 77 | return false | ||
| 78 | diff --git a/src/import/pkg/kubelet/eviction/helpers.go b/src/import/pkg/kubelet/eviction/helpers.go | ||
| 79 | index dfdb8ce3b60..41c55855aad 100644 | ||
| 80 | --- a/src/import/pkg/kubelet/eviction/helpers.go | ||
| 81 | +++ b/src/import/pkg/kubelet/eviction/helpers.go | ||
| 82 | @@ -18,6 +18,7 @@ package eviction | ||
| 83 | |||
| 84 | import ( | ||
| 85 | "fmt" | ||
| 86 | + "os" | ||
| 87 | "sort" | ||
| 88 | "strconv" | ||
| 89 | "strings" | ||
| 90 | @@ -415,7 +416,7 @@ func localEphemeralVolumeNames(pod *v1.Pod) []string { | ||
| 91 | } | ||
| 92 | |||
| 93 | // podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure. | ||
| 94 | -func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) { | ||
| 95 | +func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType, etcHostsPath string) (v1.ResourceList, error) { | ||
| 96 | disk := resource.Quantity{Format: resource.BinarySI} | ||
| 97 | inodes := resource.Quantity{Format: resource.DecimalSI} | ||
| 98 | |||
| 99 | @@ -429,6 +430,12 @@ func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, stat | ||
| 100 | disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage]) | ||
| 101 | inodes.Add(podLocalVolumeUsageList[resourceInodes]) | ||
| 102 | } | ||
| 103 | + if len(etcHostsPath) > 0 { | ||
| 104 | + if stat, err := os.Stat(etcHostsPath); err == nil { | ||
| 105 | + disk.Add(*resource.NewQuantity(int64(stat.Size()), resource.BinarySI)) | ||
| 106 | + inodes.Add(*resource.NewQuantity(int64(1), resource.DecimalSI)) | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | return v1.ResourceList{ | ||
| 110 | v1.ResourceEphemeralStorage: disk, | ||
| 111 | resourceInodes: inodes, | ||
| 112 | diff --git a/src/import/pkg/kubelet/kubelet.go b/src/import/pkg/kubelet/kubelet.go | ||
| 113 | index c2acd358e59..8da5d0f2e92 100644 | ||
| 114 | --- a/src/import/pkg/kubelet/kubelet.go | ||
| 115 | +++ b/src/import/pkg/kubelet/kubelet.go | ||
| 116 | @@ -831,8 +831,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, | ||
| 117 | klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff) | ||
| 118 | klet.podKillingCh = make(chan *kubecontainer.PodPair, podKillingChannelCapacity) | ||
| 119 | |||
| 120 | + etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(klet.getPodDir(podUID)) } | ||
| 121 | // setup eviction manager | ||
| 122 | - evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock) | ||
| 123 | + evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock, etcHostsPathFunc) | ||
| 124 | |||
| 125 | klet.evictionManager = evictionManager | ||
| 126 | klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) | ||
| 127 | diff --git a/src/import/pkg/kubelet/kubelet_pods.go b/src/import/pkg/kubelet/kubelet_pods.go | ||
| 128 | index 013d0f55aea..02857d4b5b3 100644 | ||
| 129 | --- a/src/import/pkg/kubelet/kubelet_pods.go | ||
| 130 | +++ b/src/import/pkg/kubelet/kubelet_pods.go | ||
| 131 | @@ -291,10 +291,15 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | +// getEtcHostsPath returns the full host-side path to a pod's generated /etc/hosts file | ||
| 136 | +func getEtcHostsPath(podDir string) string { | ||
| 137 | + return path.Join(podDir, "etc-hosts") | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | // makeHostsMount makes the mountpoint for the hosts file that the containers | ||
| 141 | // in a pod are injected with. | ||
| 142 | func makeHostsMount(podDir, podIP, hostName, hostDomainName string, hostAliases []v1.HostAlias, useHostNetwork bool) (*kubecontainer.Mount, error) { | ||
| 143 | - hostsFilePath := path.Join(podDir, "etc-hosts") | ||
| 144 | + hostsFilePath := getEtcHostsPath(podDir) | ||
| 145 | if err := ensureHostsFile(hostsFilePath, podIP, hostName, hostDomainName, hostAliases, useHostNetwork); err != nil { | ||
| 146 | return nil, err | ||
| 147 | } | ||
| 148 | diff --git a/src/import/pkg/kubelet/kubelet_test.go b/src/import/pkg/kubelet/kubelet_test.go | ||
| 149 | index 80c6dcb73b6..9fb417fbb9d 100644 | ||
| 150 | --- a/src/import/pkg/kubelet/kubelet_test.go | ||
| 151 | +++ b/src/import/pkg/kubelet/kubelet_test.go | ||
| 152 | @@ -291,8 +291,9 @@ func newTestKubeletWithImageList( | ||
| 153 | UID: types.UID(kubelet.nodeName), | ||
| 154 | Namespace: "", | ||
| 155 | } | ||
| 156 | + etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kubelet.getPodDir(podUID)) } | ||
| 157 | // setup eviction manager | ||
| 158 | - evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock) | ||
| 159 | + evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock, etcHostsPathFunc) | ||
| 160 | |||
| 161 | kubelet.evictionManager = evictionManager | ||
| 162 | kubelet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) | ||
| 163 | diff --git a/src/import/pkg/kubelet/runonce_test.go b/src/import/pkg/kubelet/runonce_test.go | ||
| 164 | index 7239133e481..9b162c11702 100644 | ||
| 165 | --- a/src/import/pkg/kubelet/runonce_test.go | ||
| 166 | +++ b/src/import/pkg/kubelet/runonce_test.go | ||
| 167 | @@ -125,7 +125,8 @@ func TestRunOnce(t *testing.T) { | ||
| 168 | return nil | ||
| 169 | } | ||
| 170 | fakeMirrodPodFunc := func(*v1.Pod) (*v1.Pod, bool) { return nil, false } | ||
| 171 | - evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock) | ||
| 172 | + etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kb.getPodDir(podUID)) } | ||
| 173 | + evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock, etcHostsPathFunc) | ||
| 174 | |||
| 175 | kb.evictionManager = evictionManager | ||
| 176 | kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) | ||
| 177 | -- | ||
| 178 | 2.17.0 | ||
| 179 | |||
diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch new file mode 100644 index 00000000..9eeed26c --- /dev/null +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | From d22a61e21d677f7527bc8a4aeb3288c5e11dd49b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Casey Callendrello <cdc@redhat.com> | ||
| 3 | Date: Fri, 29 May 2020 13:03:37 +0200 | ||
| 4 | Subject: [PATCH] kubelet: block non-forwarded packets from crossing the | ||
| 5 | localhost boundary | ||
| 6 | |||
| 7 | We set route_localnet so that host-network processes can connect to | ||
| 8 | <127.0.0.1:NodePort> and it still works. This, however, is too | ||
| 9 | permissive. | ||
| 10 | |||
| 11 | So, block martians that are not already in conntrack. | ||
| 12 | |||
| 13 | See: #90259 | ||
| 14 | Signed-off-by: Casey Callendrello <cdc@redhat.com> | ||
| 15 | CVE: CVE-2020-8558 | ||
| 16 | Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16] | ||
| 17 | Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com> | ||
| 18 | --- | ||
| 19 | src/import/pkg/kubelet/kubelet_network_linux.go | 16 ++++++++++++++++ | ||
| 20 | 1 file changed, 16 insertions(+) | ||
| 21 | |||
| 22 | diff --git a/src/import/pkg/kubelet/kubelet_network_linux.go b/src/import/pkg/kubelet/kubelet_network_linux.go | ||
| 23 | index 1c9ad46b989..d18ab75a053 100644 | ||
| 24 | --- a/src/import/pkg/kubelet/kubelet_network_linux.go | ||
| 25 | +++ b/src/import/pkg/kubelet/kubelet_network_linux.go | ||
| 26 | @@ -68,6 +68,22 @@ func (kl *Kubelet) syncNetworkUtil() { | ||
| 27 | klog.Errorf("Failed to ensure rule to drop packet marked by %v in %v chain %v: %v", KubeMarkDropChain, utiliptables.TableFilter, KubeFirewallChain, err) | ||
| 28 | return | ||
| 29 | } | ||
| 30 | + | ||
| 31 | + // drop all non-local packets to localhost if they're not part of an existing | ||
| 32 | + // forwarded connection. See #90259 | ||
| 33 | + if !kl.iptClient.IsIpv6() { // ipv6 doesn't have this issue | ||
| 34 | + if _, err := kl.iptClient.EnsureRule(utiliptables.Append, utiliptables.TableFilter, KubeFirewallChain, | ||
| 35 | + "-m", "comment", "--comment", "block incoming localnet connections", | ||
| 36 | + "--dst", "127.0.0.0/8", | ||
| 37 | + "!", "--src", "127.0.0.0/8", | ||
| 38 | + "-m", "conntrack", | ||
| 39 | + "!", "--ctstate", "RELATED,ESTABLISHED,DNAT", | ||
| 40 | + "-j", "DROP"); err != nil { | ||
| 41 | + klog.Errorf("Failed to ensure rule to drop invalid localhost packets in %v chain %v: %v", utiliptables.TableFilter, KubeFirewallChain, err) | ||
| 42 | + return | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | if _, err := kl.iptClient.EnsureRule(utiliptables.Prepend, utiliptables.TableFilter, utiliptables.ChainOutput, "-j", string(KubeFirewallChain)); err != nil { | ||
| 47 | klog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", utiliptables.TableFilter, utiliptables.ChainOutput, KubeFirewallChain, err) | ||
| 48 | return | ||
| 49 | -- | ||
| 50 | 2.17.0 | ||
| 51 | |||
diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch new file mode 100644 index 00000000..f47826df --- /dev/null +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | From ba3ca4929ed3887c95f94fcf97610f3449446804 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Tim Allclair <tallclair@google.com> | ||
| 3 | Date: Wed, 17 Jun 2020 11:09:02 -0700 | ||
| 4 | Subject: [PATCH] Don't return proxied redirects to the client | ||
| 5 | |||
| 6 | CVE: CVE-2020-8559 | ||
| 7 | Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16] | ||
| 8 | Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com> | ||
| 9 | --- | ||
| 10 | .../k8s.io/apimachinery/pkg/util/net/http.go | 2 +- | ||
| 11 | .../apimachinery/pkg/util/net/http_test.go | 12 ++--- | ||
| 12 | .../pkg/util/proxy/upgradeaware.go | 10 ++++ | ||
| 13 | .../pkg/util/proxy/upgradeaware_test.go | 47 ++++++++++++++++++- | ||
| 14 | 4 files changed, 62 insertions(+), 9 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go | ||
| 17 | index bd79d6c4a09..c24fbc6921c 100644 | ||
| 18 | --- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go | ||
| 19 | +++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go | ||
| 20 | @@ -431,7 +431,7 @@ redirectLoop: | ||
| 21 | |||
| 22 | // Only follow redirects to the same host. Otherwise, propagate the redirect response back. | ||
| 23 | if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() { | ||
| 24 | - break redirectLoop | ||
| 25 | + return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname()) | ||
| 26 | } | ||
| 27 | |||
| 28 | // Reset the connection. | ||
| 29 | diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go | ||
| 30 | index 4e4e317b9a4..142b80f1a84 100644 | ||
| 31 | --- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go | ||
| 32 | +++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go | ||
| 33 | @@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) { | ||
| 34 | redirects: []string{"/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9", "/10"}, | ||
| 35 | expectError: true, | ||
| 36 | }, { | ||
| 37 | - desc: "redirect to different host are prevented", | ||
| 38 | - redirects: []string{"http://example.com/foo"}, | ||
| 39 | - expectedRedirects: 0, | ||
| 40 | + desc: "redirect to different host are prevented", | ||
| 41 | + redirects: []string{"http://example.com/foo"}, | ||
| 42 | + expectError: true, | ||
| 43 | }, { | ||
| 44 | - desc: "multiple redirect to different host forbidden", | ||
| 45 | - redirects: []string{"/1", "/2", "/3", "http://example.com/foo"}, | ||
| 46 | - expectedRedirects: 3, | ||
| 47 | + desc: "multiple redirect to different host forbidden", | ||
| 48 | + redirects: []string{"/1", "/2", "/3", "http://example.com/foo"}, | ||
| 49 | + expectError: true, | ||
| 50 | }, { | ||
| 51 | desc: "redirect to different port is allowed", | ||
| 52 | redirects: []string{"http://HOST/foo"}, | ||
| 53 | diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go | ||
| 54 | index fcdc76a0529..3a02919d135 100644 | ||
| 55 | --- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go | ||
| 56 | +++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go | ||
| 57 | @@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques | ||
| 58 | rawResponse = headerBytes | ||
| 59 | } | ||
| 60 | |||
| 61 | + // If the backend did not upgrade the request, return an error to the client. If the response was | ||
| 62 | + // an error, the error is forwarded directly after the connection is hijacked. Otherwise, just | ||
| 63 | + // return a generic error here. | ||
| 64 | + if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 { | ||
| 65 | + err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode) | ||
| 66 | + klog.Errorf("Proxy upgrade error: %v", err) | ||
| 67 | + h.Responder.Error(w, req, err) | ||
| 68 | + return true | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | // Once the connection is hijacked, the ErrorResponder will no longer work, so | ||
| 72 | // hijacking should be the last step in the upgrade. | ||
| 73 | requestHijacker, ok := w.(http.Hijacker) | ||
| 74 | diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go | ||
| 75 | index 7d14f6534a8..236362373cd 100644 | ||
| 76 | --- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go | ||
| 77 | +++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go | ||
| 78 | @@ -493,7 +493,7 @@ func (r *noErrorsAllowed) Error(w http.ResponseWriter, req *http.Request, err er | ||
| 79 | r.t.Error(err) | ||
| 80 | } | ||
| 81 | |||
| 82 | -func TestProxyUpgradeErrorResponse(t *testing.T) { | ||
| 83 | +func TestProxyUpgradeConnectionErrorResponse(t *testing.T) { | ||
| 84 | var ( | ||
| 85 | responder *fakeResponder | ||
| 86 | expectedErr = errors.New("EXPECTED") | ||
| 87 | @@ -541,7 +541,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) { | ||
| 88 | |||
| 89 | func TestProxyUpgradeErrorResponseTerminates(t *testing.T) { | ||
| 90 | for _, intercept := range []bool{true, false} { | ||
| 91 | - for _, code := range []int{200, 400, 500} { | ||
| 92 | + for _, code := range []int{400, 500} { | ||
| 93 | t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) { | ||
| 94 | // Set up a backend server | ||
| 95 | backend := http.NewServeMux() | ||
| 96 | @@ -601,6 +601,49 @@ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) { | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | +func TestProxyUpgradeErrorResponse(t *testing.T) { | ||
| 101 | + for _, intercept := range []bool{true, false} { | ||
| 102 | + for _, code := range []int{200, 300, 302, 307} { | ||
| 103 | + t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) { | ||
| 104 | + // Set up a backend server | ||
| 105 | + backend := http.NewServeMux() | ||
| 106 | + backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| 107 | + http.Redirect(w, r, "https://example.com/there", code) | ||
| 108 | + })) | ||
| 109 | + backendServer := httptest.NewServer(backend) | ||
| 110 | + defer backendServer.Close() | ||
| 111 | + backendServerURL, _ := url.Parse(backendServer.URL) | ||
| 112 | + backendServerURL.Path = "/hello" | ||
| 113 | + | ||
| 114 | + // Set up a proxy pointing to a specific path on the backend | ||
| 115 | + proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t}) | ||
| 116 | + proxyHandler.InterceptRedirects = intercept | ||
| 117 | + proxyHandler.RequireSameHostRedirects = true | ||
| 118 | + proxy := httptest.NewServer(proxyHandler) | ||
| 119 | + defer proxy.Close() | ||
| 120 | + proxyURL, _ := url.Parse(proxy.URL) | ||
| 121 | + | ||
| 122 | + conn, err := net.Dial("tcp", proxyURL.Host) | ||
| 123 | + require.NoError(t, err) | ||
| 124 | + bufferedReader := bufio.NewReader(conn) | ||
| 125 | + | ||
| 126 | + // Send upgrade request resulting in a non-101 response from the backend | ||
| 127 | + req, _ := http.NewRequest("GET", "/", nil) | ||
| 128 | + req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade) | ||
| 129 | + require.NoError(t, req.Write(conn)) | ||
| 130 | + // Verify we get the correct response and full message body content | ||
| 131 | + resp, err := http.ReadResponse(bufferedReader, nil) | ||
| 132 | + require.NoError(t, err) | ||
| 133 | + assert.Equal(t, fakeStatusCode, resp.StatusCode) | ||
| 134 | + resp.Body.Close() | ||
| 135 | + | ||
| 136 | + // clean up | ||
| 137 | + conn.Close() | ||
| 138 | + }) | ||
| 139 | + } | ||
| 140 | + } | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | func TestDefaultProxyTransport(t *testing.T) { | ||
| 144 | tests := []struct { | ||
| 145 | name, | ||
| 146 | -- | ||
| 147 | 2.17.0 | ||
| 148 | |||
diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb index 941e0ca2..fbe2dd88 100644 --- a/recipes-containers/kubernetes/kubernetes_git.bb +++ b/recipes-containers/kubernetes/kubernetes_git.bb | |||
| @@ -16,6 +16,9 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.16;name=k | |||
| 16 | file://CVE-2020-8552.patch \ | 16 | file://CVE-2020-8552.patch \ |
| 17 | file://CVE-2020-8555.patch \ | 17 | file://CVE-2020-8555.patch \ |
| 18 | file://CVE-2019-11254.patch \ | 18 | file://CVE-2019-11254.patch \ |
| 19 | file://CVE-2020-8557.patch \ | ||
| 20 | file://CVE-2020-8558.patch \ | ||
| 21 | file://CVE-2020-8559.patch \ | ||
| 19 | " | 22 | " |
| 20 | 23 | ||
| 21 | DEPENDS += "rsync-native \ | 24 | DEPENDS += "rsync-native \ |
