From 9b11293c1f362c335dbbf4bd5210129f2a50c5e3 Mon Sep 17 00:00:00 2001 From: cchen-vertica <136734971+cchen-vertica@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:44:21 -0600 Subject: [PATCH] Fixed unsandbox issue and CVE-2024-45337 (#1005) This PR added a sandbox initiator to unsandbox hosts option for fixing unsandboxing issue, and updated golang.org/x/crypto from 0.21.0 to 0.31.0 to fix CVE-2024-45337. --- .../unreleased/Security-20241213-145350.yaml | 5 ++++ go.mod | 10 ++++---- go.sum | 20 ++++++++-------- .../sandbox/unsandboxsubcluster_reconciler.go | 6 +++++ pkg/podfacts/podfacts.go | 11 +++++++++ pkg/podfacts/podfacts_test.go | 24 +++++++++++++++++++ pkg/vadmin/opts/unsandboxsc/opts.go | 7 ++++++ pkg/vadmin/unsandbox_sc_vc.go | 5 +++- 8 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 changes/unreleased/Security-20241213-145350.yaml diff --git a/changes/unreleased/Security-20241213-145350.yaml b/changes/unreleased/Security-20241213-145350.yaml new file mode 100644 index 000000000..4a8ac0311 --- /dev/null +++ b/changes/unreleased/Security-20241213-145350.yaml @@ -0,0 +1,5 @@ +kind: Security +body: Fix for CVE-2024-45337 +time: 2024-12-13T14:53:50.849642169-05:00 +custom: + Issue: "1005" diff --git a/go.mod b/go.mod index ea92cc47a..1c15bb75e 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/vertica/vertica-sql-go v1.1.1 go.uber.org/zap v1.25.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 - golang.org/x/text v0.14.0 + golang.org/x/text v0.21.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.26.2 @@ -75,12 +75,12 @@ require ( github.com/theckman/yacspin v0.13.12 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.10.0 // indirect - golang.org/x/crypto v0.21.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect golang.org/x/time v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/api v0.153.0 // indirect diff --git a/go.sum b/go.sum index 8cf37670d..8a72ab774 100644 --- a/go.sum +++ b/go.sum @@ -362,8 +362,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -453,8 +453,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -497,12 +497,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -510,8 +510,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/pkg/controllers/sandbox/unsandboxsubcluster_reconciler.go b/pkg/controllers/sandbox/unsandboxsubcluster_reconciler.go index 7db9bb78e..12a2c8639 100644 --- a/pkg/controllers/sandbox/unsandboxsubcluster_reconciler.go +++ b/pkg/controllers/sandbox/unsandboxsubcluster_reconciler.go @@ -251,10 +251,16 @@ func (r *UnsandboxSubclusterReconciler) unsandboxSubcluster(ctx context.Context, return err } + sbInitiator, ok := r.OriginalPFacts.GetInitiatorIPInSB(r.ConfigMap.Data[vapi.SandboxNameKey], scName) + if !ok { + r.Log.Info("Cannot find initiator in sandbox. The sandbox may only have one subcluster", + "sandboxName", r.ConfigMap.Data[vapi.SandboxNameKey]) + } r.SRec.Eventf(r.Vdb, corev1.EventTypeNormal, events.UnsandboxSubclusterStart, "Starting unsandbox subcluster %q", scName) err = r.Dispatcher.UnsandboxSubcluster(ctx, unsandboxsc.WithInitiator(r.InitiatorIP), + unsandboxsc.WithSBInitiator(sbInitiator), unsandboxsc.WithSubcluster(scName), // vclusterOps needs correct node names and addresses to do re-ip unsandboxsc.WithNodeNameAddressMap(nodeNameAddressMap), diff --git a/pkg/podfacts/podfacts.go b/pkg/podfacts/podfacts.go index 3d8e7b583..4c9f3d09c 100644 --- a/pkg/podfacts/podfacts.go +++ b/pkg/podfacts/podfacts.go @@ -1714,3 +1714,14 @@ func (p *PodFacts) FindSecondarySubclustersWithDifferentImage(vdb *vapi.VerticaD } return scs, priScImage } + +// GetInitiatorIPInSB returns the first primary up pod IP in the given sandbox but not in the given subcluster +func (p *PodFacts) GetInitiatorIPInSB(sbName, excludeSCName string) (string, bool) { + initiator, ok := p.FindFirstPodSorted(func(v *PodFact) bool { + return v.isPrimary && v.upNode && v.sandbox == sbName && v.subclusterName != excludeSCName + }) + if initiator == nil { + return "", false + } + return initiator.podIP, ok +} diff --git a/pkg/podfacts/podfacts_test.go b/pkg/podfacts/podfacts_test.go index b28c84c68..3f2869fec 100644 --- a/pkg/podfacts/podfacts_test.go +++ b/pkg/podfacts/podfacts_test.go @@ -397,6 +397,30 @@ var _ = Describe("podfacts", func() { result = pf.QuorumCheckForRestartCluster(true) Expect(result).Should(BeFalse()) }) + + It("should find sandbox initiator correctly", func() { + pf := MakePodFacts(vdbRec, &cmds.FakePodRunner{}, logger, TestPassword) + pf.Detail[types.NamespacedName{Name: "p1"}] = &PodFact{ + isPrimary: false, subclusterName: "sc1", upNode: true, sandbox: "sand1", podIP: "1.1.1.1", + } + pf.Detail[types.NamespacedName{Name: "p2"}] = &PodFact{ + isPrimary: true, subclusterName: "sc2", upNode: true, sandbox: "sand1", podIP: "2.2.2.2", + } + pf.Detail[types.NamespacedName{Name: "p3"}] = &PodFact{ + isPrimary: true, subclusterName: "sc3", upNode: true, sandbox: "sand1", podIP: "3.3.3.3", + } + pf.Detail[types.NamespacedName{Name: "p4"}] = &PodFact{ + isPrimary: true, subclusterName: "sc4", upNode: true, sandbox: "sand2", podIP: "4.4.4.4", + } + // should get a primary up node ip not in sc2 + initiatorIP, ok := pf.GetInitiatorIPInSB("sand1", "sc2") + Expect(initiatorIP).Should(Equal("3.3.3.3")) + Expect(ok).Should(BeTrue()) + // should not get an ip + initiatorIP, ok = pf.GetInitiatorIPInSB("sand2", "sc4") + Expect(initiatorIP).Should(Equal("")) + Expect(ok).Should(BeFalse()) + }) }) func verifyReIP(pf *PodFacts) { diff --git a/pkg/vadmin/opts/unsandboxsc/opts.go b/pkg/vadmin/opts/unsandboxsc/opts.go index 8d3d1676a..e96c67764 100644 --- a/pkg/vadmin/opts/unsandboxsc/opts.go +++ b/pkg/vadmin/opts/unsandboxsc/opts.go @@ -18,6 +18,7 @@ package unsandboxsc // Params holds all of the option for an unsandbox subcluster invocation. type Params struct { InitiatorIP string + SBInitiatorIP string Subcluster string NodeNameAddressMap map[string]string } @@ -37,6 +38,12 @@ func WithInitiator(initiatorIP string) Option { } } +func WithSBInitiator(sbInitiatorIP string) Option { + return func(s *Params) { + s.SBInitiatorIP = sbInitiatorIP + } +} + func WithSubcluster(subcluster string) Option { return func(s *Params) { s.Subcluster = subcluster diff --git a/pkg/vadmin/unsandbox_sc_vc.go b/pkg/vadmin/unsandbox_sc_vc.go index 5c661d012..0d5d51680 100644 --- a/pkg/vadmin/unsandbox_sc_vc.go +++ b/pkg/vadmin/unsandbox_sc_vc.go @@ -57,7 +57,10 @@ func (v *VClusterOps) genUnsandboxSubclusterOptions(s *unsandboxsc.Params, certs opts.DBName = v.VDB.Spec.DBName opts.IsEon = v.VDB.IsEON() opts.RawHosts = append(opts.RawHosts, s.InitiatorIP) - v.Log.Info("Setup unsandbox subcluster options", "hosts", opts.RawHosts[0]) + if s.SBInitiatorIP != "" { + opts.RawHosts = append(opts.RawHosts, s.SBInitiatorIP) + } + v.Log.Info("Setup unsandbox subcluster options", "hosts", opts.RawHosts) opts.IPv6 = net.IsIPv6(s.InitiatorIP) opts.SCName = s.Subcluster