Merge pull request #9737 from everpeace/kep-3169-SupplementalGroupsPolicy

KEP-3619: Fine-grained SupplementalGroups control
This commit is contained in:
Mike Brown 2024-06-13 16:59:20 +00:00 committed by GitHub
commit 98ebb3ecff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 1762 additions and 635 deletions

14
go.mod
View File

@ -29,7 +29,7 @@ require (
github.com/containernetworking/cni v1.2.0
github.com/containernetworking/plugins v1.4.1
github.com/coreos/go-systemd/v22 v22.5.0
github.com/davecgh/go-spew v1.1.1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/distribution/reference v0.6.0
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c
github.com/docker/go-metrics v0.0.1
@ -78,7 +78,7 @@ require (
k8s.io/apimachinery v0.30.0
k8s.io/client-go v0.30.0
k8s.io/component-base v0.30.0
k8s.io/cri-api v0.30.0
k8s.io/cri-api v0.31.0-alpha.0.0.20240529224029-3a66d9d86654
k8s.io/klog/v2 v2.120.1
k8s.io/kubelet v0.30.0
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
@ -116,7 +116,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
@ -129,12 +129,12 @@ require (
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect

29
go.sum
View File

@ -78,8 +78,9 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
@ -260,8 +261,9 @@ github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
@ -281,8 +283,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -366,8 +368,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
@ -395,8 +397,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
@ -438,16 +440,17 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
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.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -525,8 +528,8 @@ k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=
k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ=
k8s.io/cri-api v0.30.0 h1:hZqh3vH5JZdqeAyhD9nPXSbT6GDgrtPJkPiIzhWKVhk=
k8s.io/cri-api v0.30.0/go.mod h1://4/umPJSW1ISNSNng4OwjpkvswJOQwU8rnkvO8P+xg=
k8s.io/cri-api v0.31.0-alpha.0.0.20240529224029-3a66d9d86654 h1:REcqRW1lajhGkr+RMfO5mQ7JYp93Fe65js/hJ8R/wq0=
k8s.io/cri-api v0.31.0-alpha.0.0.20240529224029-3a66d9d86654/go.mod h1:8SzLKTnltnWXG9FMIL4SHWcAnnPGssi5viN/SMMMf4k=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=

View File

@ -65,8 +65,23 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon
} else if imageConfig.User != "" {
userstr, _, _ = strings.Cut(imageConfig.User, ":")
}
specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr),
customopts.WithSupplementalGroups(securityContext.GetSupplementalGroups()))
switch securityContext.GetSupplementalGroupsPolicy() {
case runtime.SupplementalGroupsPolicy_Merge:
// merging group defined in /etc/passwd
// and SupplementalGroups defined in security context
specOpts = append(specOpts,
customopts.WithAdditionalGIDs(userstr),
customopts.WithSupplementalGroups(securityContext.GetSupplementalGroups()),
)
case runtime.SupplementalGroupsPolicy_Strict:
// no merging group defined in /etc/passwd
specOpts = append(specOpts,
customopts.WithSupplementalGroups(securityContext.GetSupplementalGroups()),
)
default:
return nil, fmt.Errorf("not implemented in this containerd release: SupplementalGroupsPolicy=%d", securityContext.GetSupplementalGroupsPolicy())
}
asp := securityContext.GetApparmor()
if asp == nil {

View File

@ -1468,7 +1468,7 @@ additional-group-for-root:x:22222:root
expected runtimespec.User
}{
{
desc: "Only SecurityContext was set, SecurityContext defines User",
desc: "[SupplementalGroupsPolicy=Merge(default)] Only SecurityContext was set, SecurityContext defines User",
securityContext: &runtime.LinuxContainerSecurityContext{
RunAsUser: &runtime.Int64Value{Value: 1000},
RunAsGroup: &runtime.Int64Value{Value: 2000},
@ -1477,13 +1477,13 @@ additional-group-for-root:x:22222:root
expected: runtimespec.User{UID: 1000, GID: 2000, AdditionalGids: []uint32{2000, 3333, 11111}},
},
{
desc: "Only imageConfig.User was set, imageConfig.User defines User",
desc: "[SupplementalGroupsPolicy=Merge(default)] Only imageConfig.User was set, imageConfig.User defines User",
imageConfigUser: "1000",
securityContext: nil,
expected: runtimespec.User{UID: 1000, GID: 1000, AdditionalGids: []uint32{1000, 11111}},
},
{
desc: "Both SecurityContext and ImageConfig.User was set, SecurityContext defines User",
desc: "[SupplementalGroupsPolicy=Merge(default)] Both SecurityContext and ImageConfig.User were set, SecurityContext defines User",
imageConfigUser: "0",
securityContext: &runtime.LinuxContainerSecurityContext{
RunAsUser: &runtime.Int64Value{Value: 1000},
@ -1493,9 +1493,38 @@ additional-group-for-root:x:22222:root
expected: runtimespec.User{UID: 1000, GID: 2000, AdditionalGids: []uint32{2000, 3333, 11111}},
},
{
desc: "No SecurityContext nor ImageConfig.User were set, runtime default defines User",
desc: "[SupplementalGroupsPolicy=Merge(default)] No SecurityContext nor ImageConfig.User were set, runtime default defines User",
expected: runtimespec.User{UID: 0, GID: 0, AdditionalGids: []uint32{0, 22222}},
},
{
desc: "[SupplementalGroupsPolicy=Strict] Only SecurityContext was set, SecurityContext defines User",
securityContext: &runtime.LinuxContainerSecurityContext{
RunAsUser: &runtime.Int64Value{Value: 1000},
RunAsGroup: &runtime.Int64Value{Value: 2000},
SupplementalGroups: []int64{3333},
SupplementalGroupsPolicy: runtime.SupplementalGroupsPolicy_Strict,
},
expected: runtimespec.User{UID: 1000, GID: 2000, AdditionalGids: []uint32{2000, 3333}},
},
{
desc: "[SupplementalGroupsPolicy=Strict] Only imageConfig.User was set, imageConfig.User defines User",
imageConfigUser: "1000",
securityContext: &runtime.LinuxContainerSecurityContext{
SupplementalGroupsPolicy: runtime.SupplementalGroupsPolicy_Strict,
},
expected: runtimespec.User{UID: 1000, GID: 1000, AdditionalGids: []uint32{1000}},
},
{
desc: "[SupplementalGroupsPolicy=Strict] Both SecurityContext and ImageConfig.User were set, SecurityContext defines User",
imageConfigUser: "0",
securityContext: &runtime.LinuxContainerSecurityContext{
RunAsUser: &runtime.Int64Value{Value: 1000},
RunAsGroup: &runtime.Int64Value{Value: 2000},
SupplementalGroups: []int64{3333},
SupplementalGroupsPolicy: runtime.SupplementalGroupsPolicy_Strict,
},
expected: runtimespec.User{UID: 1000, GID: 2000, AdditionalGids: []uint32{2000, 3333}},
},
} {
test := test
t.Run(test.desc, func(t *testing.T) {

View File

@ -24,6 +24,7 @@ import (
containerstore "github.com/containerd/containerd/v2/internal/cri/store/container"
"github.com/containerd/containerd/v2/internal/cri/util"
"github.com/containerd/errdefs"
"github.com/containerd/log"
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
@ -60,7 +61,10 @@ func (c *criService) ContainerStatus(ctx context.Context, r *runtime.ContainerSt
imageRef = repoDigests[0]
}
}
status := toCRIContainerStatus(container, spec, imageRef)
status, err := toCRIContainerStatus(ctx, container, spec, imageRef)
if err != nil {
return nil, fmt.Errorf("failed to get ContainerStatus: %w", err)
}
if status.GetCreatedAt() == 0 {
// CRI doesn't allow CreatedAt == 0.
info, err := container.Container.Info(ctx)
@ -82,7 +86,7 @@ func (c *criService) ContainerStatus(ctx context.Context, r *runtime.ContainerSt
}
// toCRIContainerStatus converts internal container object to CRI container status.
func toCRIContainerStatus(container containerstore.Container, spec *runtime.ImageSpec, imageRef string) *runtime.ContainerStatus {
func toCRIContainerStatus(ctx context.Context, container containerstore.Container, spec *runtime.ImageSpec, imageRef string) (*runtime.ContainerStatus, error) {
meta := container.Metadata
status := container.Status.Get()
reason := status.Reason
@ -104,6 +108,12 @@ func toCRIContainerStatus(container containerstore.Container, spec *runtime.Imag
st, ft = status.StartedAt, status.FinishedAt
}
runtimeUser, err := toCRIContainerUser(ctx, container)
if err != nil {
log.G(ctx).WithField("Id", meta.ID).WithError(err).Debug("failed to get ContainerUser. returning an empty ContainerUser")
runtimeUser = &runtime.ContainerUser{}
}
return &runtime.ContainerStatus{
Id: meta.ID,
Metadata: meta.Config.GetMetadata(),
@ -121,7 +131,8 @@ func toCRIContainerStatus(container containerstore.Container, spec *runtime.Imag
Mounts: meta.Config.GetMounts(),
LogPath: meta.LogPath,
Resources: status.Resources,
}
User: runtimeUser,
}, nil
}
// ContainerInfo is extra information for a container.

View File

@ -0,0 +1,54 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package server
import (
"context"
"errors"
"fmt"
containerstore "github.com/containerd/containerd/v2/internal/cri/store/container"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
)
func toCRIContainerUser(ctx context.Context, container containerstore.Container) (*runtime.ContainerUser, error) {
if container.Container == nil {
return nil, errors.New("container must not be nil")
}
runtimeSpec, err := container.Container.Spec(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get container runtime spec: %w", err)
}
if runtimeSpec.Process == nil {
return &runtime.ContainerUser{}, nil
}
user := runtimeSpec.Process.User
var supplementalGroups []int64
for _, gid := range user.AdditionalGids {
supplementalGroups = append(supplementalGroups, int64(gid))
}
return &runtime.ContainerUser{
Linux: &runtime.LinuxContainerUser{
Uid: int64(user.UID),
Gid: int64(user.GID),
SupplementalGroups: supplementalGroups,
},
}, nil
}

View File

@ -0,0 +1,125 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package server
import (
"context"
"errors"
"fmt"
"testing"
containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/internal/cri/store/container"
specs "github.com/opencontainers/runtime-spec/specs-go"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestToCRIContainerUser(t *testing.T) {
fakeErrorOnSpec := errors.New("error")
testCases := []struct {
name string
container containerd.Container
expected *runtime.ContainerUser
expectErr bool
expectedErr error
}{
{
name: "container is nil",
container: nil,
expectErr: true,
expectedErr: errors.New("container must not be nil"),
},
{
name: "Spec() returns error",
container: &fakeSpecOnlyContainer{
t: t,
errOnSpec: fakeErrorOnSpec,
},
expectErr: true,
expectedErr: fmt.Errorf("failed to get container runtime spec: %w", fakeErrorOnSpec),
},
{
name: "no Process",
container: &fakeSpecOnlyContainer{
t: t,
spec: &specs.Spec{},
},
expected: &runtime.ContainerUser{},
},
{
name: "no additionalGids",
container: &fakeSpecOnlyContainer{
t: t,
spec: &specs.Spec{
Process: &specs.Process{
User: specs.User{
UID: 0,
GID: 0,
},
},
},
},
expected: &runtime.ContainerUser{
Linux: &runtime.LinuxContainerUser{
Uid: 0,
Gid: 0,
},
},
},
{
name: "with additionalGids",
container: &fakeSpecOnlyContainer{
t: t,
spec: &specs.Spec{
Process: &specs.Process{
User: specs.User{
UID: 0,
GID: 0,
AdditionalGids: []uint32{0, 1234},
},
},
},
},
expected: &runtime.ContainerUser{
Linux: &runtime.LinuxContainerUser{
Uid: 0,
Gid: 0,
SupplementalGroups: []int64{0, 1234},
},
},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
got, err := toCRIContainerUser(context.Background(), container.Container{
Container: testCase.container,
})
if testCase.expectErr {
require.Nil(t, got)
require.Error(t, err)
assert.Equal(t, testCase.expectedErr, err)
} else {
require.NoError(t, err)
assert.Equal(t, testCase.expected, got)
}
})
}
}

View File

@ -0,0 +1,30 @@
//go:build !windows && !linux
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package server
import (
"context"
containerstore "github.com/containerd/containerd/v2/internal/cri/store/container"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
)
func toCRIContainerUser(ctx context.Context, container containerstore.Container) (*runtime.ContainerUser, error) {
return &runtime.ContainerUser{}, nil
}

View File

@ -22,8 +22,13 @@ import (
"testing"
"time"
containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/core/containers"
criconfig "github.com/containerd/containerd/v2/internal/cri/config"
snapshotstore "github.com/containerd/containerd/v2/internal/cri/store/snapshot"
"github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/typeurl/v2"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/assert"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
@ -31,7 +36,7 @@ import (
imagestore "github.com/containerd/containerd/v2/internal/cri/store/image"
)
func getContainerStatusTestData() (*containerstore.Metadata, *containerstore.Status,
func getContainerStatusTestData(t *testing.T) (*containerstore.Metadata, containerd.Container, *containerstore.Status,
*imagestore.Image, *runtime.ContainerStatus) {
imageID := "sha256:1123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
testID := "test-id"
@ -70,6 +75,9 @@ func getContainerStatusTestData() (*containerstore.Metadata, *containerstore.Sta
"gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
},
}
container := &fakeSpecOnlyContainer{t: t, spec: &specs.Spec{}}
expected := &runtime.ContainerStatus{
Id: testID,
Metadata: config.GetMetadata(),
@ -82,9 +90,10 @@ func getContainerStatusTestData() (*containerstore.Metadata, *containerstore.Sta
Annotations: config.GetAnnotations(),
Mounts: config.GetMounts(),
LogPath: "test-log-path",
User: &runtime.ContainerUser{},
}
return metadata, status, image, expected
return metadata, container, status, image, expected
}
func TestToCRIContainerStatus(t *testing.T) {
@ -139,7 +148,7 @@ func TestToCRIContainerStatus(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
metadata, status, _, expected := getContainerStatusTestData()
metadata, ctnr, status, _, expected := getContainerStatusTestData(t)
// Update status with test case.
status.StartedAt = test.startedAt
status.FinishedAt = test.finishedAt
@ -149,6 +158,7 @@ func TestToCRIContainerStatus(t *testing.T) {
container, err := containerstore.NewContainer(
*metadata,
containerstore.WithFakeStatus(*status),
containerstore.WithContainer(ctnr),
)
assert.NoError(t, err)
// Set expectation based on test case.
@ -158,9 +168,11 @@ func TestToCRIContainerStatus(t *testing.T) {
expected.ExitCode = test.exitCode
expected.Message = test.message
patchExceptedWithState(expected, test.expectedState)
containerStatus := toCRIContainerStatus(container,
containerStatus, err := toCRIContainerStatus(context.Background(),
container,
expected.Image,
expected.ImageRef)
assert.Nil(t, err)
assert.Equal(t, expected, containerStatus, test.desc)
})
}
@ -168,7 +180,7 @@ func TestToCRIContainerStatus(t *testing.T) {
// TODO(mikebrow): add a fake containerd container.Container.Spec client api so we can test verbose is true option
func TestToCRIContainerInfo(t *testing.T) {
metadata, status, _, _ := getContainerStatusTestData()
metadata, _, status, _, _ := getContainerStatusTestData(t)
container, err := containerstore.NewContainer(
*metadata,
containerstore.WithFakeStatus(*status),
@ -231,7 +243,7 @@ func TestContainerStatus(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
c := newTestCRIService()
metadata, status, image, expected := getContainerStatusTestData()
metadata, ctnr, status, image, expected := getContainerStatusTestData(t)
// Update status with test case.
status.StartedAt = test.startedAt
status.FinishedAt = test.finishedAt
@ -239,6 +251,7 @@ func TestContainerStatus(t *testing.T) {
container, err := containerstore.NewContainer(
*metadata,
containerstore.WithFakeStatus(*status),
containerstore.WithContainer(ctnr),
)
assert.NoError(t, err)
if test.exist {
@ -302,3 +315,85 @@ func patchExceptedWithState(expected *runtime.ContainerStatus, state runtime.Con
expected.FinishedAt = 0
}
}
var _ containerd.Container = &fakeSpecOnlyContainer{}
type fakeSpecOnlyContainer struct {
t *testing.T
spec *specs.Spec
errOnSpec error
}
// Spec implements client.Container.
func (c *fakeSpecOnlyContainer) Spec(context.Context) (*specs.Spec, error) {
if c.errOnSpec != nil {
return nil, c.errOnSpec
}
return c.spec, nil
}
// Checkpoint implements client.Container.
func (c *fakeSpecOnlyContainer) Checkpoint(context.Context, string, ...containerd.CheckpointOpts) (containerd.Image, error) {
c.t.Error("fakeSpecOnlyContainer.Checkpoint: not implemented")
return nil, errors.New("not implemented")
}
// Delete implements client.Container.
func (c *fakeSpecOnlyContainer) Delete(context.Context, ...containerd.DeleteOpts) error {
c.t.Error("fakeSpecOnlyContainer.Delete: not implemented")
return errors.New("not implemented")
}
// Extensions implements client.Container.
func (c *fakeSpecOnlyContainer) Extensions(context.Context) (map[string]typeurl.Any, error) {
c.t.Error("fakeSpecOnlyContainer.Extensions: not implemented")
return nil, errors.New("not implemented")
}
// ID implements client.Container.
func (c *fakeSpecOnlyContainer) ID() string {
c.t.Error("fakeSpecOnlyContainer.ID: not implemented")
return "" // not implemented
}
// Image implements client.Container.
func (c *fakeSpecOnlyContainer) Image(context.Context) (containerd.Image, error) {
c.t.Error("fakeSpecOnlyContainer.Image: not implemented")
return nil, errors.New("not implemented")
}
// Info implements client.Container.
func (c *fakeSpecOnlyContainer) Info(context.Context, ...containerd.InfoOpts) (containers.Container, error) {
c.t.Error("fakeSpecOnlyContainer.Info: not implemented")
return containers.Container{}, errors.New("not implemented")
}
// Labels implements client.Container.
func (c *fakeSpecOnlyContainer) Labels(context.Context) (map[string]string, error) {
c.t.Error("fakeSpecOnlyContainer.Labels: not implemented")
return nil, errors.New("not implemented")
}
// NewTask implements client.Container.
func (c *fakeSpecOnlyContainer) NewTask(context.Context, cio.Creator, ...containerd.NewTaskOpts) (containerd.Task, error) {
c.t.Error("fakeSpecOnlyContainer.NewTask: not implemented")
return nil, errors.New("not implemented")
}
// SetLabels implements client.Container.
func (c *fakeSpecOnlyContainer) SetLabels(context.Context, map[string]string) (map[string]string, error) {
c.t.Error("fakeSpecOnlyContainer.SetLabels: not implemented")
return nil, errors.New("not implemented")
}
// Task implements client.Container.
func (c *fakeSpecOnlyContainer) Task(context.Context, cio.Attach) (containerd.Task, error) {
c.t.Error("fakeSpecOnlyContainer.Task: not implemented")
return nil, errors.New("not implemented")
}
// Update implements client.Container.
func (c *fakeSpecOnlyContainer) Update(context.Context, ...containerd.UpdateContainerOpts) error {
c.t.Error("fakeSpecOnlyContainer.Update: not implemented")
return errors.New("not implemented")
}

View File

@ -0,0 +1,28 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package server
import (
"context"
containerstore "github.com/containerd/containerd/v2/internal/cri/store/container"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
)
func toCRIContainerUser(ctx context.Context, container containerstore.Container) (*runtime.ContainerUser, error) {
return &runtime.ContainerUser{}, nil
}

View File

@ -104,7 +104,7 @@ tokenization, and tokenization and tree construction stages of the WHATWG HTML
parsing specification respectively. While the tokenizer parses and normalizes
individual HTML tokens, only the parser constructs the DOM tree from the
tokenized HTML, as described in the tree construction stage of the
specification, dynamically modifying or extending the docuemnt's DOM tree.
specification, dynamically modifying or extending the document's DOM tree.
If your use case requires semantically well-formed HTML documents, as defined by
the WHATWG specification, the parser should be used rather than the tokenizer.

View File

@ -12,7 +12,7 @@ import (
"golang.org/x/net/idna"
)
var isTokenTable = [127]bool{
var isTokenTable = [256]bool{
'!': true,
'#': true,
'$': true,
@ -93,12 +93,7 @@ var isTokenTable = [127]bool{
}
func IsTokenRune(r rune) bool {
i := int(r)
return i < len(isTokenTable) && isTokenTable[i]
}
func isNotToken(r rune) bool {
return !IsTokenRune(r)
return r < utf8.RuneSelf && isTokenTable[byte(r)]
}
// HeaderValuesContainsToken reports whether any string in values
@ -202,8 +197,8 @@ func ValidHeaderFieldName(v string) bool {
if len(v) == 0 {
return false
}
for _, r := range v {
if !IsTokenRune(r) {
for i := 0; i < len(v); i++ {
if !isTokenTable[v[i]] {
return false
}
}

View File

@ -490,6 +490,9 @@ func terminalReadFrameError(err error) bool {
// returned error is ErrFrameTooLarge. Other errors may be of type
// ConnectionError, StreamError, or anything else from the underlying
// reader.
//
// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
// indicates the stream responsible for the error.
func (fr *Framer) ReadFrame() (Frame, error) {
fr.errDetail = nil
if fr.lastFrame != nil {
@ -1521,7 +1524,7 @@ func (fr *Framer) maxHeaderStringLen() int {
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
// merge them into the provided hf and returns a MetaHeadersFrame
// with the decoded hpack values.
func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
func (fr *Framer) readMetaFrame(hf *HeadersFrame) (Frame, error) {
if fr.AllowIllegalReads {
return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
}
@ -1592,7 +1595,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
}
// It would be nice to send a RST_STREAM before sending the GOAWAY,
// but the structure of the server's frame writer makes this difficult.
return nil, ConnectionError(ErrCodeProtocol)
return mh, ConnectionError(ErrCodeProtocol)
}
// Also close the connection after any CONTINUATION frame following an
@ -1604,11 +1607,11 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
}
// It would be nice to send a RST_STREAM before sending the GOAWAY,
// but the structure of the server's frame writer makes this difficult.
return nil, ConnectionError(ErrCodeProtocol)
return mh, ConnectionError(ErrCodeProtocol)
}
if _, err := hdec.Write(frag); err != nil {
return nil, ConnectionError(ErrCodeCompression)
return mh, ConnectionError(ErrCodeCompression)
}
if hc.HeadersEnded() {
@ -1625,7 +1628,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
mh.HeadersFrame.invalidate()
if err := hdec.Close(); err != nil {
return nil, ConnectionError(ErrCodeCompression)
return mh, ConnectionError(ErrCodeCompression)
}
if invalid != nil {
fr.errDetail = invalid

View File

@ -732,11 +732,7 @@ func isClosedConnError(err error) bool {
return false
}
// TODO: remove this string search and be more like the Windows
// case below. That might involve modifying the standard library
// to return better error types.
str := err.Error()
if strings.Contains(str, "use of closed network connection") {
if errors.Is(err, net.ErrClosed) {
return true
}
@ -1482,6 +1478,11 @@ func (sc *serverConn) processFrameFromReader(res readFrameResult) bool {
sc.goAway(ErrCodeFlowControl)
return true
case ConnectionError:
if res.f != nil {
if id := res.f.Header().StreamID; id > sc.maxClientStreamID {
sc.maxClientStreamID = id
}
}
sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)
sc.goAway(ErrCode(ev))
return true // goAway will handle shutdown

View File

@ -936,7 +936,20 @@ func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
}
last := f.LastStreamID
for streamID, cs := range cc.streams {
if streamID > last {
if streamID <= last {
// The server's GOAWAY indicates that it received this stream.
// It will either finish processing it, or close the connection
// without doing so. Either way, leave the stream alone for now.
continue
}
if streamID == 1 && cc.goAway.ErrCode != ErrCodeNo {
// Don't retry the first stream on a connection if we get a non-NO error.
// If the server is sending an error on a new connection,
// retrying the request on a new one probably isn't going to work.
cs.abortStreamLocked(fmt.Errorf("http2: Transport received GOAWAY from server ErrCode:%v", cc.goAway.ErrCode))
} else {
// Aborting the stream with errClentConnGotGoAway indicates that
// the request should be retried on a new connection.
cs.abortStreamLocked(errClientConnGotGoAway)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -321,6 +321,20 @@ message NamespaceOption {
UserNamespace userns_options = 5;
}
// SupplementalGroupsPolicy defines how supplemental groups
// of the first container processes are calculated.
enum SupplementalGroupsPolicy {
// Merge means that the container's provided SupplementalGroups
// and FsGroup (specified in SecurityContext) will be merged with
// the primary user's groups as defined in the container image
// (in /etc/group).
Merge = 0;
// Strict means that the container's provided SupplementalGroups
// and FsGroup (specified in SecurityContext) will be used instead of
// any groups defined in the container image.
Strict = 1;
}
// Int64Value is the wrapper of int64.
message Int64Value {
// The value.
@ -345,13 +359,14 @@ message LinuxSandboxSecurityContext {
Int64Value run_as_group = 8;
// If set, the root filesystem of the sandbox is read-only.
bool readonly_rootfs = 4;
// List of groups applied to the first process run in the sandbox, in
// addition to the sandbox's primary GID, and group memberships defined
// in the container image for the sandbox's primary UID of the container process.
// If the list is empty, no additional groups are added to any container.
// Note that group memberships defined in the container image for the sandbox's primary UID
// of the container process are still effective, even if they are not included in this list.
// List of groups applied to the first process run in each container.
// supplemental_groups_policy can control how groups will be calculated.
repeated int64 supplemental_groups = 5;
// supplemental_groups_policy defines how supplemental groups of the first
// container processes are calculated.
// Valid values are "Merge" and "Strict".
// If not specified, "Merge" is used.
SupplementalGroupsPolicy supplemental_groups_policy = 11;
// Indicates whether the sandbox will be asked to run a privileged
// container. If a privileged container is to be executed within it, this
// MUST be true.
@ -905,13 +920,14 @@ message LinuxContainerSecurityContext {
string run_as_username = 6;
// If set, the root filesystem of the container is read-only.
bool readonly_rootfs = 7;
// List of groups applied to the first process run in the container, in
// addition to the container's primary GID, and group memberships defined
// in the container image for the container's primary UID of the container process.
// If the list is empty, no additional groups are added to any container.
// Note that group memberships defined in the container image for the container's primary UID
// of the container process are still effective, even if they are not included in this list.
// List of groups applied to the first process run in each container.
// supplemental_groups_policy can control how groups will be calculated.
repeated int64 supplemental_groups = 8;
// supplemental_groups_policy defines how supplemental groups of the first
// container processes are calculated.
// Valid values are "Merge" and "Strict".
// If not specified, "Merge" is used.
SupplementalGroupsPolicy supplemental_groups_policy = 17;
// no_new_privs defines if the flag for no_new_privs should be set on the
// container.
bool no_new_privs = 11;
@ -950,6 +966,15 @@ message LinuxContainerConfig {
LinuxContainerSecurityContext security_context = 2;
}
message LinuxContainerUser {
// uid is the primary uid initially attached to the first process in the container
int64 uid = 1;
// gid is the primary gid initially attached to the first process in the container
int64 gid = 2;
// supplemental_groups are the supplemental groups initially attached to the first process in the container
repeated int64 supplemental_groups = 3;
}
// WindowsNamespaceOption provides options for Windows namespaces.
message WindowsNamespaceOption {
// Network namespace for this container/sandbox.
@ -1286,6 +1311,8 @@ message ContainerStatus {
// misusage, we now introduce the image_id field, which should always refer
// to a unique image identifier on the node.
string image_id = 17;
// User identities initially attached to the container
ContainerUser user = 18;
}
message ContainerStatusResponse {
@ -1306,6 +1333,17 @@ message ContainerResources {
WindowsContainerResources windows = 2;
}
message ContainerUser {
// User identities initially attached to first process in the Linux container.
// Note that the actual running identity can be changed if the process has enough privilege to do so.
LinuxContainerUser linux = 1;
// User identities initially attached to first process in the Windows container
// This is just reserved for future use.
// WindowsContainerUser windows = 2;
}
message UpdateContainerResourcesRequest {
// ID of the container to update.
string container_id = 1;

14
vendor/modules.txt vendored
View File

@ -231,7 +231,7 @@ github.com/coreos/go-systemd/v22/dbus
# github.com/cpuguy83/go-md2man/v2 v2.0.4
## explicit; go 1.11
github.com/cpuguy83/go-md2man/v2/md2man
# github.com/davecgh/go-spew v1.1.1
# github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
## explicit
github.com/davecgh/go-spew/spew
# github.com/distribution/reference v0.6.0
@ -412,7 +412,7 @@ github.com/pelletier/go-toml/v2/unstable
# github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0
# github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
## explicit
github.com/pmezard/go-difflib/difflib
# github.com/prometheus/client_golang v1.19.1
@ -545,7 +545,7 @@ go.opentelemetry.io/proto/otlp/collector/trace/v1
go.opentelemetry.io/proto/otlp/common/v1
go.opentelemetry.io/proto/otlp/resource/v1
go.opentelemetry.io/proto/otlp/trace/v1
# golang.org/x/crypto v0.22.0
# golang.org/x/crypto v0.23.0
## explicit; go 1.18
golang.org/x/crypto/cast5
golang.org/x/crypto/openpgp
@ -563,7 +563,7 @@ golang.org/x/exp/slices
# golang.org/x/mod v0.18.0
## explicit; go 1.18
golang.org/x/mod/semver
# golang.org/x/net v0.24.0
# golang.org/x/net v0.25.0
## explicit; go 1.18
golang.org/x/net/bpf
golang.org/x/net/html
@ -595,10 +595,10 @@ golang.org/x/sys/windows/registry
golang.org/x/sys/windows/svc
golang.org/x/sys/windows/svc/debug
golang.org/x/sys/windows/svc/mgr
# golang.org/x/term v0.19.0
# golang.org/x/term v0.20.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/text v0.14.0
# golang.org/x/text v0.15.0
## explicit; go 1.18
golang.org/x/text/secure/bidirule
golang.org/x/text/transform
@ -812,7 +812,7 @@ k8s.io/client-go/util/workqueue
# k8s.io/component-base v0.30.0
## explicit; go 1.22.0
k8s.io/component-base/logs/logreduction
# k8s.io/cri-api v0.30.0
# k8s.io/cri-api v0.31.0-alpha.0.0.20240529224029-3a66d9d86654
## explicit; go 1.22.0
k8s.io/cri-api/pkg/apis/runtime/v1
k8s.io/cri-api/pkg/errors