mirror of https://github.com/containers/podman
Vendor in containers/(buildah, common)
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>pull/21880/head
parent
38546de7b6
commit
3abc488c84
|
@ -310,7 +310,9 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
|
|||
pullPolicy = buildahDefine.PullAlways
|
||||
}
|
||||
|
||||
if flags.PullNever || strings.EqualFold(strings.TrimSpace(flags.Pull), "never") {
|
||||
if flags.PullNever ||
|
||||
strings.EqualFold(strings.TrimSpace(flags.Pull), "false") ||
|
||||
strings.EqualFold(strings.TrimSpace(flags.Pull), "never") {
|
||||
pullPolicy = buildahDefine.PullNever
|
||||
}
|
||||
|
||||
|
|
14
go.mod
14
go.mod
|
@ -10,11 +10,11 @@ require (
|
|||
github.com/checkpoint-restore/checkpointctl v1.1.0
|
||||
github.com/checkpoint-restore/go-criu/v7 v7.0.0
|
||||
github.com/containernetworking/plugins v1.4.0
|
||||
github.com/containers/buildah v1.34.1-0.20240201124221-b850c711ff5c
|
||||
github.com/containers/buildah v1.34.1-0.20240229193131-f5d7689ef4cd
|
||||
github.com/containers/common v0.57.1-0.20240229165734-cec09922602e
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/gvisor-tap-vsock v0.7.3
|
||||
github.com/containers/image/v5 v5.29.3-0.20240227090231-5bef5e1e1506
|
||||
github.com/containers/image/v5 v5.29.3-0.20240229213915-cdc68020a24f
|
||||
github.com/containers/libhvee v0.6.1-0.20240225143609-c1bda9d3838c
|
||||
github.com/containers/ocicrypt v1.1.9
|
||||
github.com/containers/psgo v1.9.0
|
||||
|
@ -118,7 +118,7 @@ require (
|
|||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.2 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
|
@ -129,7 +129,7 @@ require (
|
|||
github.com/go-openapi/loads v0.21.2 // indirect
|
||||
github.com/go-openapi/runtime v0.26.0 // indirect
|
||||
github.com/go-openapi/spec v0.20.9 // indirect
|
||||
github.com/go-openapi/strfmt v0.22.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.22.1 // indirect
|
||||
github.com/go-openapi/swag v0.22.9 // indirect
|
||||
github.com/go-openapi/validate v0.22.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
|
@ -141,7 +141,7 @@ require (
|
|||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-containerregistry v0.17.0 // indirect
|
||||
github.com/google/go-containerregistry v0.19.0 // indirect
|
||||
github.com/google/go-intervals v0.0.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
|
@ -188,7 +188,7 @@ require (
|
|||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/sigstore/fulcio v1.4.3 // indirect
|
||||
github.com/sigstore/rekor v1.2.2 // indirect
|
||||
github.com/sigstore/sigstore v1.8.1 // indirect
|
||||
github.com/sigstore/sigstore v1.8.2 // indirect
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
|
||||
github.com/sylabs/sif/v2 v2.15.1 // indirect
|
||||
|
@ -202,7 +202,7 @@ require (
|
|||
github.com/vbatts/tar-split v0.11.5 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
|
||||
|
|
42
go.sum
42
go.sum
|
@ -74,16 +74,16 @@ github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl3
|
|||
github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
|
||||
github.com/containernetworking/plugins v1.4.0 h1:+w22VPYgk7nQHw7KT92lsRmuToHvb7wwSv9iTbXzzic=
|
||||
github.com/containernetworking/plugins v1.4.0/go.mod h1:UYhcOyjefnrQvKvmmyEKsUA+M9Nfn7tqULPpH0Pkcj0=
|
||||
github.com/containers/buildah v1.34.1-0.20240201124221-b850c711ff5c h1:r+1vFyTAoXptJrsPsnOMI3G0jm4+BCfXAcIyuA33lzo=
|
||||
github.com/containers/buildah v1.34.1-0.20240201124221-b850c711ff5c/go.mod h1:Hw4qo2URFpWvZ2tjLstoQMpNC6+gR4PtxQefvV/UKaA=
|
||||
github.com/containers/buildah v1.34.1-0.20240229193131-f5d7689ef4cd h1:4cHNzaywyyJsCAtwUKMZm8r/wqm/WuNC70GfnI3kh18=
|
||||
github.com/containers/buildah v1.34.1-0.20240229193131-f5d7689ef4cd/go.mod h1:3fn5edBIPpIOPJYdnxBdTF7bjnBHhqZwYK5a6ApNdyk=
|
||||
github.com/containers/common v0.57.1-0.20240229165734-cec09922602e h1:TPgCd6bWFyliJxCXEiCI1LnbB3kBUkpx1dw51ngDjWI=
|
||||
github.com/containers/common v0.57.1-0.20240229165734-cec09922602e/go.mod h1:8irlyBcVooYx0F+YmoY7PQPAIgdJvCj17bvL7PqeaxI=
|
||||
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
||||
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||
github.com/containers/gvisor-tap-vsock v0.7.3 h1:yORnf15sP+sLFhxLNLgmB5/lOhldn9dRMHx/tmYtSOQ=
|
||||
github.com/containers/gvisor-tap-vsock v0.7.3/go.mod h1:NI1fLMtKXQZoDrrOeqryGz7x7j/XSFWRmQILva7Fu9c=
|
||||
github.com/containers/image/v5 v5.29.3-0.20240227090231-5bef5e1e1506 h1:Wdkl9fdxXYp2zaiw0GWC7fF8DSqD72B5jhILY0qK/sU=
|
||||
github.com/containers/image/v5 v5.29.3-0.20240227090231-5bef5e1e1506/go.mod h1:2/7sa5zJsx3Gl4v2MHkBrSMxsQePJcx9EDehbxmxlKE=
|
||||
github.com/containers/image/v5 v5.29.3-0.20240229213915-cdc68020a24f h1:DEK6PaY5/B6CYXjtdfAQGCUltHEPaoXvLb+C0PH6HiE=
|
||||
github.com/containers/image/v5 v5.29.3-0.20240229213915-cdc68020a24f/go.mod h1:a48d1rhHBl2zb630MSf20QQo4eIlIQvhZTqTcVJhbpA=
|
||||
github.com/containers/libhvee v0.6.1-0.20240225143609-c1bda9d3838c h1:C80Xw6cDHkx0zMJk/Qkczcz/1OOVEF9+6iHuEZbD47k=
|
||||
github.com/containers/libhvee v0.6.1-0.20240225143609-c1bda9d3838c/go.mod h1:zX7HGsRwCxBOpzc8Jvwq2aEaECsb2q5/l5HqB9n7UPc=
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
|
||||
|
@ -164,8 +164,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
|||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
|
||||
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
|
||||
github.com/go-jose/go-jose/v3 v3.0.2 h1:2Edjn8Nrb44UvTdp84KU0bBPs1cO7noRCybtS3eJEUQ=
|
||||
github.com/go-jose/go-jose/v3 v3.0.2/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
|
@ -202,8 +202,8 @@ github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6
|
|||
github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
|
||||
github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
|
||||
github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
|
||||
github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgAcaI=
|
||||
github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4=
|
||||
github.com/go-openapi/strfmt v0.22.1 h1:5Ky8cybT4576C6Ffc+8gYji/wRXCo6Ozm8RaWjPI6jc=
|
||||
github.com/go-openapi/strfmt v0.22.1/go.mod h1:OfVoytIXJasDkkGvkb1Cceb3BPyMOwk1FgmyyEw7NYg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
|
@ -219,7 +219,7 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74=
|
||||
github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-rod/rod v0.114.5 h1:1x6oqnslwFVuXJbJifgxspJUd3O4ntaGhRLHt+4Er9c=
|
||||
github.com/go-rod/rod v0.114.7 h1:h4pimzSOUnw7Eo41zdJA788XsawzHjJMyzCE3BrBww0=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
|
@ -288,8 +288,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.17.0 h1:5p+zYs/R4VGHkhyvgWurWrpJ2hW4Vv9fQI+GzdcwXLk=
|
||||
github.com/google/go-containerregistry v0.17.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||
github.com/google/go-containerregistry v0.19.0 h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic=
|
||||
github.com/google/go-containerregistry v0.19.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||
github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM=
|
||||
github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
|
@ -519,8 +519,8 @@ github.com/sigstore/fulcio v1.4.3 h1:9JcUCZjjVhRF9fmhVuz6i1RyhCc/EGCD7MOl+iqCJLQ
|
|||
github.com/sigstore/fulcio v1.4.3/go.mod h1:BQPWo7cfxmJwgaHlphUHUpFkp5+YxeJes82oo39m5og=
|
||||
github.com/sigstore/rekor v1.2.2 h1:5JK/zKZvcQpL/jBmHvmFj3YbpDMBQnJQ6ygp8xdF3bY=
|
||||
github.com/sigstore/rekor v1.2.2/go.mod h1:FGnWBGWzeNceJnp0x9eDFd41mI8aQqCjj+Zp0IEs0Qg=
|
||||
github.com/sigstore/sigstore v1.8.1 h1:mAVposMb14oplk2h/bayPmIVdzbq2IhCgy4g6R0ZSjo=
|
||||
github.com/sigstore/sigstore v1.8.1/go.mod h1:02SL1158BSj15bZyOFz7m+/nJzLZfFd9A8ab3Kz7w/E=
|
||||
github.com/sigstore/sigstore v1.8.2 h1:0Ttjcn3V0fVQXlYq7+oHaaHkGFIt3ywm7SF4JTU/l8c=
|
||||
github.com/sigstore/sigstore v1.8.2/go.mod h1:CHVcSyknCcjI4K2ZhS1SI28r0tcQyBlwtALG536x1DY=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
@ -586,10 +586,8 @@ github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZla
|
|||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
|
@ -610,8 +608,8 @@ go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
|||
go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
|
||||
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
|
||||
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
|
||||
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
||||
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
|
@ -636,13 +634,13 @@ golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
|||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
|
||||
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -655,6 +653,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -675,6 +674,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
|
|||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
@ -689,6 +690,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -739,6 +741,8 @@ golang.org/x/sys v0.17.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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
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 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -749,6 +753,7 @@ 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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
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/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
|
@ -768,6 +773,7 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
@ -256,6 +256,9 @@ skip_if_remote "Explicit request in buildah PR 4190 to skip this on remote" \
|
|||
skip_if_rootless "Flakes when run rootless, too. See Buildah PR 4190" \
|
||||
"build: test race in updating image name while performing parallel commits"
|
||||
|
||||
skip_if_remote "--events-backend does not work with podman-remote" \
|
||||
"build test default ulimits"
|
||||
|
||||
###############################################################################
|
||||
# BEGIN tests which are skipped due to actual podman or podman-remote bugs.
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ env:
|
|||
DEBIAN_NAME: "debian-13"
|
||||
|
||||
# Image identifiers
|
||||
IMAGE_SUFFIX: "c20240102t212217z-f39f38d13"
|
||||
IMAGE_SUFFIX: "c20240222t143004z-f39f38d13"
|
||||
FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}"
|
||||
PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}"
|
||||
DEBIAN_CACHE_IMAGE_NAME: "debian-${IMAGE_SUFFIX}"
|
||||
|
@ -221,6 +221,7 @@ integration_task:
|
|||
DISTRO_NV: "${DEBIAN_NAME}"
|
||||
IMAGE_NAME: "${DEBIAN_CACHE_IMAGE_NAME}"
|
||||
STORAGE_DRIVER: 'vfs'
|
||||
CI_DESIRED_RUNTIME: runc
|
||||
# OVERLAY
|
||||
- env:
|
||||
DISTRO_NV: "${FEDORA_NAME}"
|
||||
|
@ -234,6 +235,7 @@ integration_task:
|
|||
DISTRO_NV: "${DEBIAN_NAME}"
|
||||
IMAGE_NAME: "${DEBIAN_CACHE_IMAGE_NAME}"
|
||||
STORAGE_DRIVER: 'overlay'
|
||||
CI_DESIRED_RUNTIME: runc
|
||||
|
||||
gce_instance:
|
||||
image_name: "$IMAGE_NAME"
|
||||
|
@ -323,6 +325,8 @@ in_podman_task:
|
|||
# set of tasks all passed, and allows confirming that based on the status
|
||||
# of this task.
|
||||
success_task:
|
||||
# N/B: The prow merge-bot (tide) is sensitized to this exact name, DO NOT CHANGE IT.
|
||||
# Ref: https://github.com/openshift/release/pull/48909
|
||||
name: "Total Success"
|
||||
alias: success
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ APPARMORTAG := $(shell hack/apparmor_tag.sh)
|
|||
STORAGETAGS := exclude_graphdriver_devicemapper $(shell ./btrfs_tag.sh) $(shell ./btrfs_installed_tag.sh) $(shell ./hack/libsubid_tag.sh)
|
||||
SECURITYTAGS ?= seccomp $(APPARMORTAG)
|
||||
TAGS ?= $(SECURITYTAGS) $(STORAGETAGS) $(shell ./hack/systemd_tag.sh)
|
||||
ifeq ($(shell uname -s),FreeBSD)
|
||||
# FreeBSD needs CNI until netavark is supported
|
||||
TAGS += cni
|
||||
endif
|
||||
BUILDTAGS += $(TAGS)
|
||||
PREFIX := /usr/local
|
||||
BINDIR := $(PREFIX)/bin
|
||||
|
@ -87,7 +91,7 @@ endif
|
|||
buildah: bin/buildah
|
||||
|
||||
ALL_CROSS_TARGETS := $(addprefix bin/buildah.,$(subst /,.,$(shell $(GO) tool dist list)))
|
||||
LINUX_CROSS_TARGETS := $(filter bin/buildah.linux.%,$(ALL_CROSS_TARGETS))
|
||||
LINUX_CROSS_TARGETS := $(filter-out %.loong64,$(filter bin/buildah.linux.%,$(ALL_CROSS_TARGETS)))
|
||||
DARWIN_CROSS_TARGETS := $(filter bin/buildah.darwin.%,$(ALL_CROSS_TARGETS))
|
||||
WINDOWS_CROSS_TARGETS := $(addsuffix .exe,$(filter bin/buildah.windows.%,$(ALL_CROSS_TARGETS)))
|
||||
FREEBSD_CROSS_TARGETS := $(filter bin/buildah.freebsd.%,$(ALL_CROSS_TARGETS))
|
||||
|
@ -196,7 +200,7 @@ test-unit: tests/testreport/testreport
|
|||
$(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" -cover $(RACEFLAGS) ./cmd/buildah -args --root $$tmp/root --runroot $$tmp/runroot --storage-driver vfs --signature-policy $(shell pwd)/tests/policy.json --registries-conf $(shell pwd)/tests/registries.conf
|
||||
|
||||
vendor-in-container:
|
||||
podman run --privileged --rm --env HOME=/root -v `pwd`:/src -w /src docker.io/library/golang:1.20 make vendor
|
||||
podman run --privileged --rm --env HOME=/root -v `pwd`:/src -w /src docker.io/library/golang:1.21 make vendor
|
||||
|
||||
.PHONY: vendor
|
||||
vendor:
|
||||
|
|
|
@ -11,11 +11,11 @@ import (
|
|||
"syscall"
|
||||
|
||||
"github.com/containers/buildah/util"
|
||||
cutil "github.com/containers/common/pkg/util"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/containers/storage/pkg/mount"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -192,11 +192,11 @@ func SetupIntermediateMountNamespace(spec *specs.Spec, bundlePath string) (unmou
|
|||
// Decide if the mount should not be redirected to an intermediate location first.
|
||||
func leaveBindMountAlone(mount specs.Mount) bool {
|
||||
// If we know we shouldn't do a redirection for this mount, skip it.
|
||||
if cutil.StringInSlice(NoBindOption, mount.Options) {
|
||||
if slices.Contains(mount.Options, NoBindOption) {
|
||||
return true
|
||||
}
|
||||
// If we're not bind mounting it in, we don't need to do anything for it.
|
||||
if mount.Type != "bind" && !cutil.StringInSlice("bind", mount.Options) && !cutil.StringInSlice("rbind", mount.Options) {
|
||||
if mount.Type != "bind" && !slices.Contains(mount.Options, "bind") && !slices.Contains(mount.Options, "rbind") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -294,7 +294,7 @@ func UnmountMountpoints(mountpoint string, mountpointsToRemove []string) error {
|
|||
}
|
||||
}
|
||||
// if we're also supposed to remove this thing, do that, too
|
||||
if cutil.StringInSlice(mount.Mountpoint, mountpointsToRemove) {
|
||||
if slices.Contains(mountpointsToRemove, mount.Mountpoint) {
|
||||
if err := os.Remove(mount.Mountpoint); err != nil {
|
||||
return fmt.Errorf("removing %q: %w", mount.Mountpoint, err)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package bind
|
||||
|
||||
import (
|
||||
"github.com/containers/common/pkg/util"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -14,7 +14,7 @@ const (
|
|||
|
||||
func stripNoBindOption(spec *specs.Spec) {
|
||||
for i := range spec.Mounts {
|
||||
if util.StringInSlice(NoBindOption, spec.Mounts[i].Options) {
|
||||
if slices.Contains(spec.Mounts[i].Options, NoBindOption) {
|
||||
prunedOptions := make([]string, 0, len(spec.Mounts[i].Options))
|
||||
for _, option := range spec.Mounts[i].Options {
|
||||
if option != NoBindOption {
|
||||
|
|
|
@ -34,6 +34,8 @@ const (
|
|||
runUsingChrootCommand = "buildah-chroot-runtime"
|
||||
// runUsingChrootExec is a command we use as a key for reexec
|
||||
runUsingChrootExecCommand = "buildah-chroot-exec"
|
||||
// containersConfEnv is an environment variable that we need to pass down except for the command itself
|
||||
containersConfEnv = "CONTAINERS_CONF"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -128,6 +130,9 @@ func RunUsingChroot(spec *specs.Spec, bundlePath, homeDir string, stdin io.Reade
|
|||
cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr
|
||||
cmd.Dir = "/"
|
||||
cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}
|
||||
if _, ok := os.LookupEnv(containersConfEnv); ok {
|
||||
cmd.Env = append(cmd.Env, containersConfEnv+"="+os.Getenv(containersConfEnv))
|
||||
}
|
||||
|
||||
interrupted := make(chan os.Signal, 100)
|
||||
cmd.Hook = func(int) error {
|
||||
|
@ -511,6 +516,9 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io
|
|||
cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr
|
||||
cmd.Dir = "/"
|
||||
cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}
|
||||
if _, ok := os.LookupEnv(containersConfEnv); ok {
|
||||
cmd.Env = append(cmd.Env, containersConfEnv+"="+os.Getenv(containersConfEnv))
|
||||
}
|
||||
if ctty != nil {
|
||||
cmd.Setsid = true
|
||||
cmd.Ctty = ctty
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/containers/buildah/define"
|
||||
"github.com/containers/buildah/docker"
|
||||
internalUtil "github.com/containers/buildah/internal/util"
|
||||
"github.com/containers/common/pkg/util"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/image/v5/transports"
|
||||
|
@ -20,6 +19,7 @@ import (
|
|||
"github.com/containers/storage/pkg/stringid"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// unmarshalConvertedConfig obtains the config blob of img valid for the wantedManifestMIMEType format
|
||||
|
@ -229,10 +229,10 @@ func (b *Builder) OSFeatures() []string {
|
|||
// SetOSFeature adds a feature of the OS which the container, or a container
|
||||
// built using an image built from this container, depends on the OS supplying.
|
||||
func (b *Builder) SetOSFeature(feature string) {
|
||||
if !util.StringInSlice(feature, b.OCIv1.OSFeatures) {
|
||||
if !slices.Contains(b.OCIv1.OSFeatures, feature) {
|
||||
b.OCIv1.OSFeatures = append(b.OCIv1.OSFeatures, feature)
|
||||
}
|
||||
if !util.StringInSlice(feature, b.Docker.OSFeatures) {
|
||||
if !slices.Contains(b.Docker.OSFeatures, feature) {
|
||||
b.Docker.OSFeatures = append(b.Docker.OSFeatures, feature)
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ func (b *Builder) SetOSFeature(feature string) {
|
|||
// container built using an image built from this container, depends on the OS
|
||||
// supplying.
|
||||
func (b *Builder) UnsetOSFeature(feature string) {
|
||||
if util.StringInSlice(feature, b.OCIv1.OSFeatures) {
|
||||
if slices.Contains(b.OCIv1.OSFeatures, feature) {
|
||||
features := make([]string, 0, len(b.OCIv1.OSFeatures))
|
||||
for _, f := range b.OCIv1.OSFeatures {
|
||||
if f != feature {
|
||||
|
@ -250,7 +250,7 @@ func (b *Builder) UnsetOSFeature(feature string) {
|
|||
}
|
||||
b.OCIv1.OSFeatures = features
|
||||
}
|
||||
if util.StringInSlice(feature, b.Docker.OSFeatures) {
|
||||
if slices.Contains(b.Docker.OSFeatures, feature) {
|
||||
features := make([]string, 0, len(b.Docker.OSFeatures))
|
||||
for _, f := range b.Docker.OSFeatures {
|
||||
if f != feature {
|
||||
|
|
|
@ -29,7 +29,7 @@ const (
|
|||
// identify working containers.
|
||||
Package = "buildah"
|
||||
// Version for the Package. Also used by .packit.sh for Packit builds.
|
||||
Version = "1.34.1-dev"
|
||||
Version = "1.35.0-dev"
|
||||
|
||||
// DefaultRuntime if containers.conf fails.
|
||||
DefaultRuntime = "runc"
|
||||
|
@ -54,6 +54,9 @@ const (
|
|||
SNP TeeType = "snp"
|
||||
)
|
||||
|
||||
// DefaultRlimitValue is the value set by default for nofile and nproc
|
||||
const RLimitDefaultValue = uint64(1048576)
|
||||
|
||||
// TeeType is a supported trusted execution environment type.
|
||||
type TeeType string
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
gotypes "go/types"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -36,6 +37,7 @@ import (
|
|||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/openshift/imagebuilder"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
|
@ -493,6 +495,26 @@ func preprocessContainerfileContents(logger *logrus.Logger, containerfile string
|
|||
return &stdoutBuffer, nil
|
||||
}
|
||||
|
||||
// platformIsUnknown checks if the platform value indicates that the
|
||||
// corresponding index entry is suitable for use as a base image
|
||||
func platformIsAcceptable(platform *v1.Platform, logger *logrus.Logger) bool {
|
||||
if platform == nil {
|
||||
logger.Trace("rejecting potential base image with no platform information")
|
||||
return false
|
||||
}
|
||||
if gotypes.SizesFor("gc", platform.Architecture) == nil {
|
||||
// the compiler's never heard of this
|
||||
logger.Tracef("rejecting potential base image architecture %q for which Go has no knowledge of how to do unsafe code", platform.Architecture)
|
||||
return false
|
||||
}
|
||||
if slices.Contains([]string{"", "unknown"}, platform.OS) {
|
||||
// we're hard-wired to reject images with these values
|
||||
logger.Tracef("rejecting potential base image for which the OS value is always-rejected value %q", platform.OS)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// platformsForBaseImages resolves the names of base images from the
|
||||
// dockerfiles, and if they are all valid references to manifest lists, returns
|
||||
// the list of platforms that are supported by all of the base images.
|
||||
|
@ -570,7 +592,10 @@ func platformsForBaseImages(ctx context.Context, logger *logrus.Logger, dockerfi
|
|||
if baseImageIndex == 0 {
|
||||
// populate the list with the first image's normalized platforms
|
||||
for _, instance := range index.Manifests {
|
||||
if instance.Platform == nil {
|
||||
if !platformIsAcceptable(instance.Platform, logger) {
|
||||
continue
|
||||
}
|
||||
if instance.ArtifactType != "" {
|
||||
continue
|
||||
}
|
||||
platform := internalUtil.NormalizePlatform(*instance.Platform)
|
||||
|
@ -581,7 +606,10 @@ func platformsForBaseImages(ctx context.Context, logger *logrus.Logger, dockerfi
|
|||
// prune the list of any normalized platforms this base image doesn't support
|
||||
imagePlatforms := make(map[string]struct{})
|
||||
for _, instance := range index.Manifests {
|
||||
if instance.Platform == nil {
|
||||
if !platformIsAcceptable(instance.Platform, logger) {
|
||||
continue
|
||||
}
|
||||
if instance.ArtifactType != "" {
|
||||
continue
|
||||
}
|
||||
platform := internalUtil.NormalizePlatform(*instance.Platform)
|
||||
|
|
|
@ -1217,7 +1217,24 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
}
|
||||
logrus.Debugf("Parsed Step: %+v", *step)
|
||||
if !s.executor.quiet {
|
||||
s.log("%s", step.Original)
|
||||
logMsg := step.Original
|
||||
if len(step.Heredocs) > 0 {
|
||||
summarizeHeredoc := func(doc string) string {
|
||||
doc = strings.TrimSpace(doc)
|
||||
lines := strings.Split(strings.ReplaceAll(doc, "\r\n", "\n"), "\n")
|
||||
summary := lines[0]
|
||||
if len(lines) > 1 {
|
||||
summary += "..."
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
for _, doc := range node.Heredocs {
|
||||
heredocContent := summarizeHeredoc(doc.Content)
|
||||
logMsg = logMsg + " (" + heredocContent + ")"
|
||||
}
|
||||
}
|
||||
s.log("%s", logMsg)
|
||||
}
|
||||
|
||||
// Check if there's a --from if the step command is COPY.
|
||||
|
@ -1737,11 +1754,15 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
|
|||
buildArgs := s.getBuildArgsKey()
|
||||
return "/bin/sh -c #(nop) ARG " + buildArgs
|
||||
case "RUN":
|
||||
shArg := ""
|
||||
buildArgs := s.getBuildArgsResolvedForRun()
|
||||
if buildArgs != "" {
|
||||
return "|" + strconv.Itoa(len(strings.Split(buildArgs, " "))) + " " + buildArgs + " /bin/sh -c " + node.Original[4:]
|
||||
if len(node.Original) > 4 {
|
||||
shArg = node.Original[4:]
|
||||
}
|
||||
result := "/bin/sh -c " + node.Original[4:]
|
||||
if buildArgs != "" {
|
||||
return "|" + strconv.Itoa(len(strings.Split(buildArgs, " "))) + " " + buildArgs + " /bin/sh -c " + shArg
|
||||
}
|
||||
result := "/bin/sh -c " + shArg
|
||||
if len(node.Heredocs) > 0 {
|
||||
for _, doc := range node.Heredocs {
|
||||
heredocContent := strings.TrimSpace(doc.Content)
|
||||
|
|
|
@ -235,11 +235,11 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a
|
|||
}
|
||||
// if id is set a new subdirectory with `id` will be created under /host-temp/buildah-build-cache/id
|
||||
id := ""
|
||||
//buidkit parity: cache directory defaults to 755
|
||||
// buildkit parity: cache directory defaults to 755
|
||||
mode = 0o755
|
||||
//buidkit parity: cache directory defaults to uid 0 if not specified
|
||||
// buildkit parity: cache directory defaults to uid 0 if not specified
|
||||
uid := 0
|
||||
//buidkit parity: cache directory defaults to gid 0 if not specified
|
||||
// buildkit parity: cache directory defaults to gid 0 if not specified
|
||||
gid := 0
|
||||
// sharing mode
|
||||
sharing := "shared"
|
||||
|
@ -384,7 +384,7 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a
|
|||
UID: uid,
|
||||
GID: gid,
|
||||
}
|
||||
//buildkit parity: change uid and gid if specified otheriwise keep `0`
|
||||
// buildkit parity: change uid and gid if specified otheriwise keep `0`
|
||||
err = idtools.MkdirAllAndChownNew(newMount.Source, os.FileMode(mode), idPair)
|
||||
if err != nil {
|
||||
return newMount, nil, fmt.Errorf("unable to change uid,gid of cache directory: %w", err)
|
||||
|
@ -602,7 +602,7 @@ func GetTmpfsMount(args []string) (specs.Mount, error) {
|
|||
// Alias for "ro"
|
||||
newMount.Options = append(newMount.Options, "ro")
|
||||
case "tmpcopyup":
|
||||
//the path that is shadowed by the tmpfs mount is recursively copied up to the tmpfs itself.
|
||||
// the path that is shadowed by the tmpfs mount is recursively copied up to the tmpfs itself.
|
||||
newMount.Options = append(newMount.Options, argName)
|
||||
case "tmpfs-mode":
|
||||
if !hasArgValue {
|
||||
|
|
|
@ -19,12 +19,12 @@ import (
|
|||
"github.com/containers/buildah/pkg/parse"
|
||||
"github.com/containers/buildah/pkg/util"
|
||||
"github.com/containers/common/pkg/auth"
|
||||
cutil "github.com/containers/common/pkg/util"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
type BuildOptions struct {
|
||||
|
@ -316,13 +316,6 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
|
|||
iopts.NoCache = true
|
||||
}
|
||||
}
|
||||
var pullPushRetryDelay time.Duration
|
||||
pullPushRetryDelay, err = time.ParseDuration(iopts.RetryDelay)
|
||||
if err != nil {
|
||||
return options, nil, nil, fmt.Errorf("unable to parse value provided %q as --retry-delay: %w", iopts.RetryDelay, err)
|
||||
}
|
||||
// Following log line is used in integration test.
|
||||
logrus.Debugf("Setting MaxPullPushRetries to %d and PullPushRetryDelay to %v", iopts.Retry, pullPushRetryDelay)
|
||||
|
||||
if c.Flag("network").Changed && c.Flag("isolation").Changed {
|
||||
if isolation == define.IsolationChroot {
|
||||
|
@ -340,7 +333,7 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
|
|||
if err != nil {
|
||||
return options, nil, nil, err
|
||||
}
|
||||
if !cutil.StringInSlice(contextDir, sbomScanOption.ContextDir) {
|
||||
if !slices.Contains(sbomScanOption.ContextDir, contextDir) {
|
||||
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, contextDir)
|
||||
}
|
||||
for _, abc := range additionalBuildContext {
|
||||
|
@ -405,7 +398,6 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
|
|||
OutputFormat: format,
|
||||
Platforms: platforms,
|
||||
PullPolicy: pullPolicy,
|
||||
PullPushRetryDelay: pullPushRetryDelay,
|
||||
Quiet: iopts.Quiet,
|
||||
RemoveIntermediateCtrs: iopts.Rm,
|
||||
ReportWriter: reporter,
|
||||
|
@ -424,6 +416,15 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
|
|||
UnsetEnvs: iopts.UnsetEnvs,
|
||||
UnsetLabels: iopts.UnsetLabels,
|
||||
}
|
||||
if iopts.RetryDelay != "" {
|
||||
options.PullPushRetryDelay, err = time.ParseDuration(iopts.RetryDelay)
|
||||
if err != nil {
|
||||
return options, nil, nil, fmt.Errorf("unable to parse value provided %q as --retry-delay: %w", iopts.RetryDelay, err)
|
||||
}
|
||||
// Following log line is used in integration test.
|
||||
logrus.Debugf("Setting MaxPullPushRetries to %d and PullPushRetryDelay to %v", iopts.Retry, options.PullPushRetryDelay)
|
||||
}
|
||||
|
||||
if iopts.Quiet {
|
||||
options.ReportWriter = io.Discard
|
||||
}
|
||||
|
|
|
@ -367,7 +367,7 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
|
|||
fs := pflag.FlagSet{}
|
||||
defaultContainerConfig, err := config.Default()
|
||||
if err != nil {
|
||||
return fs, fmt.Errorf("failed to get container config: %w", err)
|
||||
return fs, fmt.Errorf("failed to get default container config: %w", err)
|
||||
}
|
||||
|
||||
fs.StringSliceVar(&flags.AddHost, "add-host", []string{}, "add a custom host-to-IP mapping (`host:ip`) (default [])")
|
||||
|
@ -392,8 +392,8 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
|
|||
fs.StringVar(&flags.Isolation, "isolation", DefaultIsolation(), "`type` of process isolation to use. Use BUILDAH_ISOLATION environment variable to override.")
|
||||
fs.StringVarP(&flags.Memory, "memory", "m", "", "memory limit (format: <number>[<unit>], where unit = b, k, m or g)")
|
||||
fs.StringVar(&flags.MemorySwap, "memory-swap", "", "swap limit equal to memory plus swap: '-1' to enable unlimited swap")
|
||||
fs.IntVar(&flags.Retry, "retry", MaxPullPushRetries, "number of times to retry in case of failure when performing push/pull")
|
||||
fs.StringVar(&flags.RetryDelay, "retry-delay", PullPushRetryDelay.String(), "delay between retries in case of push/pull failures")
|
||||
fs.IntVar(&flags.Retry, "retry", int(defaultContainerConfig.Engine.Retry), "number of times to retry in case of failure when performing push/pull")
|
||||
fs.StringVar(&flags.RetryDelay, "retry-delay", defaultContainerConfig.Engine.RetryDelay, "delay between retries in case of push/pull failures")
|
||||
fs.String("arch", runtime.GOARCH, "set the ARCH of the image to the provided value instead of the architecture of the host")
|
||||
fs.String("os", runtime.GOOS, "prefer `OS` instead of the running OS when pulling images")
|
||||
fs.StringSlice("platform", []string{parse.DefaultPlatform()}, "set the `OS/ARCH[/VARIANT]` of the image to the provided value instead of the current operating system and architecture of the host (for example \"linux/arm\")")
|
||||
|
|
|
@ -491,7 +491,9 @@ func PullPolicyFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name string)
|
|||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if pullNeverFlagValue || strings.EqualFold(pullFlagValue, "never") {
|
||||
if pullNeverFlagValue ||
|
||||
strings.EqualFold(pullFlagValue, "never") ||
|
||||
strings.EqualFold(pullFlagValue, "false") {
|
||||
pullPolicy = define.PullNever
|
||||
}
|
||||
logrus.Debugf("Pull Policy for pull [%v]", pullPolicy)
|
||||
|
@ -814,8 +816,11 @@ func SBOMScanOptionsFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name str
|
|||
return nil, fmt.Errorf("invalid value for --sbom-purl-output: %w", err)
|
||||
}
|
||||
|
||||
if options.Image == "" || len(options.Commands) == 0 || (options.SBOMOutput == "" && options.ImageSBOMOutput == "" && options.PURLOutput == "" && options.ImagePURLOutput == "") {
|
||||
return options, fmt.Errorf("sbom configuration missing one or more of (%q, %q, %q, %q, %q or %q)", "--sbom-scanner-imag", "--sbom-scanner-command", "--sbom-output", "--sbom-image-output", "--sbom-purl-output", "--sbom-image-purl-output")
|
||||
if options.Image == "" || len(options.Commands) == 0 {
|
||||
return options, fmt.Errorf("sbom configuration missing one or more of (%q or %q)", "--sbom-scanner-image", "--sbom-scanner-command")
|
||||
}
|
||||
if options.SBOMOutput == "" && options.ImageSBOMOutput == "" && options.PURLOutput == "" && options.ImagePURLOutput == "" {
|
||||
return options, fmt.Errorf("sbom configuration missing one or more of (%q, %q, %q or %q)", "--sbom-output", "--sbom-image-output", "--sbom-purl-output", "--sbom-image-purl-output")
|
||||
}
|
||||
if len(options.Commands) > 1 && options.MergeStrategy == "" {
|
||||
return options, fmt.Errorf("sbom configuration included multiple %q values but no %q value", "--sbom-scanner-command", "--sbom-merge-strategy")
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
"github.com/containers/common/libnetwork/resolvconf"
|
||||
nettypes "github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/common/pkg/config"
|
||||
cutil "github.com/containers/common/pkg/util"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
"github.com/containers/storage/pkg/stringid"
|
||||
|
@ -34,6 +33,7 @@ import (
|
|||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -203,7 +203,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)}
|
||||
|
||||
hostFile := ""
|
||||
if !options.NoHosts && !cutil.StringInSlice(config.DefaultHostsFile, volumes) && options.ConfigureNetwork != define.NetworkDisabled {
|
||||
if !options.NoHosts && !slices.Contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled {
|
||||
hostFile, err = b.generateHosts(path, rootIDPair, mountPoint, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -211,7 +211,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
bindFiles[config.DefaultHostsFile] = hostFile
|
||||
}
|
||||
|
||||
if !cutil.StringInSlice(resolvconf.DefaultResolvConf, volumes) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") {
|
||||
if !slices.Contains(volumes, resolvconf.DefaultResolvConf) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") {
|
||||
resolvFile, err := b.addResolvConf(path, rootIDPair, b.CommonBuildOpts.DNSServers, b.CommonBuildOpts.DNSSearch, b.CommonBuildOpts.DNSOptions, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -35,7 +35,6 @@ import (
|
|||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/common/pkg/hooks"
|
||||
hooksExec "github.com/containers/common/pkg/hooks/exec"
|
||||
cutil "github.com/containers/common/pkg/util"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
|
@ -45,6 +44,7 @@ import (
|
|||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -261,7 +261,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)}
|
||||
|
||||
hostFile := ""
|
||||
if !options.NoHosts && !cutil.StringInSlice(config.DefaultHostsFile, volumes) && options.ConfigureNetwork != define.NetworkDisabled {
|
||||
if !options.NoHosts && !slices.Contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled {
|
||||
hostFile, err = b.generateHosts(path, rootIDPair, mountPoint, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -269,7 +269,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
bindFiles[config.DefaultHostsFile] = hostFile
|
||||
}
|
||||
|
||||
if !options.NoHostname && !(cutil.StringInSlice("/etc/hostname", volumes)) {
|
||||
if !options.NoHostname && !(slices.Contains(volumes, "/etc/hostname")) {
|
||||
hostFile, err := b.generateHostname(path, spec.Hostname, rootIDPair)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -278,7 +278,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
bindFiles["/etc/hostname"] = hostFile
|
||||
}
|
||||
|
||||
if !cutil.StringInSlice(resolvconf.DefaultResolvConf, volumes) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") {
|
||||
if !slices.Contains(volumes, resolvconf.DefaultResolvConf) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") {
|
||||
resolvFile, err := b.addResolvConf(path, rootIDPair, b.CommonBuildOpts.DNSServers, b.CommonBuildOpts.DNSSearch, b.CommonBuildOpts.DNSOptions, spec.Linux.Namespaces)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -854,6 +854,9 @@ func addRlimits(ulimit []string, g *generate.Generator, defaultUlimits []string)
|
|||
var (
|
||||
ul *units.Ulimit
|
||||
err error
|
||||
// setup rlimits
|
||||
nofileSet bool
|
||||
nprocSet bool
|
||||
)
|
||||
|
||||
ulimit = append(defaultUlimits, ulimit...)
|
||||
|
@ -862,8 +865,39 @@ func addRlimits(ulimit []string, g *generate.Generator, defaultUlimits []string)
|
|||
return fmt.Errorf("ulimit option %q requires name=SOFT:HARD, failed to be parsed: %w", u, err)
|
||||
}
|
||||
|
||||
if strings.ToUpper(ul.Name) == "NOFILE" {
|
||||
nofileSet = true
|
||||
}
|
||||
if strings.ToUpper(ul.Name) == "NPROC" {
|
||||
nprocSet = true
|
||||
}
|
||||
g.AddProcessRlimits("RLIMIT_"+strings.ToUpper(ul.Name), uint64(ul.Hard), uint64(ul.Soft))
|
||||
}
|
||||
if !nofileSet {
|
||||
max := define.RLimitDefaultValue
|
||||
var rlimit unix.Rlimit
|
||||
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err == nil {
|
||||
if max < rlimit.Max || unshare.IsRootless() {
|
||||
max = rlimit.Max
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err)
|
||||
}
|
||||
g.AddProcessRlimits("RLIMIT_NOFILE", max, max)
|
||||
}
|
||||
if !nprocSet {
|
||||
max := define.RLimitDefaultValue
|
||||
var rlimit unix.Rlimit
|
||||
if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err == nil {
|
||||
if max < rlimit.Max || unshare.IsRootless() {
|
||||
max = rlimit.Max
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err)
|
||||
}
|
||||
g.AddProcessRlimits("RLIMIT_NPROC", max, max)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import (
|
|||
|
||||
"github.com/containers/buildah/define"
|
||||
"github.com/containers/buildah/internal/sbom"
|
||||
"github.com/containers/common/pkg/util"
|
||||
"github.com/mattn/go-shellwords"
|
||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
func stringSliceReplaceAll(slice []string, replacements map[string]string, important []string) (built []string, replacedAnImportantValue bool) {
|
||||
|
@ -23,7 +23,7 @@ func stringSliceReplaceAll(slice []string, replacements map[string]string, impor
|
|||
for from, to := range replacements {
|
||||
previous := element
|
||||
if element = strings.ReplaceAll(previous, from, to); element != previous {
|
||||
if len(important) == 0 || util.StringInSlice(from, important) {
|
||||
if len(important) == 0 || slices.Contains(important, from) {
|
||||
replacedAnImportantValue = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/containers/buildah/define"
|
||||
"github.com/containers/common/libimage"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/common/pkg/util"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/pkg/shortnames"
|
||||
"github.com/containers/image/v5/signature"
|
||||
|
@ -26,6 +25,7 @@ import (
|
|||
"github.com/opencontainers/go-digest"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -45,9 +45,9 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
// StringInSlice is deprecated, use github.com/containers/common/pkg/util.StringInSlice
|
||||
// StringInSlice is deprecated, use golang.org/x/exp/slices.Contains
|
||||
func StringInSlice(s string, slice []string) bool {
|
||||
return util.StringInSlice(s, slice)
|
||||
return slices.Contains(slice, s)
|
||||
}
|
||||
|
||||
// resolveName checks if name is a valid image name, and if that name doesn't
|
||||
|
@ -244,7 +244,7 @@ func Runtime() string {
|
|||
|
||||
conf, err := config.Default()
|
||||
if err != nil {
|
||||
logrus.Warnf("Error loading container config when searching for local runtime: %v", err)
|
||||
logrus.Warnf("Error loading default container config when searching for local runtime: %v", err)
|
||||
return define.DefaultRuntime
|
||||
}
|
||||
return conf.Engine.OCIRuntime
|
||||
|
|
|
@ -23,9 +23,9 @@ var (
|
|||
// compressionBufferSize is the buffer size used to compress a blob
|
||||
compressionBufferSize = 1048576
|
||||
|
||||
// expectedCompressionFormats is used to check if a blob with a specified media type is compressed
|
||||
// expectedBaseCompressionFormats is used to check if a blob with a specified media type is compressed
|
||||
// using the algorithm that the media type says it should be compressed with
|
||||
expectedCompressionFormats = map[string]*compressiontypes.Algorithm{
|
||||
expectedBaseCompressionFormats = map[string]*compressiontypes.Algorithm{
|
||||
imgspecv1.MediaTypeImageLayerGzip: &compression.Gzip,
|
||||
imgspecv1.MediaTypeImageLayerZstd: &compression.Zstd,
|
||||
manifest.DockerV2Schema2LayerMediaType: &compression.Gzip,
|
||||
|
@ -62,8 +62,8 @@ func blobPipelineDetectCompressionStep(stream *sourceStream, srcInfo types.BlobI
|
|||
res.srcCompressorName = internalblobinfocache.Uncompressed
|
||||
}
|
||||
|
||||
if expectedFormat, known := expectedCompressionFormats[stream.info.MediaType]; known && res.isCompressed && format.Name() != expectedFormat.Name() {
|
||||
logrus.Debugf("blob %s with type %s should be compressed with %s, but compressor appears to be %s", srcInfo.Digest.String(), srcInfo.MediaType, expectedFormat.Name(), format.Name())
|
||||
if expectedBaseFormat, known := expectedBaseCompressionFormats[stream.info.MediaType]; known && res.isCompressed && format.BaseVariantName() != expectedBaseFormat.Name() {
|
||||
logrus.Debugf("blob %s with type %s should be compressed with %s, but compressor appears to be %s", srcInfo.Digest.String(), srcInfo.MediaType, expectedBaseFormat.Name(), format.Name())
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
@ -172,7 +172,8 @@ func (ic *imageCopier) bpcCompressUncompressed(stream *sourceStream, detected bp
|
|||
// bpcRecompressCompressed checks if we should be recompressing a compressed input to another format, and returns a *bpCompressionStepData if so.
|
||||
func (ic *imageCopier) bpcRecompressCompressed(stream *sourceStream, detected bpDetectCompressionStepData) (*bpCompressionStepData, error) {
|
||||
if ic.c.dest.DesiredLayerCompression() == types.Compress && detected.isCompressed &&
|
||||
ic.compressionFormat != nil && ic.compressionFormat.Name() != detected.format.Name() {
|
||||
ic.compressionFormat != nil &&
|
||||
(ic.compressionFormat.Name() != detected.format.Name() && ic.compressionFormat.Name() != detected.format.BaseVariantName()) {
|
||||
// When the blob is compressed, but the desired format is different, it first needs to be decompressed and finally
|
||||
// re-compressed using the desired format.
|
||||
logrus.Debugf("Blob will be converted")
|
||||
|
|
|
@ -23,11 +23,11 @@ type digestingReader struct {
|
|||
func newDigestingReader(source io.Reader, expectedDigest digest.Digest) (*digestingReader, error) {
|
||||
var digester digest.Digester
|
||||
if err := expectedDigest.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("Invalid digest specification %s", expectedDigest)
|
||||
return nil, fmt.Errorf("invalid digest specification %q: %w", expectedDigest, err)
|
||||
}
|
||||
digestAlgorithm := expectedDigest.Algorithm()
|
||||
if !digestAlgorithm.Available() {
|
||||
return nil, fmt.Errorf("Invalid digest specification %s: unsupported digest algorithm %s", expectedDigest, digestAlgorithm)
|
||||
return nil, fmt.Errorf("invalid digest specification %q: unsupported digest algorithm %q", expectedDigest, digestAlgorithm)
|
||||
}
|
||||
digester = digestAlgorithm.Digester()
|
||||
|
||||
|
|
|
@ -383,7 +383,11 @@ func (ic *imageCopier) compareImageDestinationManifestEqual(ctx context.Context,
|
|||
|
||||
compressionAlgos := set.New[string]()
|
||||
for _, srcInfo := range ic.src.LayerInfos() {
|
||||
if _, c := compressionEditsFromMIMEType(srcInfo); c != nil {
|
||||
_, c, err := compressionEditsFromBlobInfo(srcInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c != nil {
|
||||
compressionAlgos.Add(c.Name())
|
||||
}
|
||||
}
|
||||
|
@ -636,21 +640,28 @@ type diffIDResult struct {
|
|||
err error
|
||||
}
|
||||
|
||||
// compressionEditsFromMIMEType returns a (CompressionOperation, CompressionAlgorithm) value pair suitable
|
||||
// for types.BlobInfo, based on a MIME type of srcInfo.
|
||||
func compressionEditsFromMIMEType(srcInfo types.BlobInfo) (types.LayerCompression, *compressiontypes.Algorithm) {
|
||||
// compressionEditsFromBlobInfo returns a (CompressionOperation, CompressionAlgorithm) value pair suitable
|
||||
// for types.BlobInfo.
|
||||
func compressionEditsFromBlobInfo(srcInfo types.BlobInfo) (types.LayerCompression, *compressiontypes.Algorithm, error) {
|
||||
// This MIME type → compression mapping belongs in manifest-specific code in our manifest
|
||||
// package (but we should preferably replace/change UpdatedImage instead of productizing
|
||||
// this workaround).
|
||||
switch srcInfo.MediaType {
|
||||
case manifest.DockerV2Schema2LayerMediaType, imgspecv1.MediaTypeImageLayerGzip:
|
||||
return types.PreserveOriginal, &compression.Gzip
|
||||
return types.PreserveOriginal, &compression.Gzip, nil
|
||||
case imgspecv1.MediaTypeImageLayerZstd:
|
||||
return types.PreserveOriginal, &compression.Zstd
|
||||
tocDigest, err := chunkedToc.GetTOCDigest(srcInfo.Annotations)
|
||||
if err != nil {
|
||||
return types.PreserveOriginal, nil, err
|
||||
}
|
||||
if tocDigest != nil {
|
||||
return types.PreserveOriginal, &compression.ZstdChunked, nil
|
||||
}
|
||||
return types.PreserveOriginal, &compression.Zstd, nil
|
||||
case manifest.DockerV2SchemaLayerMediaTypeUncompressed, imgspecv1.MediaTypeImageLayer:
|
||||
return types.Decompress, nil
|
||||
return types.Decompress, nil, nil
|
||||
default:
|
||||
return types.PreserveOriginal, nil
|
||||
return types.PreserveOriginal, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,7 +677,12 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to
|
|||
// (Sadly UpdatedImage() is documented to not update MediaTypes from
|
||||
// ManifestUpdateOptions.LayerInfos[].MediaType, so we are doing it indirectly.)
|
||||
if srcInfo.CompressionOperation == types.PreserveOriginal && srcInfo.CompressionAlgorithm == nil {
|
||||
srcInfo.CompressionOperation, srcInfo.CompressionAlgorithm = compressionEditsFromMIMEType(srcInfo)
|
||||
op, algo, err := compressionEditsFromBlobInfo(srcInfo)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, "", err
|
||||
}
|
||||
srcInfo.CompressionOperation = op
|
||||
srcInfo.CompressionAlgorithm = algo
|
||||
}
|
||||
|
||||
ic.c.printCopyInfo("blob", srcInfo)
|
||||
|
|
|
@ -978,13 +978,10 @@ func (c *dockerClient) fetchManifest(ctx context.Context, ref dockerReference, t
|
|||
// This function can return nil reader when no url is supported by this function. In this case, the caller
|
||||
// should fallback to fetch the non-external blob (i.e. pull from the registry).
|
||||
func (c *dockerClient) getExternalBlob(ctx context.Context, urls []string) (io.ReadCloser, int64, error) {
|
||||
var (
|
||||
resp *http.Response
|
||||
err error
|
||||
)
|
||||
if len(urls) == 0 {
|
||||
return nil, 0, errors.New("internal error: getExternalBlob called with no URLs")
|
||||
}
|
||||
var remoteErrors []error
|
||||
for _, u := range urls {
|
||||
blobURL, err := url.Parse(u)
|
||||
if err != nil || (blobURL.Scheme != "http" && blobURL.Scheme != "https") {
|
||||
|
@ -993,24 +990,28 @@ func (c *dockerClient) getExternalBlob(ctx context.Context, urls []string) (io.R
|
|||
// NOTE: we must not authenticate on additional URLs as those
|
||||
// can be abused to leak credentials or tokens. Please
|
||||
// refer to CVE-2020-15157 for more information.
|
||||
resp, err = c.makeRequestToResolvedURL(ctx, http.MethodGet, blobURL, nil, nil, -1, noAuth, nil)
|
||||
if err == nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err = fmt.Errorf("error fetching external blob from %q: %d (%s)", u, resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
logrus.Debug(err)
|
||||
resp.Body.Close()
|
||||
continue
|
||||
}
|
||||
break
|
||||
resp, err := c.makeRequestToResolvedURL(ctx, http.MethodGet, blobURL, nil, nil, -1, noAuth, nil)
|
||||
if err != nil {
|
||||
remoteErrors = append(remoteErrors, err)
|
||||
continue
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("error fetching external blob from %q: %d (%s)", u, resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
remoteErrors = append(remoteErrors, err)
|
||||
logrus.Debug(err)
|
||||
resp.Body.Close()
|
||||
continue
|
||||
}
|
||||
return resp.Body, getBlobSize(resp), nil
|
||||
}
|
||||
if resp == nil && err == nil {
|
||||
if remoteErrors == nil {
|
||||
return nil, 0, nil // fallback to non-external blob
|
||||
}
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
err := fmt.Errorf("failed fetching external blob from all urls: %w", remoteErrors[0])
|
||||
for _, e := range remoteErrors[1:] {
|
||||
err = fmt.Errorf("%s, %w", err, e)
|
||||
}
|
||||
return resp.Body, getBlobSize(resp), nil
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
func getBlobSize(resp *http.Response) int64 {
|
||||
|
|
3
vendor/github.com/containers/image/v5/internal/imagedestination/impl/helpers.go
generated
vendored
3
vendor/github.com/containers/image/v5/internal/imagedestination/impl/helpers.go
generated
vendored
|
@ -17,7 +17,8 @@ func CandidateMatchesTryReusingBlobOptions(options private.TryReusingBlobOptions
|
|||
// The caller must re-compress to build those annotations.
|
||||
return false
|
||||
}
|
||||
if candidateCompression == nil || (options.RequiredCompression.Name() != candidateCompression.Name()) {
|
||||
if candidateCompression == nil ||
|
||||
(options.RequiredCompression.Name() != candidateCompression.Name() && options.RequiredCompression.Name() != candidateCompression.BaseVariantName()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,7 +169,8 @@ func NormalizedMIMEType(input string) string {
|
|||
|
||||
// CompressionAlgorithmIsUniversallySupported returns true if MIMETypeSupportsCompressionAlgorithm(mimeType, algo) returns true for all mimeType values.
|
||||
func CompressionAlgorithmIsUniversallySupported(algo compressiontypes.Algorithm) bool {
|
||||
switch algo.Name() { // Should this use InternalUnstableUndocumentedMIMEQuestionMark() ?
|
||||
// Compare the discussion about BaseVariantName in MIMETypeSupportsCompressionAlgorithm().
|
||||
switch algo.Name() {
|
||||
case compressiontypes.GzipAlgorithmName:
|
||||
return true
|
||||
default:
|
||||
|
@ -182,7 +183,9 @@ func MIMETypeSupportsCompressionAlgorithm(mimeType string, algo compressiontypes
|
|||
if CompressionAlgorithmIsUniversallySupported(algo) {
|
||||
return true
|
||||
}
|
||||
switch algo.Name() { // Should this use InternalUnstableUndocumentedMIMEQuestionMark() ?
|
||||
// This does not use BaseVariantName: Plausibly a manifest format might support zstd but not have annotation fields.
|
||||
// The logic might have to be more complex (and more ad-hoc) if more manifest formats, with more capabilities, emerge.
|
||||
switch algo.Name() {
|
||||
case compressiontypes.ZstdAlgorithmName, compressiontypes.ZstdChunkedAlgorithmName:
|
||||
return mimeType == imgspecv1.MediaTypeImageManifest
|
||||
default: // Includes Bzip2AlgorithmName and XzAlgorithmName, which are defined names but are not supported anywhere
|
||||
|
|
|
@ -103,8 +103,8 @@ func addCompressionAnnotations(compressionAlgorithms []compression.Algorithm, an
|
|||
*annotationsMap = map[string]string{}
|
||||
}
|
||||
for _, algo := range compressionAlgorithms {
|
||||
switch algo.Name() {
|
||||
case compression.ZstdAlgorithmName, compression.ZstdChunkedAlgorithmName: // Should this use InternalUnstableUndocumentedMIMEQuestionMark() ?
|
||||
switch algo.BaseVariantName() {
|
||||
case compression.ZstdAlgorithmName:
|
||||
(*annotationsMap)[OCI1InstanceAnnotationCompressionZSTD] = OCI1InstanceAnnotationCompressionZSTDValue
|
||||
default:
|
||||
continue
|
||||
|
|
|
@ -55,7 +55,7 @@ func compressionVariantMIMEType(variantTable []compressionMIMETypeSet, mimeType
|
|||
if variants != nil {
|
||||
name := mtsUncompressed
|
||||
if algorithm != nil {
|
||||
name = algorithm.InternalUnstableUndocumentedMIMEQuestionMark()
|
||||
name = algorithm.BaseVariantName()
|
||||
}
|
||||
if res, ok := variants[name]; ok {
|
||||
if res != mtsUnsupportedMIMEType {
|
||||
|
|
|
@ -19,19 +19,19 @@ type Algorithm = types.Algorithm
|
|||
|
||||
var (
|
||||
// Gzip compression.
|
||||
Gzip = internal.NewAlgorithm(types.GzipAlgorithmName, types.GzipAlgorithmName,
|
||||
Gzip = internal.NewAlgorithm(types.GzipAlgorithmName, "",
|
||||
[]byte{0x1F, 0x8B, 0x08}, GzipDecompressor, gzipCompressor)
|
||||
// Bzip2 compression.
|
||||
Bzip2 = internal.NewAlgorithm(types.Bzip2AlgorithmName, types.Bzip2AlgorithmName,
|
||||
Bzip2 = internal.NewAlgorithm(types.Bzip2AlgorithmName, "",
|
||||
[]byte{0x42, 0x5A, 0x68}, Bzip2Decompressor, bzip2Compressor)
|
||||
// Xz compression.
|
||||
Xz = internal.NewAlgorithm(types.XzAlgorithmName, types.XzAlgorithmName,
|
||||
Xz = internal.NewAlgorithm(types.XzAlgorithmName, "",
|
||||
[]byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, XzDecompressor, xzCompressor)
|
||||
// Zstd compression.
|
||||
Zstd = internal.NewAlgorithm(types.ZstdAlgorithmName, types.ZstdAlgorithmName,
|
||||
Zstd = internal.NewAlgorithm(types.ZstdAlgorithmName, "",
|
||||
[]byte{0x28, 0xb5, 0x2f, 0xfd}, ZstdDecompressor, zstdCompressor)
|
||||
// ZstdChunked is a Zstd compression with chunk metadta which allows random access to individual files.
|
||||
ZstdChunked = internal.NewAlgorithm(types.ZstdChunkedAlgorithmName, types.ZstdAlgorithmName, /* Note: InternalUnstableUndocumentedMIMEQuestionMark is not ZstdChunkedAlgorithmName */
|
||||
// ZstdChunked is a Zstd compression with chunk metadata which allows random access to individual files.
|
||||
ZstdChunked = internal.NewAlgorithm(types.ZstdChunkedAlgorithmName, types.ZstdAlgorithmName,
|
||||
nil, ZstdDecompressor, compressor.ZstdCompressor)
|
||||
|
||||
compressionAlgorithms = map[string]Algorithm{
|
||||
|
|
|
@ -12,23 +12,28 @@ type DecompressorFunc func(io.Reader) (io.ReadCloser, error)
|
|||
|
||||
// Algorithm is a compression algorithm that can be used for CompressStream.
|
||||
type Algorithm struct {
|
||||
name string
|
||||
mime string
|
||||
prefix []byte // Initial bytes of a stream compressed using this algorithm, or empty to disable detection.
|
||||
decompressor DecompressorFunc
|
||||
compressor CompressorFunc
|
||||
name string
|
||||
baseVariantName string
|
||||
prefix []byte // Initial bytes of a stream compressed using this algorithm, or empty to disable detection.
|
||||
decompressor DecompressorFunc
|
||||
compressor CompressorFunc
|
||||
}
|
||||
|
||||
// NewAlgorithm creates an Algorithm instance.
|
||||
// nontrivialBaseVariantName is typically "".
|
||||
// This function exists so that Algorithm instances can only be created by code that
|
||||
// is allowed to import this internal subpackage.
|
||||
func NewAlgorithm(name, mime string, prefix []byte, decompressor DecompressorFunc, compressor CompressorFunc) Algorithm {
|
||||
func NewAlgorithm(name, nontrivialBaseVariantName string, prefix []byte, decompressor DecompressorFunc, compressor CompressorFunc) Algorithm {
|
||||
baseVariantName := name
|
||||
if nontrivialBaseVariantName != "" {
|
||||
baseVariantName = nontrivialBaseVariantName
|
||||
}
|
||||
return Algorithm{
|
||||
name: name,
|
||||
mime: mime,
|
||||
prefix: prefix,
|
||||
decompressor: decompressor,
|
||||
compressor: compressor,
|
||||
name: name,
|
||||
baseVariantName: baseVariantName,
|
||||
prefix: prefix,
|
||||
decompressor: decompressor,
|
||||
compressor: compressor,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,10 +42,11 @@ func (c Algorithm) Name() string {
|
|||
return c.name
|
||||
}
|
||||
|
||||
// InternalUnstableUndocumentedMIMEQuestionMark ???
|
||||
// DO NOT USE THIS anywhere outside of c/image until it is properly documented.
|
||||
func (c Algorithm) InternalUnstableUndocumentedMIMEQuestionMark() string {
|
||||
return c.mime
|
||||
// BaseVariantName returns the name of the “base variant” of the compression algorithm.
|
||||
// It is either equal to Name() of the same algorithm, or equal to Name() of some other Algorithm (the “base variant”).
|
||||
// This supports a single level of “is-a” relationship between compression algorithms, e.g. where "zstd:chunked" data is valid "zstd" data.
|
||||
func (c Algorithm) BaseVariantName() string {
|
||||
return c.baseVariantName
|
||||
}
|
||||
|
||||
// AlgorithmCompressor returns the compressor field of algo.
|
||||
|
|
|
@ -142,9 +142,13 @@ func WithFulcioAndInteractiveOIDC(fulcioURL *url.URL, oidcIssuerURL *url.URL, oi
|
|||
}
|
||||
|
||||
logrus.Debugf("Starting interactive OIDC authentication for issuer %s", oidcIssuerURL.Redacted())
|
||||
// This is intended to match oauthflow.DefaultIDTokenGetter, overriding only input/output
|
||||
// This is intended to match oauthflow.DefaultIDTokenGetter (incl. the update in init()), overriding only input/output
|
||||
htmlPage, err := oauth.GetInteractiveSuccessHTML(false, 10)
|
||||
if err != nil {
|
||||
return fmt.Errorf("formatting HTML content: %w", err)
|
||||
}
|
||||
tokenGetter := &oauthflow.InteractiveIDTokenGetter{
|
||||
HTMLPage: oauth.InteractiveSuccessHTML,
|
||||
HTMLPage: htmlPage,
|
||||
Input: interactiveInput,
|
||||
Output: interactiveOutput,
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
Serious about security
|
||||
======================
|
||||
|
||||
Square recognizes the important contributions the security research community
|
||||
can make. We therefore encourage reporting security issues with the code
|
||||
contained in this repository.
|
||||
|
||||
If you believe you have discovered a security vulnerability, please follow the
|
||||
guidelines at <https://bugcrowd.com/squareopensource>.
|
||||
|
|
@ -1,6 +1,23 @@
|
|||
# v3.0.2
|
||||
|
||||
## Fixed
|
||||
|
||||
- DecryptMulti: handle decompression error (#19)
|
||||
|
||||
## Changed
|
||||
|
||||
- jwe/CompactSerialize: improve performance (#67)
|
||||
- Increase the default number of PBKDF2 iterations to 600k (#48)
|
||||
- Return the proper algorithm for ECDSA keys (#45)
|
||||
|
||||
## Added
|
||||
|
||||
- Add Thumbprint support for opaque signers (#38)
|
||||
|
||||
# v3.0.1
|
||||
|
||||
Fixed:
|
||||
## Fixed
|
||||
|
||||
- Security issue: an attacker specifying a large "p2c" value can cause
|
||||
JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
|
||||
amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
# Go JOSE
|
||||
|
||||
[![godoc](http://img.shields.io/badge/godoc-jose_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2)
|
||||
[![godoc](http://img.shields.io/badge/godoc-jwt_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2/jwt)
|
||||
[![license](http://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE)
|
||||
[![build](https://travis-ci.org/go-jose/go-jose.svg?branch=master)](https://travis-ci.org/go-jose/go-jose)
|
||||
[![coverage](https://coveralls.io/repos/github/go-jose/go-jose/badge.svg?branch=master)](https://coveralls.io/r/go-jose/go-jose)
|
||||
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3)
|
||||
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3/jwt)
|
||||
[![license](https://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE)
|
||||
[![test](https://img.shields.io/github/checks-status/go-jose/go-jose/v3)](https://github.com/go-jose/go-jose/actions)
|
||||
|
||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||
and Encryption set of standards. This includes support for JSON Web Encryption,
|
||||
JSON Web Signature, and JSON Web Token standards.
|
||||
|
||||
**Help Wanted!** If you'd like to help us develop this library please reach
|
||||
out to css (at) css.bio. While I'm still working on keeping this maintained,
|
||||
I have limited time for in-depth development and could use some additional help.
|
||||
|
||||
**Disclaimer**: This library contains encryption software that is subject to
|
||||
the U.S. Export Administration Regulations. You may not export, re-export,
|
||||
transfer or download this code or any part of it in violation of any United
|
||||
|
@ -21,13 +24,13 @@ US maintained blocked list.
|
|||
## Overview
|
||||
|
||||
The implementation follows the
|
||||
[JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516) (RFC 7516),
|
||||
[JSON Web Signature](http://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
|
||||
[JSON Web Token](http://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications.
|
||||
[JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516),
|
||||
[JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
|
||||
[JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications.
|
||||
Tables of supported algorithms are shown below. The library supports both
|
||||
the compact and JWS/JWE JSON Serialization formats, and has optional support for
|
||||
multiple recipients. It also comes with a small command-line utility
|
||||
([`jose-util`](https://github.com/go-jose/go-jose/tree/master/jose-util))
|
||||
([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util))
|
||||
for dealing with JOSE messages in a shell.
|
||||
|
||||
**Note**: We use a forked version of the `encoding/json` package from the Go
|
||||
|
@ -38,29 +41,19 @@ libraries in other languages.
|
|||
|
||||
### Versions
|
||||
|
||||
[Version 2](https://gopkg.in/go-jose/go-jose.v2)
|
||||
([branch](https://github.com/go-jose/go-jose/tree/v2),
|
||||
[doc](https://godoc.org/gopkg.in/go-jose/go-jose.v2)) is the current stable version:
|
||||
|
||||
import "gopkg.in/go-jose/go-jose.v2"
|
||||
|
||||
[Version 3](https://github.com/go-jose/go-jose)
|
||||
([branch](https://github.com/go-jose/go-jose/tree/master),
|
||||
[doc](https://godoc.org/github.com/go-jose/go-jose)) is the under development/unstable version (not released yet):
|
||||
([branch](https://github.com/go-jose/go-jose/tree/v3),
|
||||
[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v3), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
|
||||
|
||||
import "github.com/go-jose/go-jose/v3"
|
||||
|
||||
All new feature development takes place on the `master` branch, which we are
|
||||
preparing to release as version 3 soon. Version 2 will continue to receive
|
||||
critical bug and security fixes. Note that starting with version 3 we are
|
||||
using Go modules for versioning instead of `gopkg.in` as before. Version 3 also will require Go version 1.13 or higher.
|
||||
|
||||
Version 1 (on the `v1` branch) is frozen and not supported anymore.
|
||||
The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
|
||||
are still useable but not actively developed anymore.
|
||||
|
||||
### Supported algorithms
|
||||
|
||||
See below for a table of supported algorithms. Algorithm identifiers match
|
||||
the names in the [JSON Web Algorithms](http://dx.doi.org/10.17487/RFC7518)
|
||||
the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518)
|
||||
standard where possible. The Godoc reference has a list of constants.
|
||||
|
||||
Key encryption | Algorithm identifier(s)
|
||||
|
@ -103,20 +96,20 @@ allows attaching a key id.
|
|||
|
||||
Algorithm(s) | Corresponding types
|
||||
:------------------------- | -------------------------------
|
||||
RSA | *[rsa.PublicKey](http://golang.org/pkg/crypto/rsa/#PublicKey), *[rsa.PrivateKey](http://golang.org/pkg/crypto/rsa/#PrivateKey)
|
||||
ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey)
|
||||
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://godoc.org/pkg/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://godoc.org/pkg/crypto/ed25519#PrivateKey)
|
||||
RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey)
|
||||
ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey)
|
||||
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey)
|
||||
AES, HMAC | []byte
|
||||
|
||||
<sup>1. Only available in version 2 or later of the package</sup>
|
||||
|
||||
## Examples
|
||||
|
||||
[![godoc](http://img.shields.io/badge/godoc-jose_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2)
|
||||
[![godoc](http://img.shields.io/badge/godoc-jwt_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2/jwt)
|
||||
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3)
|
||||
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3/jwt)
|
||||
|
||||
Examples can be found in the Godoc
|
||||
reference for this package. The
|
||||
[`jose-util`](https://github.com/go-jose/go-jose/tree/master/jose-util)
|
||||
[`jose-util`](https://github.com/go-jose/go-jose/tree/v3/jose-util)
|
||||
subdirectory also contains a small command-line utility which might be useful
|
||||
as an example as well.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# Security Policy
|
||||
This document explains how to contact the Let's Encrypt security team to report security vulnerabilities.
|
||||
|
||||
## Supported Versions
|
||||
| Version | Supported |
|
||||
| ------- | ----------|
|
||||
| >= v3 | ✓ |
|
||||
| v2 | ✗ |
|
||||
| v1 | ✗ |
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Please see [https://letsencrypt.org/contact/#security](https://letsencrypt.org/contact/#security) for the email address to report a vulnerability. Ensure that the subject line for your report contains the word `vulnerability` and is descriptive. Your email should be acknowledged within 24 hours. If you do not receive a response within 24 hours, please follow-up again with another email.
|
|
@ -285,6 +285,9 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm
|
|||
|
||||
switch alg {
|
||||
case RS256, RS384, RS512:
|
||||
// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
|
||||
// random parameter is legacy and ignored, and it can be nil.
|
||||
// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
|
||||
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
|
||||
case PS256, PS384, PS512:
|
||||
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
@ -76,14 +75,24 @@ type recipientKeyInfo struct {
|
|||
type EncrypterOptions struct {
|
||||
Compression CompressionAlgorithm
|
||||
|
||||
// Optional map of additional keys to be inserted into the protected header
|
||||
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||
// additional values here. All values must be JSON-serializable.
|
||||
// Optional map of name/value pairs to be inserted into the protected
|
||||
// header of a JWS object. Some specifications which make use of
|
||||
// JWS require additional values here.
|
||||
//
|
||||
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||
// that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||
// if necessary. It returns itself and so can be used in a fluent style.
|
||||
// if necessary, and returns the updated EncrypterOptions.
|
||||
//
|
||||
// The v parameter will be serialized by [json.Marshal] and must be a valid
|
||||
// input to that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
|
||||
if eo.ExtraHeaders == nil {
|
||||
eo.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||
|
@ -111,7 +120,17 @@ func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions {
|
|||
// default of 100000 will be used for the count and a 128-bit random salt will
|
||||
// be generated.
|
||||
type Recipient struct {
|
||||
Algorithm KeyAlgorithm
|
||||
Algorithm KeyAlgorithm
|
||||
// Key must have one of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *rsa.PublicKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (a symmetric key)
|
||||
// - Any type that satisfies the OpaqueKeyEncrypter interface
|
||||
//
|
||||
// The type of Key must match the value of Algorithm.
|
||||
Key interface{}
|
||||
KeyID string
|
||||
PBES2Count int
|
||||
|
@ -150,16 +169,17 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
|||
switch rcpt.Algorithm {
|
||||
case DIRECT:
|
||||
// Direct encryption mode must be treated differently
|
||||
if reflect.TypeOf(rawKey) != reflect.TypeOf([]byte{}) {
|
||||
keyBytes, ok := rawKey.([]byte)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
if encrypter.cipher.keySize() != len(rawKey.([]byte)) {
|
||||
if encrypter.cipher.keySize() != len(keyBytes) {
|
||||
return nil, ErrInvalidKeySize
|
||||
}
|
||||
encrypter.keyGenerator = staticKeyGenerator{
|
||||
key: rawKey.([]byte),
|
||||
key: keyBytes,
|
||||
}
|
||||
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, rawKey.([]byte))
|
||||
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes)
|
||||
recipientInfo.keyID = keyID
|
||||
if rcpt.KeyID != "" {
|
||||
recipientInfo.keyID = rcpt.KeyID
|
||||
|
@ -168,16 +188,16 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
|||
return encrypter, nil
|
||||
case ECDH_ES:
|
||||
// ECDH-ES (w/o key wrapping) is similar to DIRECT mode
|
||||
typeOf := reflect.TypeOf(rawKey)
|
||||
if typeOf != reflect.TypeOf(&ecdsa.PublicKey{}) {
|
||||
keyDSA, ok := rawKey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
encrypter.keyGenerator = ecKeyGenerator{
|
||||
size: encrypter.cipher.keySize(),
|
||||
algID: string(enc),
|
||||
publicKey: rawKey.(*ecdsa.PublicKey),
|
||||
publicKey: keyDSA,
|
||||
}
|
||||
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, rawKey.(*ecdsa.PublicKey))
|
||||
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA)
|
||||
recipientInfo.keyID = keyID
|
||||
if rcpt.KeyID != "" {
|
||||
recipientInfo.keyID = rcpt.KeyID
|
||||
|
@ -270,9 +290,8 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey
|
|||
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
|
||||
recipient.keyID = encryptionKey.KeyID
|
||||
return recipient, err
|
||||
}
|
||||
if encrypter, ok := encryptionKey.(OpaqueKeyEncrypter); ok {
|
||||
return newOpaqueKeyEncrypter(alg, encrypter)
|
||||
case OpaqueKeyEncrypter:
|
||||
return newOpaqueKeyEncrypter(alg, encryptionKey)
|
||||
}
|
||||
return recipientKeyInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
|
@ -300,11 +319,11 @@ func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) {
|
|||
return newDecrypter(decryptionKey.Key)
|
||||
case *JSONWebKey:
|
||||
return newDecrypter(decryptionKey.Key)
|
||||
case OpaqueKeyDecrypter:
|
||||
return &opaqueKeyDecrypter{decrypter: decryptionKey}, nil
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
if okd, ok := decryptionKey.(OpaqueKeyDecrypter); ok {
|
||||
return &opaqueKeyDecrypter{decrypter: okd}, nil
|
||||
}
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
// Implementation of encrypt method producing a JWE object.
|
||||
|
@ -403,9 +422,24 @@ func (ctx *genericEncrypter) Options() EncrypterOptions {
|
|||
}
|
||||
}
|
||||
|
||||
// Decrypt and validate the object and return the plaintext. Note that this
|
||||
// function does not support multi-recipient, if you desire multi-recipient
|
||||
// Decrypt and validate the object and return the plaintext. This
|
||||
// function does not support multi-recipient. If you desire multi-recipient
|
||||
// decryption use DecryptMulti instead.
|
||||
//
|
||||
// The decryptionKey argument must contain a private or symmetric key
|
||||
// and must have one of these types:
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PrivateKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - *JSONWebKeySet
|
||||
// - JSONWebKeySet
|
||||
// - []byte (a symmetric key)
|
||||
// - string (a symmetric key)
|
||||
// - Any type that satisfies the OpaqueKeyDecrypter interface.
|
||||
//
|
||||
// Note that ed25519 is only available for signatures, not encryption, so is
|
||||
// not an option here.
|
||||
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
|
||||
headers := obj.mergedHeaders(nil)
|
||||
|
||||
|
@ -462,15 +496,21 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
|||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return plaintext, err
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// DecryptMulti decrypts and validates the object and returns the plaintexts,
|
||||
// with support for multiple recipients. It returns the index of the recipient
|
||||
// for which the decryption was successful, the merged headers for that recipient,
|
||||
// and the plaintext.
|
||||
//
|
||||
// The decryptionKey argument must have one of the types allowed for the
|
||||
// decryptionKey argument of Decrypt().
|
||||
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
||||
globalHeaders := obj.mergedHeaders(nil)
|
||||
|
||||
|
@ -532,7 +572,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
|||
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, _ = decompress(comp, plaintext)
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
sanitized, err := headers.sanitized()
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
|
||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||
and Encryption set of standards. It implements encryption and signing based on
|
||||
the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web
|
||||
Token support available in a sub-package. The library supports both the compact
|
||||
and JWS/JWE JSON Serialization formats, and has optional support for multiple
|
||||
recipients.
|
||||
|
||||
*/
|
||||
package jose
|
||||
|
|
|
@ -189,3 +189,36 @@ func base64URLDecode(value string) ([]byte, error) {
|
|||
value = strings.TrimRight(value, "=")
|
||||
return base64.RawURLEncoding.DecodeString(value)
|
||||
}
|
||||
|
||||
func base64EncodeLen(sl []byte) int {
|
||||
return base64.RawURLEncoding.EncodedLen(len(sl))
|
||||
}
|
||||
|
||||
func base64JoinWithDots(inputs ...[]byte) string {
|
||||
if len(inputs) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Count of dots.
|
||||
totalCount := len(inputs) - 1
|
||||
|
||||
for _, input := range inputs {
|
||||
totalCount += base64EncodeLen(input)
|
||||
}
|
||||
|
||||
out := make([]byte, totalCount)
|
||||
startEncode := 0
|
||||
for i, input := range inputs {
|
||||
base64.RawURLEncoding.Encode(out[startEncode:], input)
|
||||
|
||||
if i == len(inputs)-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
startEncode += base64EncodeLen(input)
|
||||
out[startEncode] = '.'
|
||||
startEncode++
|
||||
}
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
|
|
@ -75,14 +75,13 @@ import (
|
|||
//
|
||||
// The JSON null value unmarshals into an interface, map, pointer, or slice
|
||||
// by setting that Go value to nil. Because null is often used in JSON to mean
|
||||
// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
|
||||
// “not present,” unmarshaling a JSON null into any other Go type has no effect
|
||||
// on the value and produces no error.
|
||||
//
|
||||
// When unmarshaling quoted strings, invalid UTF-8 or
|
||||
// invalid UTF-16 surrogate pairs are not treated as an error.
|
||||
// Instead, they are replaced by the Unicode replacement
|
||||
// character U+FFFD.
|
||||
//
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
// Check for well-formedness.
|
||||
// Avoids filling out half a data structure
|
||||
|
|
|
@ -58,6 +58,7 @@ import (
|
|||
// becomes a member of the object unless
|
||||
// - the field's tag is "-", or
|
||||
// - the field is empty and its tag specifies the "omitempty" option.
|
||||
//
|
||||
// The empty values are false, 0, any
|
||||
// nil pointer or interface value, and any array, slice, map, or string of
|
||||
// length zero. The object's default key string is the struct field name
|
||||
|
@ -65,28 +66,28 @@ import (
|
|||
// the struct field's tag value is the key name, followed by an optional comma
|
||||
// and options. Examples:
|
||||
//
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
//
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
//
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
//
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
//
|
||||
// The "string" option signals that a field is stored as JSON inside a
|
||||
// JSON-encoded string. It applies only to fields of string, floating point,
|
||||
// integer, or boolean types. This extra level of encoding is sometimes used
|
||||
// when communicating with JavaScript programs:
|
||||
//
|
||||
// Int64String int64 `json:",string"`
|
||||
// Int64String int64 `json:",string"`
|
||||
//
|
||||
// The key name will be used if it's a non-empty string consisting of
|
||||
// only Unicode letters, digits, dollar signs, percent signs, hyphens,
|
||||
|
@ -133,7 +134,6 @@ import (
|
|||
// JSON cannot represent cyclic data structures and Marshal does not
|
||||
// handle them. Passing cyclic structures to Marshal will result in
|
||||
// an infinite recursion.
|
||||
//
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
e := &encodeState{}
|
||||
err := e.marshal(v)
|
||||
|
|
|
@ -240,7 +240,6 @@ var _ Unmarshaler = (*RawMessage)(nil)
|
|||
// Number, for JSON numbers
|
||||
// string, for JSON string literals
|
||||
// nil, for JSON null
|
||||
//
|
||||
type Token interface{}
|
||||
|
||||
const (
|
||||
|
|
|
@ -252,13 +252,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
|
|||
|
||||
serializedProtected := mustSerializeJSON(obj.protected)
|
||||
|
||||
return fmt.Sprintf(
|
||||
"%s.%s.%s.%s.%s",
|
||||
base64.RawURLEncoding.EncodeToString(serializedProtected),
|
||||
base64.RawURLEncoding.EncodeToString(obj.recipients[0].encryptedKey),
|
||||
base64.RawURLEncoding.EncodeToString(obj.iv),
|
||||
base64.RawURLEncoding.EncodeToString(obj.ciphertext),
|
||||
base64.RawURLEncoding.EncodeToString(obj.tag)), nil
|
||||
return base64JoinWithDots(
|
||||
serializedProtected,
|
||||
obj.recipients[0].encryptedKey,
|
||||
obj.iv,
|
||||
obj.ciphertext,
|
||||
obj.tag,
|
||||
), nil
|
||||
}
|
||||
|
||||
// FullSerialize serializes an object using the full JSON serialization format.
|
||||
|
|
|
@ -67,9 +67,21 @@ type rawJSONWebKey struct {
|
|||
X5tSHA256 string `json:"x5t#S256,omitempty"`
|
||||
}
|
||||
|
||||
// JSONWebKey represents a public or private key in JWK format.
|
||||
// JSONWebKey represents a public or private key in JWK format. It can be
|
||||
// marshaled into JSON and unmarshaled from JSON.
|
||||
type JSONWebKey struct {
|
||||
// Cryptographic key, can be a symmetric or asymmetric key.
|
||||
// Key is the Go in-memory representation of this key. It must have one
|
||||
// of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - ed25519.PrivateKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PublicKey
|
||||
// - *rsa.PrivateKey
|
||||
// - []byte (a symmetric key)
|
||||
//
|
||||
// When marshaling this JSONWebKey into JSON, the "kty" header parameter
|
||||
// will be automatically set based on the type of this field.
|
||||
Key interface{}
|
||||
// Key identifier, parsed from `kid` header.
|
||||
KeyID string
|
||||
|
@ -389,6 +401,8 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
|||
input, err = rsaThumbprintInput(key.N, key.E)
|
||||
case ed25519.PrivateKey:
|
||||
input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
|
||||
case OpaqueSigner:
|
||||
return key.Public().Thumbprint(hash)
|
||||
default:
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||
}
|
||||
|
|
|
@ -314,15 +314,18 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
|
|||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected))
|
||||
payload := ""
|
||||
signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature)
|
||||
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
|
||||
|
||||
var payload []byte
|
||||
if !detached {
|
||||
payload = base64.RawURLEncoding.EncodeToString(obj.payload)
|
||||
payload = obj.payload
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s.%s.%s", serializedProtected, payload, signature), nil
|
||||
return base64JoinWithDots(
|
||||
serializedProtected,
|
||||
payload,
|
||||
obj.Signatures[0].Signature,
|
||||
), nil
|
||||
}
|
||||
|
||||
// CompactSerialize serializes an object using the compact serialization format.
|
||||
|
|
|
@ -121,7 +121,7 @@ func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
|||
return oke.encrypter.encryptKey(cek, alg)
|
||||
}
|
||||
|
||||
//OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
|
||||
// OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
|
||||
type OpaqueKeyDecrypter interface {
|
||||
DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
|
||||
}
|
||||
|
|
|
@ -183,8 +183,13 @@ type Header struct {
|
|||
// Unverified certificate chain parsed from x5c header.
|
||||
certificates []*x509.Certificate
|
||||
|
||||
// Any headers not recognised above get unmarshalled
|
||||
// from JSON in a generic manner and placed in this map.
|
||||
// At parse time, each header parameter with a name other than "kid",
|
||||
// "jwk", "alg", "nonce", or "x5c" will have its value passed to
|
||||
// [json.Unmarshal] to unmarshal it into an interface value.
|
||||
// The resulting value will be stored in this map, with the header
|
||||
// parameter name as the key.
|
||||
//
|
||||
// [json.Unmarshal]: https://pkg.go.dev/encoding/json#Unmarshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,15 @@ type Signer interface {
|
|||
}
|
||||
|
||||
// SigningKey represents an algorithm/key used to sign a message.
|
||||
//
|
||||
// Key must have one of these types:
|
||||
// - ed25519.PrivateKey
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PrivateKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (an HMAC key)
|
||||
// - Any type that satisfies the OpaqueSigner interface
|
||||
type SigningKey struct {
|
||||
Algorithm SignatureAlgorithm
|
||||
Key interface{}
|
||||
|
@ -52,12 +61,22 @@ type SignerOptions struct {
|
|||
|
||||
// Optional map of additional keys to be inserted into the protected header
|
||||
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||
// additional values here. All values must be JSON-serializable.
|
||||
// additional values here.
|
||||
//
|
||||
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||
// that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||
// if necessary. It returns itself and so can be used in a fluent style.
|
||||
// if necessary, and returns the updated SignerOptions.
|
||||
//
|
||||
// The v argument will be serialized by [json.Marshal] and must be a valid
|
||||
// input to that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
|
||||
if so.ExtraHeaders == nil {
|
||||
so.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||
|
@ -173,11 +192,11 @@ func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
|||
return newVerifier(verificationKey.Key)
|
||||
case *JSONWebKey:
|
||||
return newVerifier(verificationKey.Key)
|
||||
case OpaqueVerifier:
|
||||
return &opaqueVerifier{verifier: verificationKey}, nil
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
if ov, ok := verificationKey.(OpaqueVerifier); ok {
|
||||
return &opaqueVerifier{verifier: ov}, nil
|
||||
}
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
|
||||
|
@ -204,11 +223,11 @@ func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipient
|
|||
return newJWKSigner(alg, signingKey)
|
||||
case *JSONWebKey:
|
||||
return newJWKSigner(alg, *signingKey)
|
||||
case OpaqueSigner:
|
||||
return newOpaqueSigner(alg, signingKey)
|
||||
default:
|
||||
return recipientSigInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
if signer, ok := signingKey.(OpaqueSigner); ok {
|
||||
return newOpaqueSigner(alg, signer)
|
||||
}
|
||||
return recipientSigInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
|
||||
|
@ -321,12 +340,21 @@ func (ctx *genericSigner) Options() SignerOptions {
|
|||
}
|
||||
|
||||
// Verify validates the signature on the object and returns the payload.
|
||||
// This function does not support multi-signature, if you desire multi-sig
|
||||
// This function does not support multi-signature. If you desire multi-signature
|
||||
// verification use VerifyMulti instead.
|
||||
//
|
||||
// Be careful when verifying signatures based on embedded JWKs inside the
|
||||
// payload header. You cannot assume that the key received in a payload is
|
||||
// trusted.
|
||||
//
|
||||
// The verificationKey argument must have one of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *rsa.PublicKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (an HMAC key)
|
||||
// - Any type that implements the OpaqueVerifier interface.
|
||||
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
||||
err := obj.DetachedVerify(obj.payload, verificationKey)
|
||||
if err != nil {
|
||||
|
@ -346,6 +374,9 @@ func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
|
|||
// most cases, you will probably want to use Verify instead. DetachedVerify
|
||||
// is only useful if you have a payload and signature that are separated from
|
||||
// each other.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
|
||||
key := tryJWKS(verificationKey, obj.headers()...)
|
||||
verifier, err := newVerifier(key)
|
||||
|
@ -388,6 +419,9 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
|
|||
// returns the index of the signature that was verified, along with the signature
|
||||
// object and the payload. We return the signature and index to guarantee that
|
||||
// callers are getting the verified value.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
||||
idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
|
||||
if err != nil {
|
||||
|
@ -405,6 +439,9 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa
|
|||
// DetachedVerifyMulti is only useful if you have a payload and signature that are
|
||||
// separated from each other, and the signature can have multiple signers at the
|
||||
// same time.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
|
||||
key := tryJWKS(verificationKey, obj.headers()...)
|
||||
verifier, err := newVerifier(key)
|
||||
|
|
|
@ -40,12 +40,17 @@ var RandReader = rand.Reader
|
|||
|
||||
const (
|
||||
// RFC7518 recommends a minimum of 1,000 iterations:
|
||||
// https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
||||
// - https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
||||
//
|
||||
// NIST recommends a minimum of 10,000:
|
||||
// https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||
// 1Password uses 100,000:
|
||||
// https://support.1password.com/pbkdf2/
|
||||
defaultP2C = 100000
|
||||
// - https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||
//
|
||||
// 1Password increased in 2023 from 100,000 to 650,000:
|
||||
// - https://support.1password.com/pbkdf2/
|
||||
//
|
||||
// OWASP recommended 600,000 in Dec 2022:
|
||||
// - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
|
||||
defaultP2C = 600000
|
||||
// Default salt size: 128 bits
|
||||
defaultP2SSize = 16
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@ package strfmt
|
|||
|
||||
import (
|
||||
"encoding"
|
||||
stderrors "errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
@ -117,7 +118,7 @@ func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc {
|
|||
case "datetime":
|
||||
input := data
|
||||
if len(input) == 0 {
|
||||
return nil, fmt.Errorf("empty string is an invalid datetime format")
|
||||
return nil, stderrors.New("empty string is an invalid datetime format")
|
||||
}
|
||||
return ParseDateTime(input)
|
||||
case "duration":
|
||||
|
|
|
@ -15,8 +15,120 @@
|
|||
// Package oauth implements OAuth/OIDC support for device and token flows
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// GetInteractiveSuccessHTML is the page displayed upon success when using a web browser during an interactive Oauth token flow.
|
||||
// The page will close automatically if autoclose is true with the timeout specified.
|
||||
func GetInteractiveSuccessHTML(autoclose bool, timeout int) (string, error) {
|
||||
const successTemplate = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Sigstore Authentication</title>
|
||||
<link id="favicon" rel="icon" type="image/svg"/>
|
||||
<style>
|
||||
:root { font-family: "Trebuchet MS", sans-serif; height: 100%; color: #444444; overflow: hidden; }
|
||||
body { display: flex; justify-content: center; height: 100%; margin: 0 10%; background: #FFEAD7; }
|
||||
.container { display: flex; flex-direction: column; justify-content: space-between; }
|
||||
.sigstore { color: #2F2E71; font-weight: bold; }
|
||||
.header { position: absolute; top: 30px; left: 22px; }
|
||||
.title { font-size: 3.5em; margin-bottom: 30px; animation: 750ms ease-in-out 0s 1 show; }
|
||||
.content { font-size: 1.5em; animation: 250ms hide, 750ms ease-in-out 250ms 1 show; }
|
||||
.anchor { position: relative; }
|
||||
.links { display: flex; justify-content: space-between; font-size: 1.2em; padding: 60px 0; position: absolute; bottom: 0; left: 0; right: 0; animation: 500ms hide, 750ms ease-in-out 500ms 1 show; }
|
||||
.link { color: #444444; text-decoration: none; user-select: none; }
|
||||
.link:hover { color: #6349FF; }
|
||||
.link:hover>.arrow { transform: scaleX(1.5) translateX(3px); }
|
||||
.link:hover>.sigstore { color: inherit; }
|
||||
.link, .arrow { transition: 200ms; }
|
||||
.arrow { display: inline-block; margin-left: 6px; transform: scaleX(1.5); }
|
||||
@keyframes hide { 0%, 100% { opacity: 0; } }
|
||||
@keyframes show { 0% { opacity: 0; transform: translateY(40px); } 100% { opacity: 1; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div>
|
||||
<a class="header" href="https://sigstore.dev">
|
||||
<svg id="logo" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="28.14" height="30.3">
|
||||
<circle r="7" cx="14" cy="15" fill="#FFEAD7"></circle>
|
||||
<path fill="#2F2E71" d="M27.8 10.9c-.3-1.2-.9-2.2-1.7-3.1-.6-.7-1.3-1.3-2-2-.7-.6-1.2-1.3-1.5-2.1-.2-.4-.4-.8-.7-1.2-.5-.7-1.3-1.2-2.1-1.6-1.3-.7-2.7-.9-4.2-.9-.8 0-1.6.1-2.4.3-1.2.2-2.3.7-3.4 1.3-.7.4-1.3.9-1.9 1.4-1 .8-2 1.6-2.8 2.6-.6.8-1.4 1.3-2.2 1.8-.8.4-1.4 1-2 1.6-.6.6-.9 1.3-.9 2.1 0 .6.1 1.2.2 1.7.2.9.6 1.7.9 2.6.2.5.3 1 .3 1.5s0 1-.1 1.5c-.1 1.1 0 2.3.2 3.4.2 1 .8 1.8 1.8 2.2.1.1.3.1.4.1.2.1.2.2.1.3l-.1.1c-.4.5-.7 1.1-.6 1.8.1 1.1 1.3 1.8 2.3 1.3.6-.2 1.2 0 1.4.4.1.1.1.2.2.3.2.5.4.9.7 1.3.4.5.9.7 1.6.6.4-.1.8-.2 1.2-.4.7-.4 1.3-.9 2-1.5.2-.2.4-.2.7-.2.4 0 .8.2 1.2.5.6.4 1.2.7 1.9.9 1.3.4 2.5.5 3.8.2 1.3-.3 2.4-.9 3.4-1.6.7-.5 1.2-1 1.6-1.7.4-.7.6-1.4.8-2.2.3-1.1.4-2.2.4-3.4.1-1 .2-1.9.5-2.8.2-.7.5-1.4.8-2.1.2-.6.4-1.2.5-1.9.1-1.1 0-2.1-.3-3.1zM14.9.8c.3-.1.7-.1 1-.1h.3c1.1 0 2.1.2 3.1.5.6.2 1.2.6 1.7 1s.7.9.9 1.4v.1c0 .1 0 .2-.1.2s-.1 0-.2-.1c-.4-.4-.7-.8-1.1-1.1-.6-.5-1.2-.9-2-1.1-1.1-.3-2.1-.5-3.2-.7h-.6c.1 0 .1 0 .2-.1-.1 0 0 0 0 0zm-4.5 12.4c.6 0 1.1.5 1.2 1.2 0 .6-.5 1.2-1.2 1.2-.6 0-1.2-.5-1.1-1.2 0-.7.5-1.2 1.1-1.2zm3.8 1.3v-3.4c0-2.3 2-3.1 3.6-2.5.3.1.6.3.9.5.2.2.2.5.1.8-.2.2-.4.3-.7.1-.2-.1-.5-.2-.7-.3-.6-.2-1.3 0-1.6.4-.1.2-.2.4-.2.7-.1.5 0 .9 0 1.4v5.9c0 1.2-.6 2.1-1.8 2.4-1 .3-1.9.2-2.7-.6-.2-.2-.3-.5-.1-.7.1-.2.4-.3.7-.2.3.1.6.3.9.4 1 .1 1.7-.3 1.7-1.4-.1-1.2-.1-2.3-.1-3.5zm-8.8 7.6h-.1c-.1-.1-.2-.1-.3-.2-.2-.2-.4-.3-.6-.5-.3-.3-.5-.6-.7-1-.4-.8-.8-1.7-1-2.7-.1-.5-.2-1-.2-1.5s-.1-1-.2-1.4c-.1-.7-.2-1.5-.2-2.2 0-.9.1-1.7.4-2.5.3-.9.7-1.7 1.4-2.4.6-.6 1.1-1.2 1.7-1.8.1-.1.3-.2.4-.2 0 .1-.1.3-.2.4-.3.4-.6.7-.9 1.1-.5.6-.9 1.2-1.2 1.8-.4.7-.7 1.4-.9 2.2-.1.4-.2.8-.2 1.2 0 .4-.1.8 0 1.3 0 .6.1 1.1.2 1.6.1.6.2 1.1.2 1.7 0 .7.2 1.4.4 2.1 0 .2.2.3.2.5.3.6.6 1.1 1.1 1.5.2.2.4.5.6.7 0 0 0 .1.1.1v.2zM8 24.6c-.4 0-.7.1-1.1.2-.4.1-.6-.1-.7-.5 0-.1-.1-.3 0-.4.1-.3.3-.3.5-.1.2.2.5.4.7.5.1.1.2.1.4.1.1 0 .2.1.4.2H8zm7.6 2.1c-.3.2-.7.3-1.1.3-.3 0-.6-.1-.9-.1h-.2c-.4.1-.7.1-1.1.2-.1 0-.3 0-.4.1H11c-.4 0-.7-.2-1-.5-.1-.1-.2-.3-.3-.5-.1-.1-.1-.2-.1-.4 0-.1.1-.1.2-.1h.1c.5.3 1.1.4 1.6.5.7.1 1.4.2 2.1.2.4 0 .7.1 1.1.1h.8c.2.1.1.1.1.2zm3.7-2.5c-.7.4-1.5.7-2.3.9-.2 0-.5.1-.7.1-.2 0-.5 0-.7.1-.4.1-.8 0-1.2 0-.3 0-.6-.1-.9 0h-.2c-.4-.1-.9-.2-1.3-.3-.5-.1-1-.3-1.4-.5-.4-.1-.8-.3-1.1-.5-.2-.1-.4-.3-.6-.4-.6-.6-1.2-1.1-1.7-1.6-.4-.5-.8-.9-1.2-1.4-.4-.6-.7-1.2-1-1.9l-.3-.9c-.1-.3-.2-.5-.2-.8v-.8c.3.8.5 1.7.9 2.5.7 1.6 1.7 3 3 4.1 1.4 1.1 2.9 1.8 4.6 2.1.9.2 1.8.2 2.7.2 1.1-.1 2.2-.3 3.2-.8.2-.1.3-.2.5-.2 0 .1 0 .1-.1.1zm.1-8.7c-.6 0-1.1-.5-1.1-1.2 0-.6.5-1.2 1.2-1.2.6 0 1.1.5 1.1 1.2s-.5 1.3-1.2 1.2zm6.2 5.7c0 .4-.1.8-.2 1.2-.1.4-.1.9-.3 1.3-.1.4-.2.7-.4 1.1-.1.3-.3.6-.6.8-.3.2-.5.4-.9.5-.4.2-.7.3-1.2.3h-.9c-.2-.1-.2-.1-.1-.3.1-.2.3-.3.5-.4.3-.2.6-.5.8-.7.7-.7 1.3-1.6 1.9-2.4.4-.4.6-1 .9-1.5.1-.1.1-.2.2-.3.3.2.3.3.3.4zm-15-16.8c1.7-.8 3.5-1.1 5.3-.9.4 0 .8.1 1.1.3l1.8.6c.6.2 1.2.5 1.7.8.7.4 1.3.9 1.9 1.5.8.8 1.5 1.6 2 2.6.3.6.5 1.2.7 1.8.2.7.4 1.5.4 2.2v.9c0 .4-.1.8-.1 1.2v-1c0-1.2-.3-2.3-.6-3.4l-.6-1.5c-.2-.6-.5-1.1-.9-1.6-.1-.1-.3-.1-.4-.2-.1 0-.1 0-.2-.1-.5-.5-1.1-1-1.7-1.5-.8-.6-1.7-1.1-2.6-1.4-.4-.2-.8-.3-1.2-.4-.9-.2-1.8-.4-2.7-.3h-.9c-.3 0-.6.1-1 .2-.6.1-1.2.3-1.7.5h-.1s-.1 0 0-.1c0 0 0-.1-.1-.2m16.2 11.1c-.1-.8 0-1.7 0-2.5-.1-.8-.2-1.6-.4-2.4.5.7.6 1.6.7 2.4 0 .8 0 1.7-.3 2.5zm.6.5c0-.3.1-.7.2-1.1.1-.4.1-.9.1-1.3v-.4c0-.8-.2-1.6-.4-2.4-.4-.9-.8-1.6-1.4-2.4-.5-.6-.9-1.2-1.4-1.8l-.2-.2c.1 0 .1 0 .1.1 1 .8 1.8 1.6 2.4 2.7.5 1 .9 2 1 3.1.3 1.3.1 2.5-.4 3.7z"/>
|
||||
</svg><svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="120" height="30.3" viewBox="28.14 0 120 30.3">
|
||||
<path fill="#2F2E71" d="M57.7 18c.9 0 1.9-.1 2.9.3.9.3 1.5.9 1.7 2 .1 1-.2 1.9-1.1 2.5-1.1.8-2.3.9-3.6 1-1.4 0-2.9 0-4.3-.6-1.6-.7-1.8-2.6-.4-3.6.3-.2.2-.3.1-.5-.7-.8-.7-2.2.3-2.8.3-.2.2-.3 0-.6-1.4-1.6-.7-4.1 1.3-4.8 1.6-.6 3.2-.6 4.8-.1.2.1.3.1.5-.1.3-.3.6-.5.9-.7.5-.3 1.1-.3 1.4 0 .3.4.3.9-.2 1.3-.7.5-.8 1-.6 1.9.4 1.5-.6 2.9-2.1 3.4-1.3.5-2.7.5-4 .2-.3-.1-.5-.1-.6.2-.1.3-.1.6.2.8.2.1.5.2.8.2h2zm-.6-2.7c.3 0 .5 0 .7-.1.8-.2 1.3-.7 1.4-1.4.1-.7-.3-1.3-.9-1.6-.8-.3-1.6-.3-2.4 0-1 .4-1.2 1.7-.6 2.4.5.6 1.2.7 1.8.7zm-.2 4.6h-1.8c-.4 0-.6.2-.7.5-.3.7.1 1.2.9 1.4 1.2.2 2.5.2 3.7-.1l.6-.3c.5-.3.4-1.1-.1-1.3-.2-.1-.5-.2-.7-.2h-1.9zm58.6-3.3h-3.2c-.3 0-.3.1-.3.4.2 1.2 1.3 2.1 2.8 2.3 1.1.1 2.1-.1 2.9-.9.2-.2.4-.3.6-.4.4-.2.8-.2 1.1.1.4.3.4.7.3 1.1-.3.9-.9 1.4-1.7 1.8-2.3 1-4.5.9-6.5-.6-1-.7-1.5-1.8-1.7-3-.3-1.7-.2-3.3.8-4.7 1.3-1.8 3.1-2.4 5.2-2.1 2 .3 3.4 1.3 4 3.2.2.6.3 1.2.2 1.8-.1.8-.4 1.1-1.2 1.1-1.1-.1-2.2-.1-3.3-.1zm-.7-1.9h2.4c.4 0 .4-.1.4-.5-.3-1.1-1.2-1.9-2.5-2-1.5-.1-2.6.6-3.1 1.9-.2.5-.1.6.4.6h2.4zm-23 6.7c-3.3 0-5.5-2.2-5.6-5.5 0-3.2 2.2-5.6 5.4-5.6 3.4 0 5.7 2.2 5.8 5.5 0 3.4-2.2 5.6-5.6 5.6zm0-2.1c1.9 0 3.2-1.3 3.3-3.3.1-2-1.3-3.4-3.2-3.4-1.8 0-3.2 1.4-3.2 3.3-.1 1.9 1.2 3.4 3.1 3.4zm-22.6 2.1c-1.1 0-2.4-.3-3.5-1.4-.3-.4-.6-.8-.7-1.3 0-.4.1-.7.4-.9.3-.2.7-.2 1 0 .3.2.6.4.8.6.9.9 2 1.1 3.2.9.6-.1 1-.5 1-1 .1-.5-.2-1-.8-1.2-.7-.3-1.4-.3-2.1-.5-.8-.2-1.6-.4-2.2-.9-1.5-1.2-1.4-3.5.2-4.6 1.2-.8 2.6-.9 4-.7 1 .1 1.9.5 2.6 1.2.3.3.4.6.5.9.1.4 0 .7-.3 1-.3.3-.7.3-1 .1-.4-.2-.7-.5-1.1-.8-.8-.6-1.7-.8-2.7-.5-.6.1-.9.5-.9 1s.3.9.8 1.1c.9.3 1.9.4 2.9.7.6.2 1.1.4 1.5.8 1.5 1.4 1.1 4.1-.9 5.1-.7.3-1.5.4-2.7.4zm-30.3 0c-1.5 0-3-.3-4.1-1.5-.3-.3-.4-.6-.5-1-.1-.4-.1-.8.3-1.1.4-.2.9-.2 1.3.1.3.2.6.5.8.7.9.8 1.9.9 3 .7.6-.1.9-.5.9-1.1 0-.5-.3-1-.8-1.2l-2.7-.6c-1.1-.3-2-.8-2.4-2-.6-1.7.4-3.4 2.2-3.9 1.7-.5 3.3-.3 4.8.5.6.3 1 .8 1.2 1.4.1.4.1.9-.3 1.1-.4.3-.8.2-1.2-.1-.4-.3-.7-.7-1.2-.9-.8-.4-1.5-.5-2.4-.3-.5.1-.8.4-.8.9s.2.8.7 1c.7.3 1.4.3 2.1.5.8.2 1.5.3 2.2.8 1.2.8 1.5 2.5.9 3.8-.7 1.4-1.9 1.8-3.3 2-.3.2-.5.2-.7.2zM78 15.8v-2.6c0-.3-.1-.4-.4-.4h-1.3c-.6-.1-.9-.5-.9-1s.4-1 .9-1h1.3c.3 0 .4-.1.4-.4V8.9c0-.7.5-1.1 1.1-1.2.6 0 1.1.4 1.2 1v.6c0 .4-.2 1 .1 1.3.3.3.9.1 1.3.1h1.6c.4 0 .7.3.8.8.1.4-.1.8-.4 1.1-.3.2-.6.2-.9.2h-2.1c-.3 0-.4 0-.4.4v4.7c0 1.1.9 1.6 1.9 1.1.3-.1.5-.3.7-.5.4-.3.8-.3 1.2 0 .4.3.4.8.2 1.2-.3.7-.9 1.1-1.5 1.3-1.3.5-2.6.5-3.8-.4-.7-.6-1-1.4-1.1-2.4.1-.7.1-1.6.1-2.4zm24.7-4.1c.8-1 1.8-1.4 3-1.3.7.1 1.4.3 1.9.9.3.4.5.9.4 1.5-.1.4-.3.7-.7.9-.5.2-.9 0-1.3-.3-.7-.7-1.3-.9-2.1-.5-.5.3-.8.7-1 1.3-.2.5-.3 1.1-.3 1.6v4.5c0 .5-.2.9-.6 1.1-.4.2-.8.2-1.2-.1-.4-.3-.5-.7-.5-1.1v-8.4c0-.7.4-1.2 1-1.3.7-.1 1.1.3 1.3 1.1.1-.1.1 0 .1.1zm-54 4.2v4.3c0 .8-.6 1.3-1.4 1.2-.5-.1-.9-.5-.9-1.1v-8.7c0-.7.5-1.1 1.2-1.1s1.1.4 1.2 1.2c-.1 1.3-.1 2.8-.1 4.2zm.3-8.2c0 .8-.6 1.4-1.4 1.4-.8 0-1.5-.6-1.5-1.4 0-.8.7-1.4 1.5-1.4s1.4.6 1.4 1.4z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<div class="title">
|
||||
<span class="sigstore">sigstore </span>
|
||||
<span>authentication successful!</span>
|
||||
</div>
|
||||
{{ if .Autoclose -}}
|
||||
<small name="autoclose"></small>
|
||||
<noscript>
|
||||
<div class="content">
|
||||
<span>You may now close this page.</span>
|
||||
</div>
|
||||
</noscript>
|
||||
{{- else -}}
|
||||
<div class="content">
|
||||
<span>You may now close this page.</span>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
<div class="anchor">
|
||||
<div class="links">
|
||||
<a href="https://sigstore.dev/" class="link login"><span class="sigstore">sigstore</span> home <span class="arrow">→</span></a>
|
||||
<a href="https://docs.sigstore.dev/" class="link login"><span class="sigstore">sigstore</span> documentation <span class="arrow">→</span></a>
|
||||
<a href="https://blog.sigstore.dev/" class="link"><span class="sigstore">sigstore</span> blog <span class="arrow">→</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById("favicon").setAttribute("href", "data:image/svg+xml," + encodeURIComponent(document.getElementById("logo").outerHTML));
|
||||
</script>
|
||||
|
||||
{{ if .Autoclose -}}
|
||||
<script>
|
||||
var timeout = {{ .Timeout }};
|
||||
setTimeout(function() { this.close(); }, timeout*1000);
|
||||
setInterval(function() {
|
||||
timeout--;
|
||||
document.getElementsByName("autoclose")[0].innerHTML = "This page will close automatically in " + timeout + " seconds...";
|
||||
if (timeout <= 0) {
|
||||
document.getElementsByName("autoclose")[0].innerHTML = "This page will close now, thank you!";
|
||||
}
|
||||
}, 1000);
|
||||
</script>
|
||||
{{- end }}
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
// Parse the template
|
||||
tmpl, err := template.New("success").Parse(successTemplate)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing success template: %w", err)
|
||||
}
|
||||
// Pass autoclose and timeout to the template
|
||||
data := struct {
|
||||
Autoclose bool
|
||||
Timeout int
|
||||
}{
|
||||
autoclose,
|
||||
timeout,
|
||||
}
|
||||
var htmlPage bytes.Buffer
|
||||
if err := tmpl.Execute(&htmlPage, data); err != nil {
|
||||
return "", fmt.Errorf("error executing template: %w", err)
|
||||
}
|
||||
return htmlPage.String(), nil
|
||||
}
|
||||
|
||||
const (
|
||||
// InteractiveSuccessHTML is the page displayed upon success when using a web browser during an interactive Oauth token flow.
|
||||
// InteractiveSuccessHTML (deprecated) is the page displayed upon success when using a web browser during an interactive Oauth token flow.
|
||||
InteractiveSuccessHTML = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
|
156
vendor/github.com/sigstore/sigstore/pkg/oauthflow/client_credentials.go
generated
vendored
Normal file
156
vendor/github.com/sigstore/sigstore/pkg/oauthflow/client_credentials.go
generated
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
//
|
||||
// Copyright 2024 The Sigstore 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 oauthflow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// CodeURL fetches the client credentials token authorization endpoint URL from the provider's well-known configuration endpoint
|
||||
func (d *DefaultFlowClientCredentials) CodeURL() (string, error) {
|
||||
if d.codeURL != "" {
|
||||
return d.codeURL, nil
|
||||
}
|
||||
|
||||
wellKnown := strings.TrimSuffix(d.Issuer, "/") + "/.well-known/openid-configuration"
|
||||
/* #nosec */
|
||||
httpClient := &http.Client{
|
||||
Timeout: 3 * time.Second,
|
||||
}
|
||||
resp, err := httpClient.Get(wellKnown)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to read response body: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("%s: %s", resp.Status, body)
|
||||
}
|
||||
|
||||
providerConfig := struct {
|
||||
Issuer string `json:"issuer"`
|
||||
TokenEndpoint string `json:"token_endpoint"`
|
||||
}{}
|
||||
if err = json.Unmarshal(body, &providerConfig); err != nil {
|
||||
return "", fmt.Errorf("oidc: failed to decode provider discovery object: %w", err)
|
||||
}
|
||||
|
||||
if d.Issuer != providerConfig.Issuer {
|
||||
return "", fmt.Errorf("oidc: issuer did not match the issuer returned by provider, expected %q got %q", d.Issuer, providerConfig.Issuer)
|
||||
}
|
||||
|
||||
if providerConfig.TokenEndpoint == "" {
|
||||
return "", fmt.Errorf("oidc: client credentials token authorization endpoint not returned by provider")
|
||||
}
|
||||
|
||||
d.codeURL = providerConfig.TokenEndpoint
|
||||
return d.codeURL, nil
|
||||
}
|
||||
|
||||
// DefaultFlowClientCredentials fetches an OIDC Identity token using the Client Credentials Grant flow as specified in RFC8628
|
||||
type DefaultFlowClientCredentials struct {
|
||||
Issuer string
|
||||
codeURL string
|
||||
}
|
||||
|
||||
// NewClientCredentialsFlow creates a new DefaultFlowClientCredentials that retrieves an OIDC Identity Token using a Client Credentials Grant
|
||||
func NewClientCredentialsFlow(issuer string) *DefaultFlowClientCredentials {
|
||||
return &DefaultFlowClientCredentials{
|
||||
Issuer: issuer,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DefaultFlowClientCredentials) clientCredentialsFlow(_ *oidc.Provider, clientID, clientSecret, redirectURL string) (string, error) {
|
||||
data := url.Values{
|
||||
"client_id": []string{clientID},
|
||||
"client_secret": []string{clientSecret},
|
||||
"scope": []string{"openid email"},
|
||||
"grant_type": []string{"client_credentials"},
|
||||
}
|
||||
if redirectURL != "" {
|
||||
// If a redirect uri is provided then use it
|
||||
data["redirect_uri"] = []string{redirectURL}
|
||||
}
|
||||
|
||||
codeURL, err := d.CodeURL()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
/* #nosec */
|
||||
resp, err := http.PostForm(codeURL, data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("%s: %s", resp.Status, b)
|
||||
}
|
||||
|
||||
tr := tokenResp{}
|
||||
if err := json.Unmarshal(b, &tr); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if tr.IDToken != "" {
|
||||
fmt.Println("Token received!")
|
||||
return tr.IDToken, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unexpected error in client flow: %s", tr.Error)
|
||||
}
|
||||
|
||||
// GetIDToken gets an OIDC ID Token from the specified provider using the Client Credentials Grant flow
|
||||
func (d *DefaultFlowClientCredentials) GetIDToken(p *oidc.Provider, cfg oauth2.Config) (*OIDCIDToken, error) {
|
||||
idToken, err := d.clientCredentialsFlow(p, cfg.ClientID, cfg.ClientSecret, cfg.RedirectURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
verifier := p.Verifier(&oidc.Config{ClientID: cfg.ClientID})
|
||||
parsedIDToken, err := verifier.Verify(context.Background(), idToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subj, err := SubjectFromToken(parsedIDToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OIDCIDToken{
|
||||
RawString: idToken,
|
||||
Subject: subj,
|
||||
}, nil
|
||||
}
|
|
@ -19,6 +19,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/go-jose/go-jose/v3"
|
||||
|
@ -46,6 +47,17 @@ type OIDCIDToken struct {
|
|||
Subject string // Subject is the extracted subject from the raw token
|
||||
}
|
||||
|
||||
// init
|
||||
func init() {
|
||||
// set the default HTML page for the DefaultIDTokenGetter
|
||||
htmlPage, err := soauth.GetInteractiveSuccessHTML(false, 10)
|
||||
if err != nil {
|
||||
log.Print("failed to get interactive success html, defaulting to original static page")
|
||||
} else {
|
||||
DefaultIDTokenGetter.HTMLPage = htmlPage
|
||||
}
|
||||
}
|
||||
|
||||
// ConnectorIDOpt requests the value of prov as a the connector_id (either on URL or in form body) on the initial request;
|
||||
// this is used by Dex
|
||||
func ConnectorIDOpt(prov string) oauth2.AuthCodeOption {
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
//
|
||||
// Copyright 2024 The Sigstore 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 signature
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/sigstore/sigstore/pkg/signature/options"
|
||||
)
|
||||
|
||||
var ed25519phSupportedHashFuncs = []crypto.Hash{
|
||||
crypto.SHA512,
|
||||
}
|
||||
|
||||
// ED25519phSigner is a signature.Signer that uses the Ed25519 public-key signature system with pre-hashing
|
||||
type ED25519phSigner struct {
|
||||
priv ed25519.PrivateKey
|
||||
}
|
||||
|
||||
// LoadED25519phSigner calculates signatures using the specified private key.
|
||||
func LoadED25519phSigner(priv ed25519.PrivateKey) (*ED25519phSigner, error) {
|
||||
if priv == nil {
|
||||
return nil, errors.New("invalid ED25519 private key specified")
|
||||
}
|
||||
|
||||
return &ED25519phSigner{
|
||||
priv: priv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ToED25519SignerVerifier creates a ED25519SignerVerifier from a ED25519phSignerVerifier
|
||||
//
|
||||
// Clients that use ED25519phSignerVerifier should use this method to get a
|
||||
// SignerVerifier that uses the same ED25519 private key, but with the Pure
|
||||
// Ed25519 algorithm. This might be necessary to interact with Fulcio, which
|
||||
// only supports the Pure Ed25519 algorithm.
|
||||
func (e ED25519phSignerVerifier) ToED25519SignerVerifier() (*ED25519SignerVerifier, error) {
|
||||
return LoadED25519SignerVerifier(e.priv)
|
||||
}
|
||||
|
||||
// SignMessage signs the provided message. If the message is provided,
|
||||
// this method will compute the digest according to the hash function specified
|
||||
// when the ED25519phSigner was created.
|
||||
//
|
||||
// This function recognizes the following Options listed in order of preference:
|
||||
//
|
||||
// - WithDigest()
|
||||
//
|
||||
// All other options are ignored if specified.
|
||||
func (e ED25519phSigner) SignMessage(message io.Reader, opts ...SignOption) ([]byte, error) {
|
||||
digest, _, err := ComputeDigestForSigning(message, crypto.SHA512, ed25519phSupportedHashFuncs, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e.priv.Sign(nil, digest, crypto.SHA512)
|
||||
}
|
||||
|
||||
// Public returns the public key that can be used to verify signatures created by
|
||||
// this signer.
|
||||
func (e ED25519phSigner) Public() crypto.PublicKey {
|
||||
if e.priv == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return e.priv.Public()
|
||||
}
|
||||
|
||||
// PublicKey returns the public key that can be used to verify signatures created by
|
||||
// this signer. As this value is held in memory, all options provided in arguments
|
||||
// to this method are ignored.
|
||||
func (e ED25519phSigner) PublicKey(_ ...PublicKeyOption) (crypto.PublicKey, error) {
|
||||
return e.Public(), nil
|
||||
}
|
||||
|
||||
// Sign computes the signature for the specified message; the first and third arguments to this
|
||||
// function are ignored as they are not used by the ED25519ph algorithm.
|
||||
func (e ED25519phSigner) Sign(_ io.Reader, digest []byte, _ crypto.SignerOpts) ([]byte, error) {
|
||||
return e.SignMessage(nil, options.WithDigest(digest))
|
||||
}
|
||||
|
||||
// ED25519phVerifier is a signature.Verifier that uses the Ed25519 public-key signature system
|
||||
type ED25519phVerifier struct {
|
||||
publicKey ed25519.PublicKey
|
||||
}
|
||||
|
||||
// LoadED25519phVerifier returns a Verifier that verifies signatures using the
|
||||
// specified ED25519 public key.
|
||||
func LoadED25519phVerifier(pub ed25519.PublicKey) (*ED25519phVerifier, error) {
|
||||
if pub == nil {
|
||||
return nil, errors.New("invalid ED25519 public key specified")
|
||||
}
|
||||
|
||||
return &ED25519phVerifier{
|
||||
publicKey: pub,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PublicKey returns the public key that is used to verify signatures by
|
||||
// this verifier. As this value is held in memory, all options provided in arguments
|
||||
// to this method are ignored.
|
||||
func (e *ED25519phVerifier) PublicKey(_ ...PublicKeyOption) (crypto.PublicKey, error) {
|
||||
return e.publicKey, nil
|
||||
}
|
||||
|
||||
// VerifySignature verifies the signature for the given message. Unless provided
|
||||
// in an option, the digest of the message will be computed using the hash function specified
|
||||
// when the ED25519phVerifier was created.
|
||||
//
|
||||
// This function returns nil if the verification succeeded, and an error message otherwise.
|
||||
//
|
||||
// This function recognizes the following Options listed in order of preference:
|
||||
//
|
||||
// - WithDigest()
|
||||
//
|
||||
// All other options are ignored if specified.
|
||||
func (e *ED25519phVerifier) VerifySignature(signature, message io.Reader, opts ...VerifyOption) error {
|
||||
if signature == nil {
|
||||
return errors.New("nil signature passed to VerifySignature")
|
||||
}
|
||||
|
||||
digest, _, err := ComputeDigestForVerifying(message, crypto.SHA512, ed25519phSupportedHashFuncs, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sigBytes, err := io.ReadAll(signature)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading signature: %w", err)
|
||||
}
|
||||
|
||||
if err := ed25519.VerifyWithOptions(e.publicKey, digest, sigBytes, &ed25519.Options{Hash: crypto.SHA512}); err != nil {
|
||||
return fmt.Errorf("failed to verify signature: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ED25519phSignerVerifier is a signature.SignerVerifier that uses the Ed25519 public-key signature system
|
||||
type ED25519phSignerVerifier struct {
|
||||
*ED25519phSigner
|
||||
*ED25519phVerifier
|
||||
}
|
||||
|
||||
// LoadED25519phSignerVerifier creates a combined signer and verifier. This is
|
||||
// a convenience object that simply wraps an instance of ED25519phSigner and ED25519phVerifier.
|
||||
func LoadED25519phSignerVerifier(priv ed25519.PrivateKey) (*ED25519phSignerVerifier, error) {
|
||||
signer, err := LoadED25519phSigner(priv)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("initializing signer: %w", err)
|
||||
}
|
||||
pub, ok := priv.Public().(ed25519.PublicKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("given key is not ed25519.PublicKey")
|
||||
}
|
||||
verifier, err := LoadED25519phVerifier(pub)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("initializing verifier: %w", err)
|
||||
}
|
||||
|
||||
return &ED25519phSignerVerifier{
|
||||
ED25519phSigner: signer,
|
||||
ED25519phVerifier: verifier,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewDefaultED25519phSignerVerifier creates a combined signer and verifier using ED25519.
|
||||
// This creates a new ED25519 key using crypto/rand as an entropy source.
|
||||
func NewDefaultED25519phSignerVerifier() (*ED25519phSignerVerifier, ed25519.PrivateKey, error) {
|
||||
return NewED25519phSignerVerifier(rand.Reader)
|
||||
}
|
||||
|
||||
// NewED25519phSignerVerifier creates a combined signer and verifier using ED25519.
|
||||
// This creates a new ED25519 key using the specified entropy source.
|
||||
func NewED25519phSignerVerifier(rand io.Reader) (*ED25519phSignerVerifier, ed25519.PrivateKey, error) {
|
||||
_, priv, err := ed25519.GenerateKey(rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sv, err := LoadED25519phSignerVerifier(priv)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return sv, priv, nil
|
||||
}
|
||||
|
||||
// PublicKey returns the public key that is used to verify signatures by
|
||||
// this verifier. As this value is held in memory, all options provided in arguments
|
||||
// to this method are ignored.
|
||||
func (e ED25519phSignerVerifier) PublicKey(_ ...PublicKeyOption) (crypto.PublicKey, error) {
|
||||
return e.publicKey, nil
|
||||
}
|
|
@ -18,6 +18,7 @@ package signature
|
|||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"io"
|
||||
|
||||
"github.com/sigstore/sigstore/pkg/signature/options"
|
||||
|
@ -55,3 +56,10 @@ type VerifyOption interface {
|
|||
RPCOption
|
||||
MessageOption
|
||||
}
|
||||
|
||||
// LoadOption specifies options to be used when creating a Signer/Verifier
|
||||
type LoadOption interface {
|
||||
ApplyHash(*crypto.Hash)
|
||||
ApplyED25519ph(*bool)
|
||||
ApplyRSAPSS(**rsa.PSSOptions)
|
||||
}
|
||||
|
|
76
vendor/github.com/sigstore/sigstore/pkg/signature/options/loadoptions.go
generated
vendored
Normal file
76
vendor/github.com/sigstore/sigstore/pkg/signature/options/loadoptions.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// Copyright 2024 The Sigstore 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 options
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
)
|
||||
|
||||
// RequestHash implements the functional option pattern for setting a Hash
|
||||
// function when loading a signer or verifier
|
||||
type RequestHash struct {
|
||||
NoOpOptionImpl
|
||||
hashFunc crypto.Hash
|
||||
}
|
||||
|
||||
// ApplyHash sets the hash as requested by the functional option
|
||||
func (r RequestHash) ApplyHash(hash *crypto.Hash) {
|
||||
*hash = r.hashFunc
|
||||
}
|
||||
|
||||
// WithHash specifies that the given hash function should be used when loading a signer or verifier
|
||||
func WithHash(hash crypto.Hash) RequestHash {
|
||||
return RequestHash{hashFunc: hash}
|
||||
}
|
||||
|
||||
// RequestED25519ph implements the functional option pattern for specifying
|
||||
// ED25519ph (pre-hashed) should be used when loading a signer or verifier and a
|
||||
// ED25519 key is
|
||||
type RequestED25519ph struct {
|
||||
NoOpOptionImpl
|
||||
useED25519ph bool
|
||||
}
|
||||
|
||||
// ApplyED25519ph sets the ED25519ph flag as requested by the functional option
|
||||
func (r RequestED25519ph) ApplyED25519ph(useED25519ph *bool) {
|
||||
*useED25519ph = r.useED25519ph
|
||||
}
|
||||
|
||||
// WithED25519ph specifies that the ED25519ph algorithm should be used when a ED25519 key is used
|
||||
func WithED25519ph() RequestED25519ph {
|
||||
return RequestED25519ph{useED25519ph: true}
|
||||
}
|
||||
|
||||
// RequestPSSOptions implements the functional option pattern for specifying RSA
|
||||
// PSS should be used when loading a signer or verifier and a RSA key is
|
||||
// detected
|
||||
type RequestPSSOptions struct {
|
||||
NoOpOptionImpl
|
||||
opts *rsa.PSSOptions
|
||||
}
|
||||
|
||||
// ApplyRSAPSS sets the RSAPSS options as requested by the functional option
|
||||
func (r RequestPSSOptions) ApplyRSAPSS(opts **rsa.PSSOptions) {
|
||||
*opts = r.opts
|
||||
}
|
||||
|
||||
// WithRSAPSS specifies that the RSAPSS algorithm should be used when a RSA key is used
|
||||
// Note that the RSA PSSOptions contains an hash algorithm, which will override
|
||||
// the hash function specified with WithHash.
|
||||
func WithRSAPSS(opts *rsa.PSSOptions) RequestPSSOptions {
|
||||
return RequestPSSOptions{opts: opts}
|
||||
}
|
|
@ -18,6 +18,7 @@ package options
|
|||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
@ -47,3 +48,12 @@ func (NoOpOptionImpl) ApplyKeyVersion(_ *string) {}
|
|||
|
||||
// ApplyKeyVersionUsed is a no-op required to fully implement the requisite interfaces
|
||||
func (NoOpOptionImpl) ApplyKeyVersionUsed(_ **string) {}
|
||||
|
||||
// ApplyHash is a no-op required to fully implement the requisite interfaces
|
||||
func (NoOpOptionImpl) ApplyHash(_ *crypto.Hash) {}
|
||||
|
||||
// ApplyED25519ph is a no-op required to fully implement the requisite interfaces
|
||||
func (NoOpOptionImpl) ApplyED25519ph(_ *bool) {}
|
||||
|
||||
// ApplyRSAPSS is a no-op required to fully implement the requisite interfaces
|
||||
func (NoOpOptionImpl) ApplyRSAPSS(_ **rsa.PSSOptions) {}
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
_ "crypto/sha512"
|
||||
|
||||
"github.com/sigstore/sigstore/pkg/cryptoutils"
|
||||
"github.com/sigstore/sigstore/pkg/signature/options"
|
||||
|
||||
// these ensure we have the implementations loaded
|
||||
_ "golang.org/x/crypto/sha3"
|
||||
|
@ -59,12 +60,33 @@ func (s SignerOpts) HashFunc() crypto.Hash {
|
|||
// If privateKey is an RSA key, a RSAPKCS1v15Signer will be returned. If a
|
||||
// RSAPSSSigner is desired instead, use the LoadRSAPSSSigner() method directly.
|
||||
func LoadSigner(privateKey crypto.PrivateKey, hashFunc crypto.Hash) (Signer, error) {
|
||||
return LoadSignerWithOpts(privateKey, options.WithHash(hashFunc))
|
||||
}
|
||||
|
||||
// LoadSignerWithOpts returns a signature.Signer based on the algorithm of the private key
|
||||
// provided.
|
||||
func LoadSignerWithOpts(privateKey crypto.PrivateKey, opts ...LoadOption) (Signer, error) {
|
||||
var rsaPSSOptions *rsa.PSSOptions
|
||||
var useED25519ph bool
|
||||
hashFunc := crypto.SHA256
|
||||
for _, o := range opts {
|
||||
o.ApplyED25519ph(&useED25519ph)
|
||||
o.ApplyHash(&hashFunc)
|
||||
o.ApplyRSAPSS(&rsaPSSOptions)
|
||||
}
|
||||
|
||||
switch pk := privateKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
if rsaPSSOptions != nil {
|
||||
return LoadRSAPSSSigner(pk, hashFunc, rsaPSSOptions)
|
||||
}
|
||||
return LoadRSAPKCS1v15Signer(pk, hashFunc)
|
||||
case *ecdsa.PrivateKey:
|
||||
return LoadECDSASigner(pk, hashFunc)
|
||||
case ed25519.PrivateKey:
|
||||
if useED25519ph {
|
||||
return LoadED25519phSigner(pk)
|
||||
}
|
||||
return LoadED25519Signer(pk)
|
||||
}
|
||||
return nil, errors.New("unsupported public key type")
|
||||
|
@ -87,3 +109,17 @@ func LoadSignerFromPEMFile(path string, hashFunc crypto.Hash, pf cryptoutils.Pas
|
|||
}
|
||||
return LoadSigner(priv, hashFunc)
|
||||
}
|
||||
|
||||
// LoadSignerFromPEMFileWithOpts returns a signature.Signer based on the algorithm of the private key
|
||||
// in the file. The Signer will use the hash function specified in the options when computing digests.
|
||||
func LoadSignerFromPEMFileWithOpts(path string, pf cryptoutils.PassFunc, opts ...LoadOption) (Signer, error) {
|
||||
fileBytes, err := os.ReadFile(filepath.Clean(path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv, err := cryptoutils.UnmarshalPEMToPrivateKey(fileBytes, pf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return LoadSignerWithOpts(priv, opts...)
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/sigstore/sigstore/pkg/cryptoutils"
|
||||
"github.com/sigstore/sigstore/pkg/signature/options"
|
||||
)
|
||||
|
||||
// SignerVerifier creates and verifies digital signatures over a message using a specified key pair
|
||||
|
@ -39,12 +40,33 @@ type SignerVerifier interface {
|
|||
// If privateKey is an RSA key, a RSAPKCS1v15SignerVerifier will be returned. If a
|
||||
// RSAPSSSignerVerifier is desired instead, use the LoadRSAPSSSignerVerifier() method directly.
|
||||
func LoadSignerVerifier(privateKey crypto.PrivateKey, hashFunc crypto.Hash) (SignerVerifier, error) {
|
||||
return LoadSignerVerifierWithOpts(privateKey, options.WithHash(hashFunc))
|
||||
}
|
||||
|
||||
// LoadSignerVerifierWithOpts returns a signature.SignerVerifier based on the
|
||||
// algorithm of the private key provided and the user's choice.
|
||||
func LoadSignerVerifierWithOpts(privateKey crypto.PrivateKey, opts ...LoadOption) (SignerVerifier, error) {
|
||||
var rsaPSSOptions *rsa.PSSOptions
|
||||
var useED25519ph bool
|
||||
hashFunc := crypto.SHA256
|
||||
for _, o := range opts {
|
||||
o.ApplyED25519ph(&useED25519ph)
|
||||
o.ApplyHash(&hashFunc)
|
||||
o.ApplyRSAPSS(&rsaPSSOptions)
|
||||
}
|
||||
|
||||
switch pk := privateKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
if rsaPSSOptions != nil {
|
||||
return LoadRSAPSSSignerVerifier(pk, hashFunc, rsaPSSOptions)
|
||||
}
|
||||
return LoadRSAPKCS1v15SignerVerifier(pk, hashFunc)
|
||||
case *ecdsa.PrivateKey:
|
||||
return LoadECDSASignerVerifier(pk, hashFunc)
|
||||
case ed25519.PrivateKey:
|
||||
if useED25519ph {
|
||||
return LoadED25519phSignerVerifier(pk)
|
||||
}
|
||||
return LoadED25519SignerVerifier(pk)
|
||||
}
|
||||
return nil, errors.New("unsupported public key type")
|
||||
|
@ -67,3 +89,17 @@ func LoadSignerVerifierFromPEMFile(path string, hashFunc crypto.Hash, pf cryptou
|
|||
}
|
||||
return LoadSignerVerifier(priv, hashFunc)
|
||||
}
|
||||
|
||||
// LoadSignerVerifierFromPEMFileWithOpts returns a signature.SignerVerifier based on the algorithm of the private key
|
||||
// in the file. The SignerVerifier will use the hash function specified in the options when computing digests.
|
||||
func LoadSignerVerifierFromPEMFileWithOpts(path string, pf cryptoutils.PassFunc, opts ...LoadOption) (SignerVerifier, error) {
|
||||
fileBytes, err := os.ReadFile(filepath.Clean(path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv, err := cryptoutils.UnmarshalPEMToPrivateKey(fileBytes, pf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return LoadSignerVerifierWithOpts(priv, opts...)
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/sigstore/sigstore/pkg/cryptoutils"
|
||||
"github.com/sigstore/sigstore/pkg/signature/options"
|
||||
)
|
||||
|
||||
// Verifier verifies the digital signature using a specified public key
|
||||
|
@ -40,12 +41,33 @@ type Verifier interface {
|
|||
// If publicKey is an RSA key, a RSAPKCS1v15Verifier will be returned. If a
|
||||
// RSAPSSVerifier is desired instead, use the LoadRSAPSSVerifier() method directly.
|
||||
func LoadVerifier(publicKey crypto.PublicKey, hashFunc crypto.Hash) (Verifier, error) {
|
||||
return LoadVerifierWithOpts(publicKey, options.WithHash(hashFunc))
|
||||
}
|
||||
|
||||
// LoadVerifierWithOpts returns a signature.Verifier based on the algorithm of the public key
|
||||
// provided that will use the hash function specified when computing digests.
|
||||
func LoadVerifierWithOpts(publicKey crypto.PublicKey, opts ...LoadOption) (Verifier, error) {
|
||||
var rsaPSSOptions *rsa.PSSOptions
|
||||
var useED25519ph bool
|
||||
hashFunc := crypto.SHA256
|
||||
for _, o := range opts {
|
||||
o.ApplyED25519ph(&useED25519ph)
|
||||
o.ApplyHash(&hashFunc)
|
||||
o.ApplyRSAPSS(&rsaPSSOptions)
|
||||
}
|
||||
|
||||
switch pk := publicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
if rsaPSSOptions != nil {
|
||||
return LoadRSAPSSVerifier(pk, hashFunc, rsaPSSOptions)
|
||||
}
|
||||
return LoadRSAPKCS1v15Verifier(pk, hashFunc)
|
||||
case *ecdsa.PublicKey:
|
||||
return LoadECDSAVerifier(pk, hashFunc)
|
||||
case ed25519.PublicKey:
|
||||
if useED25519ph {
|
||||
return LoadED25519phVerifier(pk)
|
||||
}
|
||||
return LoadED25519Verifier(pk)
|
||||
}
|
||||
return nil, errors.New("unsupported public key type")
|
||||
|
@ -98,3 +120,19 @@ func LoadVerifierFromPEMFile(path string, hashFunc crypto.Hash) (Verifier, error
|
|||
|
||||
return LoadVerifier(pubKey, hashFunc)
|
||||
}
|
||||
|
||||
// LoadVerifierFromPEMFileWithOpts returns a signature.Verifier based on the contents of a
|
||||
// file located at path. The Verifier wil use the hash function specified in the options when computing digests.
|
||||
func LoadVerifierFromPEMFileWithOpts(path string, opts ...LoadOption) (Verifier, error) {
|
||||
fileBytes, err := os.ReadFile(filepath.Clean(path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pubKey, err := cryptoutils.UnmarshalPEMToPublicKey(fileBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return LoadVerifierWithOpts(pubKey, opts...)
|
||||
}
|
||||
|
|
|
@ -15,16 +15,15 @@ import (
|
|||
|
||||
// ArrayCodec is the Codec used for bsoncore.Array values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// ArrayCodec registered.
|
||||
// Deprecated: ArrayCodec will not be directly accessible in Go Driver 2.0.
|
||||
type ArrayCodec struct{}
|
||||
|
||||
var defaultArrayCodec = NewArrayCodec()
|
||||
|
||||
// NewArrayCodec returns an ArrayCodec.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// ArrayCodec registered.
|
||||
// Deprecated: NewArrayCodec will not be available in Go Driver 2.0. See
|
||||
// [ArrayCodec] for more details.
|
||||
func NewArrayCodec() *ArrayCodec {
|
||||
return &ArrayCodec{}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,28 @@ import (
|
|||
|
||||
// ByteSliceCodec is the Codec used for []byte values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// ByteSliceCodec registered.
|
||||
// Deprecated: ByteSliceCodec will not be directly configurable in Go Driver
|
||||
// 2.0. To configure the byte slice encode and decode behavior, use the
|
||||
// configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
|
||||
// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the byte slice
|
||||
// encode and decode behavior for a mongo.Client, use
|
||||
// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
|
||||
//
|
||||
// For example, to configure a mongo.Client to encode nil byte slices as empty
|
||||
// BSON binary values, use:
|
||||
//
|
||||
// opt := options.Client().SetBSONOptions(&options.BSONOptions{
|
||||
// NilByteSliceAsEmpty: true,
|
||||
// })
|
||||
//
|
||||
// See the deprecation notice for each field in ByteSliceCodec for the
|
||||
// corresponding settings.
|
||||
type ByteSliceCodec struct {
|
||||
// EncodeNilAsEmpty causes EncodeValue to marshal nil Go byte slices as empty BSON binary values
|
||||
// instead of BSON null.
|
||||
//
|
||||
// Deprecated: Use bson.Encoder.NilByteSliceAsEmpty instead.
|
||||
// Deprecated: Use bson.Encoder.NilByteSliceAsEmpty or options.BSONOptions.NilByteSliceAsEmpty
|
||||
// instead.
|
||||
EncodeNilAsEmpty bool
|
||||
}
|
||||
|
||||
|
@ -38,8 +53,8 @@ var (
|
|||
|
||||
// NewByteSliceCodec returns a ByteSliceCodec with options opts.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// ByteSliceCodec registered.
|
||||
// Deprecated: NewByteSliceCodec will not be available in Go Driver 2.0. See
|
||||
// [ByteSliceCodec] for more details.
|
||||
func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec {
|
||||
byteSliceOpt := bsonoptions.MergeByteSliceCodecOptions(opts...)
|
||||
codec := ByteSliceCodec{}
|
||||
|
|
|
@ -41,7 +41,7 @@ func newDefaultStructCodec() *StructCodec {
|
|||
if err != nil {
|
||||
// This function is called from the codec registration path, so errors can't be propagated. If there's an error
|
||||
// constructing the StructCodec, we panic to avoid losing it.
|
||||
panic(fmt.Errorf("error creating default StructCodec: %v", err))
|
||||
panic(fmt.Errorf("error creating default StructCodec: %w", err))
|
||||
}
|
||||
return codec
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueRe
|
|||
|
||||
for {
|
||||
key, elemVr, err := dr.ReadElement()
|
||||
if err == bsonrw.ErrEOD {
|
||||
if errors.Is(err, bsonrw.ErrEOD) {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
|
@ -1379,7 +1379,7 @@ func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr bsonrw.Value
|
|||
keyType := val.Type().Key()
|
||||
for {
|
||||
key, vr, err := dr.ReadElement()
|
||||
if err == bsonrw.ErrEOD {
|
||||
if errors.Is(err, bsonrw.ErrEOD) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1675,7 +1675,7 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueR
|
|||
idx := 0
|
||||
for {
|
||||
vr, err := ar.ReadValue()
|
||||
if err == bsonrw.ErrEOA {
|
||||
if errors.Is(err, bsonrw.ErrEOA) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1787,7 +1787,7 @@ func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr b
|
|||
elems := make([]reflect.Value, 0)
|
||||
for {
|
||||
key, vr, err := dr.ReadElement()
|
||||
if err == bsonrw.ErrEOD {
|
||||
if errors.Is(err, bsonrw.ErrEOD) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
@ -343,7 +343,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum
|
|||
}
|
||||
|
||||
currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key))
|
||||
if lookupErr != nil && lookupErr != errInvalidValue {
|
||||
if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
|
||||
return lookupErr
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum
|
|||
return err
|
||||
}
|
||||
|
||||
if lookupErr == errInvalidValue {
|
||||
if errors.Is(lookupErr, errInvalidValue) {
|
||||
err = vw.WriteNull()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -418,7 +418,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val
|
|||
|
||||
for idx := 0; idx < val.Len(); idx++ {
|
||||
currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx))
|
||||
if lookupErr != nil && lookupErr != errInvalidValue {
|
||||
if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
|
||||
return lookupErr
|
||||
}
|
||||
|
||||
|
@ -427,7 +427,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val
|
|||
return err
|
||||
}
|
||||
|
||||
if lookupErr == errInvalidValue {
|
||||
if errors.Is(lookupErr, errInvalidValue) {
|
||||
err = vw.WriteNull()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -487,7 +487,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val
|
|||
|
||||
for idx := 0; idx < val.Len(); idx++ {
|
||||
currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx))
|
||||
if lookupErr != nil && lookupErr != errInvalidValue {
|
||||
if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
|
||||
return lookupErr
|
||||
}
|
||||
|
||||
|
@ -496,7 +496,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val
|
|||
return err
|
||||
}
|
||||
|
||||
if lookupErr == errInvalidValue {
|
||||
if errors.Is(lookupErr, errInvalidValue) {
|
||||
err = vw.WriteNull()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -17,13 +17,27 @@ import (
|
|||
|
||||
// EmptyInterfaceCodec is the Codec used for interface{} values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// EmptyInterfaceCodec registered.
|
||||
// Deprecated: EmptyInterfaceCodec will not be directly configurable in Go
|
||||
// Driver 2.0. To configure the empty interface encode and decode behavior, use
|
||||
// the configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
|
||||
// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the empty interface
|
||||
// encode and decode behavior for a mongo.Client, use
|
||||
// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
|
||||
//
|
||||
// For example, to configure a mongo.Client to unmarshal BSON binary field
|
||||
// values as a Go byte slice, use:
|
||||
//
|
||||
// opt := options.Client().SetBSONOptions(&options.BSONOptions{
|
||||
// BinaryAsSlice: true,
|
||||
// })
|
||||
//
|
||||
// See the deprecation notice for each field in EmptyInterfaceCodec for the
|
||||
// corresponding settings.
|
||||
type EmptyInterfaceCodec struct {
|
||||
// DecodeBinaryAsSlice causes DecodeValue to unmarshal BSON binary field values that are the
|
||||
// "Generic" or "Old" BSON binary subtype as a Go byte slice instead of a primitive.Binary.
|
||||
//
|
||||
// Deprecated: Use bson.Decoder.BinaryAsSlice instead.
|
||||
// Deprecated: Use bson.Decoder.BinaryAsSlice or options.BSONOptions.BinaryAsSlice instead.
|
||||
DecodeBinaryAsSlice bool
|
||||
}
|
||||
|
||||
|
@ -38,8 +52,8 @@ var (
|
|||
|
||||
// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// EmptyInterfaceCodec registered.
|
||||
// Deprecated: NewEmptyInterfaceCodec will not be available in Go Driver 2.0. See
|
||||
// [EmptyInterfaceCodec] for more details.
|
||||
func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec {
|
||||
interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...)
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ package bsoncodec
|
|||
|
||||
import (
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
@ -21,25 +22,40 @@ var defaultMapCodec = NewMapCodec()
|
|||
|
||||
// MapCodec is the Codec used for map values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// MapCodec registered.
|
||||
// Deprecated: MapCodec will not be directly configurable in Go Driver 2.0. To
|
||||
// configure the map encode and decode behavior, use the configuration methods
|
||||
// on a [go.mongodb.org/mongo-driver/bson.Encoder] or
|
||||
// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the map encode and
|
||||
// decode behavior for a mongo.Client, use
|
||||
// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
|
||||
//
|
||||
// For example, to configure a mongo.Client to marshal nil Go maps as empty BSON
|
||||
// documents, use:
|
||||
//
|
||||
// opt := options.Client().SetBSONOptions(&options.BSONOptions{
|
||||
// NilMapAsEmpty: true,
|
||||
// })
|
||||
//
|
||||
// See the deprecation notice for each field in MapCodec for the corresponding
|
||||
// settings.
|
||||
type MapCodec struct {
|
||||
// DecodeZerosMap causes DecodeValue to delete any existing values from Go maps in the destination
|
||||
// value passed to Decode before unmarshaling BSON documents into them.
|
||||
//
|
||||
// Deprecated: Use bson.Decoder.ZeroMaps instead.
|
||||
// Deprecated: Use bson.Decoder.ZeroMaps or options.BSONOptions.ZeroMaps instead.
|
||||
DecodeZerosMap bool
|
||||
|
||||
// EncodeNilAsEmpty causes EncodeValue to marshal nil Go maps as empty BSON documents instead of
|
||||
// BSON null.
|
||||
//
|
||||
// Deprecated: Use bson.Encoder.NilMapAsEmpty instead.
|
||||
// Deprecated: Use bson.Encoder.NilMapAsEmpty or options.BSONOptions.NilMapAsEmpty instead.
|
||||
EncodeNilAsEmpty bool
|
||||
|
||||
// EncodeKeysWithStringer causes the Encoder to convert Go map keys to BSON document field name
|
||||
// strings using fmt.Sprintf() instead of the default string conversion logic.
|
||||
//
|
||||
// Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt instead.
|
||||
// Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt or
|
||||
// options.BSONOptions.StringifyMapKeysWithFmt instead.
|
||||
EncodeKeysWithStringer bool
|
||||
}
|
||||
|
||||
|
@ -61,8 +77,8 @@ type KeyUnmarshaler interface {
|
|||
|
||||
// NewMapCodec returns a MapCodec with options opts.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// MapCodec registered.
|
||||
// Deprecated: NewMapCodec will not be available in Go Driver 2.0. See
|
||||
// [MapCodec] for more details.
|
||||
func NewMapCodec(opts ...*bsonoptions.MapCodecOptions) *MapCodec {
|
||||
mapOpt := bsonoptions.MergeMapCodecOptions(opts...)
|
||||
|
||||
|
@ -128,7 +144,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v
|
|||
}
|
||||
|
||||
currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.MapIndex(key))
|
||||
if lookupErr != nil && lookupErr != errInvalidValue {
|
||||
if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
|
||||
return lookupErr
|
||||
}
|
||||
|
||||
|
@ -137,7 +153,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v
|
|||
return err
|
||||
}
|
||||
|
||||
if lookupErr == errInvalidValue {
|
||||
if errors.Is(lookupErr, errInvalidValue) {
|
||||
err = vw.WriteNull()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -200,7 +216,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref
|
|||
|
||||
for {
|
||||
key, vr, err := dr.ReadElement()
|
||||
if err == bsonrw.ErrEOD {
|
||||
if errors.Is(err, bsonrw.ErrEOD) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -313,7 +329,7 @@ func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value,
|
|||
if mc.EncodeKeysWithStringer {
|
||||
parsed, err := strconv.ParseFloat(key, 64)
|
||||
if err != nil {
|
||||
return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %v", keyType.Kind(), err)
|
||||
return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %w", keyType.Kind(), err)
|
||||
}
|
||||
keyVal = reflect.ValueOf(parsed)
|
||||
break
|
||||
|
|
|
@ -18,8 +18,16 @@ var _ ValueDecoder = &PointerCodec{}
|
|||
|
||||
// PointerCodec is the Codec used for pointers.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// PointerCodec registered.
|
||||
// Deprecated: PointerCodec will not be directly accessible in Go Driver 2.0. To
|
||||
// override the default pointer encode and decode behavior, create a new registry
|
||||
// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new
|
||||
// encoder and decoder for pointers.
|
||||
//
|
||||
// For example,
|
||||
//
|
||||
// reg := bson.NewRegistry()
|
||||
// reg.RegisterKindEncoder(reflect.Ptr, myPointerEncoder)
|
||||
// reg.RegisterKindDecoder(reflect.Ptr, myPointerDecoder)
|
||||
type PointerCodec struct {
|
||||
ecache typeEncoderCache
|
||||
dcache typeDecoderCache
|
||||
|
@ -27,8 +35,8 @@ type PointerCodec struct {
|
|||
|
||||
// NewPointerCodec returns a PointerCodec that has been initialized.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// PointerCodec registered.
|
||||
// Deprecated: NewPointerCodec will not be available in Go Driver 2.0. See
|
||||
// [PointerCodec] for more details.
|
||||
func NewPointerCodec() *PointerCodec {
|
||||
return &PointerCodec{}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package bsoncodec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
|
@ -20,8 +21,22 @@ var defaultSliceCodec = NewSliceCodec()
|
|||
|
||||
// SliceCodec is the Codec used for slice values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// SliceCodec registered.
|
||||
// Deprecated: SliceCodec will not be directly configurable in Go Driver 2.0. To
|
||||
// configure the slice encode and decode behavior, use the configuration methods
|
||||
// on a [go.mongodb.org/mongo-driver/bson.Encoder] or
|
||||
// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the slice encode and
|
||||
// decode behavior for a mongo.Client, use
|
||||
// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
|
||||
//
|
||||
// For example, to configure a mongo.Client to marshal nil Go slices as empty
|
||||
// BSON arrays, use:
|
||||
//
|
||||
// opt := options.Client().SetBSONOptions(&options.BSONOptions{
|
||||
// NilSliceAsEmpty: true,
|
||||
// })
|
||||
//
|
||||
// See the deprecation notice for each field in SliceCodec for the corresponding
|
||||
// settings.
|
||||
type SliceCodec struct {
|
||||
// EncodeNilAsEmpty causes EncodeValue to marshal nil Go slices as empty BSON arrays instead of
|
||||
// BSON null.
|
||||
|
@ -32,8 +47,8 @@ type SliceCodec struct {
|
|||
|
||||
// NewSliceCodec returns a MapCodec with options opts.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// SliceCodec registered.
|
||||
// Deprecated: NewSliceCodec will not be available in Go Driver 2.0. See
|
||||
// [SliceCodec] for more details.
|
||||
func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec {
|
||||
sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...)
|
||||
|
||||
|
@ -93,7 +108,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re
|
|||
|
||||
for idx := 0; idx < val.Len(); idx++ {
|
||||
currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx))
|
||||
if lookupErr != nil && lookupErr != errInvalidValue {
|
||||
if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
|
||||
return lookupErr
|
||||
}
|
||||
|
||||
|
@ -102,7 +117,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re
|
|||
return err
|
||||
}
|
||||
|
||||
if lookupErr == errInvalidValue {
|
||||
if errors.Is(lookupErr, errInvalidValue) {
|
||||
err = vw.WriteNull()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -17,8 +17,16 @@ import (
|
|||
|
||||
// StringCodec is the Codec used for string values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// StringCodec registered.
|
||||
// Deprecated: StringCodec will not be directly accessible in Go Driver 2.0. To
|
||||
// override the default string encode and decode behavior, create a new registry
|
||||
// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new
|
||||
// encoder and decoder for strings.
|
||||
//
|
||||
// For example,
|
||||
//
|
||||
// reg := bson.NewRegistry()
|
||||
// reg.RegisterKindEncoder(reflect.String, myStringEncoder)
|
||||
// reg.RegisterKindDecoder(reflect.String, myStringDecoder)
|
||||
type StringCodec struct {
|
||||
// DecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation.
|
||||
// If false, a string made from the raw object ID bytes will be used. Defaults to true.
|
||||
|
@ -38,8 +46,8 @@ var (
|
|||
|
||||
// NewStringCodec returns a StringCodec with options opts.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// StringCodec registered.
|
||||
// Deprecated: NewStringCodec will not be available in Go Driver 2.0. See
|
||||
// [StringCodec] for more details.
|
||||
func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec {
|
||||
stringOpt := bsonoptions.MergeStringCodecOptions(opts...)
|
||||
return &StringCodec{*stringOpt.DecodeObjectIDAsHex}
|
||||
|
|
|
@ -60,8 +60,22 @@ type Zeroer interface {
|
|||
|
||||
// StructCodec is the Codec used for struct values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// StructCodec registered.
|
||||
// Deprecated: StructCodec will not be directly configurable in Go Driver 2.0.
|
||||
// To configure the struct encode and decode behavior, use the configuration
|
||||
// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
|
||||
// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the struct encode
|
||||
// and decode behavior for a mongo.Client, use
|
||||
// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
|
||||
//
|
||||
// For example, to configure a mongo.Client to omit zero-value structs when
|
||||
// using the "omitempty" struct tag, use:
|
||||
//
|
||||
// opt := options.Client().SetBSONOptions(&options.BSONOptions{
|
||||
// OmitZeroStruct: true,
|
||||
// })
|
||||
//
|
||||
// See the deprecation notice for each field in StructCodec for the corresponding
|
||||
// settings.
|
||||
type StructCodec struct {
|
||||
cache sync.Map // map[reflect.Type]*structDescription
|
||||
parser StructTagParser
|
||||
|
@ -69,7 +83,7 @@ type StructCodec struct {
|
|||
// DecodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the
|
||||
// destination value passed to Decode before unmarshaling BSON documents into them.
|
||||
//
|
||||
// Deprecated: Use bson.Decoder.ZeroStructs instead.
|
||||
// Deprecated: Use bson.Decoder.ZeroStructs or options.BSONOptions.ZeroStructs instead.
|
||||
DecodeZeroStruct bool
|
||||
|
||||
// DecodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the
|
||||
|
@ -82,7 +96,7 @@ type StructCodec struct {
|
|||
// MyStruct{}) as empty and omit it from the marshaled BSON when the "omitempty" struct tag
|
||||
// option is set.
|
||||
//
|
||||
// Deprecated: Use bson.Encoder.OmitZeroStruct instead.
|
||||
// Deprecated: Use bson.Encoder.OmitZeroStruct or options.BSONOptions.OmitZeroStruct instead.
|
||||
EncodeOmitDefaultStruct bool
|
||||
|
||||
// AllowUnexportedFields allows encoding and decoding values from un-exported struct fields.
|
||||
|
@ -95,7 +109,8 @@ type StructCodec struct {
|
|||
// a duplicate field in the marshaled BSON when the "inline" struct tag option is set. The
|
||||
// default value is true.
|
||||
//
|
||||
// Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates instead.
|
||||
// Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates or
|
||||
// options.BSONOptions.ErrorOnInlineDuplicates instead.
|
||||
OverwriteDuplicatedInlinedFields bool
|
||||
}
|
||||
|
||||
|
@ -104,8 +119,8 @@ var _ ValueDecoder = &StructCodec{}
|
|||
|
||||
// NewStructCodec returns a StructCodec that uses p for struct tag parsing.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// StructCodec registered.
|
||||
// Deprecated: NewStructCodec will not be available in Go Driver 2.0. See
|
||||
// [StructCodec] for more details.
|
||||
func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) {
|
||||
if p == nil {
|
||||
return nil, errors.New("a StructTagParser must be provided to NewStructCodec")
|
||||
|
@ -164,11 +179,11 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val
|
|||
|
||||
desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(ec, desc.encoder, rv)
|
||||
|
||||
if err != nil && err != errInvalidValue {
|
||||
if err != nil && !errors.Is(err, errInvalidValue) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err == errInvalidValue {
|
||||
if errors.Is(err, errInvalidValue) {
|
||||
if desc.omitEmpty {
|
||||
continue
|
||||
}
|
||||
|
@ -189,17 +204,17 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val
|
|||
|
||||
encoder := desc.encoder
|
||||
|
||||
var zero bool
|
||||
var empty bool
|
||||
if cz, ok := encoder.(CodecZeroer); ok {
|
||||
zero = cz.IsTypeZero(rv.Interface())
|
||||
empty = cz.IsTypeZero(rv.Interface())
|
||||
} else if rv.Kind() == reflect.Interface {
|
||||
// isZero will not treat an interface rv as an interface, so we need to check for the
|
||||
// zero interface separately.
|
||||
zero = rv.IsNil()
|
||||
// isEmpty will not treat an interface rv as an interface, so we need to check for the
|
||||
// nil interface separately.
|
||||
empty = rv.IsNil()
|
||||
} else {
|
||||
zero = isZero(rv, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct)
|
||||
empty = isEmpty(rv, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct)
|
||||
}
|
||||
if desc.omitEmpty && zero {
|
||||
if desc.omitEmpty && empty {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -239,8 +254,8 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val
|
|||
}
|
||||
|
||||
func newDecodeError(key string, original error) error {
|
||||
de, ok := original.(*DecodeError)
|
||||
if !ok {
|
||||
var de *DecodeError
|
||||
if !errors.As(original, &de) {
|
||||
return &DecodeError{
|
||||
keys: []string{key},
|
||||
wrapped: original,
|
||||
|
@ -308,7 +323,7 @@ func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val
|
|||
|
||||
for {
|
||||
name, vr, err := dr.ReadElement()
|
||||
if err == bsonrw.ErrEOD {
|
||||
if errors.Is(err, bsonrw.ErrEOD) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -391,12 +406,15 @@ func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val
|
|||
return nil
|
||||
}
|
||||
|
||||
func isZero(v reflect.Value, omitZeroStruct bool) bool {
|
||||
func isEmpty(v reflect.Value, omitZeroStruct bool) bool {
|
||||
kind := v.Kind()
|
||||
if (kind != reflect.Ptr || !v.IsNil()) && v.Type().Implements(tZeroer) {
|
||||
return v.Interface().(Zeroer).IsZero()
|
||||
}
|
||||
if kind == reflect.Struct {
|
||||
switch kind {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Struct:
|
||||
if !omitZeroStruct {
|
||||
return false
|
||||
}
|
||||
|
@ -410,7 +428,7 @@ func isZero(v reflect.Value, omitZeroStruct bool) bool {
|
|||
if ff.PkgPath != "" && !ff.Anonymous {
|
||||
continue // Private field
|
||||
}
|
||||
if !isZero(v.Field(i), omitZeroStruct) {
|
||||
if !isEmpty(v.Field(i), omitZeroStruct) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,26 @@ const (
|
|||
|
||||
// TimeCodec is the Codec used for time.Time values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// TimeCodec registered.
|
||||
// Deprecated: TimeCodec will not be directly configurable in Go Driver 2.0.
|
||||
// To configure the time.Time encode and decode behavior, use the configuration
|
||||
// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
|
||||
// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the time.Time encode
|
||||
// and decode behavior for a mongo.Client, use
|
||||
// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
|
||||
//
|
||||
// For example, to configure a mongo.Client to ..., use:
|
||||
//
|
||||
// opt := options.Client().SetBSONOptions(&options.BSONOptions{
|
||||
// UseLocalTimeZone: true,
|
||||
// })
|
||||
//
|
||||
// See the deprecation notice for each field in TimeCodec for the corresponding
|
||||
// settings.
|
||||
type TimeCodec struct {
|
||||
// UseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false.
|
||||
//
|
||||
// Deprecated: Use bson.Decoder.UseLocalTimeZone instead.
|
||||
// Deprecated: Use bson.Decoder.UseLocalTimeZone or options.BSONOptions.UseLocalTimeZone
|
||||
// instead.
|
||||
UseLocalTimeZone bool
|
||||
}
|
||||
|
||||
|
@ -42,8 +56,8 @@ var (
|
|||
|
||||
// NewTimeCodec returns a TimeCodec with options opts.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// TimeCodec registered.
|
||||
// Deprecated: NewTimeCodec will not be available in Go Driver 2.0. See
|
||||
// [TimeCodec] for more details.
|
||||
func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec {
|
||||
timeOpt := bsonoptions.MergeTimeCodecOptions(opts...)
|
||||
|
||||
|
|
|
@ -18,13 +18,27 @@ import (
|
|||
|
||||
// UIntCodec is the Codec used for uint values.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// UIntCodec registered.
|
||||
// Deprecated: UIntCodec will not be directly configurable in Go Driver 2.0. To
|
||||
// configure the uint encode and decode behavior, use the configuration methods
|
||||
// on a [go.mongodb.org/mongo-driver/bson.Encoder] or
|
||||
// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the uint encode and
|
||||
// decode behavior for a mongo.Client, use
|
||||
// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
|
||||
//
|
||||
// For example, to configure a mongo.Client to marshal Go uint values as the
|
||||
// minimum BSON int size that can represent the value, use:
|
||||
//
|
||||
// opt := options.Client().SetBSONOptions(&options.BSONOptions{
|
||||
// IntMinSize: true,
|
||||
// })
|
||||
//
|
||||
// See the deprecation notice for each field in UIntCodec for the corresponding
|
||||
// settings.
|
||||
type UIntCodec struct {
|
||||
// EncodeToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the
|
||||
// minimum BSON int size (either 32-bit or 64-bit) that can represent the integer value.
|
||||
//
|
||||
// Deprecated: Use bson.Encoder.IntMinSize instead.
|
||||
// Deprecated: Use bson.Encoder.IntMinSize or options.BSONOptions.IntMinSize instead.
|
||||
EncodeToMinSize bool
|
||||
}
|
||||
|
||||
|
@ -38,8 +52,8 @@ var (
|
|||
|
||||
// NewUIntCodec returns a UIntCodec with options opts.
|
||||
//
|
||||
// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
|
||||
// UIntCodec registered.
|
||||
// Deprecated: NewUIntCodec will not be available in Go Driver 2.0. See
|
||||
// [UIntCodec] for more details.
|
||||
func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec {
|
||||
uintOpt := bsonoptions.MergeUIntCodecOptions(opts...)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package bsonrw
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
|
@ -442,7 +443,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
|
|||
|
||||
for {
|
||||
vr, err := ar.ReadValue()
|
||||
if err == ErrEOA {
|
||||
if errors.Is(err, ErrEOA) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -466,7 +467,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
|
|||
func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error {
|
||||
for {
|
||||
key, vr, err := dr.ReadElement()
|
||||
if err == ErrEOD {
|
||||
if errors.Is(err, ErrEOD) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
@ -313,7 +313,7 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) {
|
|||
// convert hex to bytes
|
||||
bytes, err := hex.DecodeString(uuidNoHyphens)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %v", err)
|
||||
return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %w", err)
|
||||
}
|
||||
|
||||
ejp.advanceState()
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package bsonrw
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
@ -613,7 +614,7 @@ func (ejvr *extJSONValueReader) ReadElement() (string, ValueReader, error) {
|
|||
name, t, err := ejvr.p.readKey()
|
||||
|
||||
if err != nil {
|
||||
if err == ErrEOD {
|
||||
if errors.Is(err, ErrEOD) {
|
||||
if ejvr.stack[ejvr.frame].mode == mCodeWithScope {
|
||||
_, err := ejvr.p.peekType()
|
||||
if err != nil {
|
||||
|
@ -640,7 +641,7 @@ func (ejvr *extJSONValueReader) ReadValue() (ValueReader, error) {
|
|||
|
||||
t, err := ejvr.p.peekType()
|
||||
if err != nil {
|
||||
if err == ErrEOA {
|
||||
if errors.Is(err, ErrEOA) {
|
||||
ejvr.pop()
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ func (js *jsonScanner) nextToken() (*jsonToken, error) {
|
|||
c, err = js.readNextByte()
|
||||
}
|
||||
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return &jsonToken{t: jttEOF}, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
|
@ -198,7 +198,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
|
|||
for {
|
||||
c, err = js.readNextByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil, errors.New("end of input in JSON string")
|
||||
}
|
||||
return nil, err
|
||||
|
@ -209,7 +209,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
|
|||
case '\\':
|
||||
c, err = js.readNextByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil, errors.New("end of input in JSON string")
|
||||
}
|
||||
return nil, err
|
||||
|
@ -248,7 +248,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
|
|||
if utf16.IsSurrogate(rn) {
|
||||
c, err = js.readNextByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil, errors.New("end of input in JSON string")
|
||||
}
|
||||
return nil, err
|
||||
|
@ -264,7 +264,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
|
|||
|
||||
c, err = js.readNextByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil, errors.New("end of input in JSON string")
|
||||
}
|
||||
return nil, err
|
||||
|
@ -325,17 +325,17 @@ func (js *jsonScanner) scanLiteral(first byte) (*jsonToken, error) {
|
|||
|
||||
c5, err := js.readNextByte()
|
||||
|
||||
if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || err == io.EOF) {
|
||||
if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) {
|
||||
js.pos = int(math.Max(0, float64(js.pos-1)))
|
||||
return &jsonToken{t: jttBool, v: true, p: p}, nil
|
||||
} else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || err == io.EOF) {
|
||||
} else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) {
|
||||
js.pos = int(math.Max(0, float64(js.pos-1)))
|
||||
return &jsonToken{t: jttNull, v: nil, p: p}, nil
|
||||
} else if bytes.Equal([]byte("fals"), lit) {
|
||||
if c5 == 'e' {
|
||||
c5, err = js.readNextByte()
|
||||
|
||||
if isValueTerminator(c5) || err == io.EOF {
|
||||
if isValueTerminator(c5) || errors.Is(err, io.EOF) {
|
||||
js.pos = int(math.Max(0, float64(js.pos-1)))
|
||||
return &jsonToken{t: jttBool, v: false, p: p}, nil
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
|
|||
for {
|
||||
c, err = js.readNextByte()
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -413,7 +413,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
|
|||
case '}', ']', ',':
|
||||
s = nssDone
|
||||
default:
|
||||
if isWhiteSpace(c) || err == io.EOF {
|
||||
if isWhiteSpace(c) || errors.Is(err, io.EOF) {
|
||||
s = nssDone
|
||||
} else {
|
||||
s = nssInvalid
|
||||
|
@ -430,7 +430,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
|
|||
case '}', ']', ',':
|
||||
s = nssDone
|
||||
default:
|
||||
if isWhiteSpace(c) || err == io.EOF {
|
||||
if isWhiteSpace(c) || errors.Is(err, io.EOF) {
|
||||
s = nssDone
|
||||
} else if isDigit(c) {
|
||||
s = nssSawIntegerDigits
|
||||
|
@ -455,7 +455,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
|
|||
case '}', ']', ',':
|
||||
s = nssDone
|
||||
default:
|
||||
if isWhiteSpace(c) || err == io.EOF {
|
||||
if isWhiteSpace(c) || errors.Is(err, io.EOF) {
|
||||
s = nssDone
|
||||
} else if isDigit(c) {
|
||||
s = nssSawFractionDigits
|
||||
|
@ -490,7 +490,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
|
|||
case '}', ']', ',':
|
||||
s = nssDone
|
||||
default:
|
||||
if isWhiteSpace(c) || err == io.EOF {
|
||||
if isWhiteSpace(c) || errors.Is(err, io.EOF) {
|
||||
s = nssDone
|
||||
} else if isDigit(c) {
|
||||
s = nssSawExponentDigits
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
// Package bson is a library for reading, writing, and manipulating BSON. BSON is a binary serialization format used to
|
||||
// store documents and make remote procedure calls in MongoDB. The BSON specification is located at https://bsonspec.org.
|
||||
// The BSON library handles marshalling and unmarshalling of values through a configurable codec system. For a description
|
||||
// of the codec system and examples of registering custom codecs, see the bsoncodec package. For additional information and
|
||||
// usage examples, check out the [Work with BSON] page in the Go Driver docs site.
|
||||
// The BSON library handles marshaling and unmarshaling of values through a configurable codec system. For a description
|
||||
// of the codec system and examples of registering custom codecs, see the bsoncodec package. For additional information
|
||||
// and usage examples, check out the [Work with BSON] page in the Go Driver docs site.
|
||||
//
|
||||
// # Raw BSON
|
||||
//
|
||||
|
@ -38,7 +38,7 @@
|
|||
// bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}}
|
||||
// bson.M{"foo": "bar", "hello": "world", "pi": 3.14159}
|
||||
//
|
||||
// When decoding BSON to a D or M, the following type mappings apply when unmarshalling:
|
||||
// When decoding BSON to a D or M, the following type mappings apply when unmarshaling:
|
||||
//
|
||||
// 1. BSON int32 unmarshals to an int32.
|
||||
// 2. BSON int64 unmarshals to an int64.
|
||||
|
@ -62,83 +62,78 @@
|
|||
// 20. BSON DBPointer unmarshals to a primitive.DBPointer.
|
||||
// 21. BSON symbol unmarshals to a primitive.Symbol.
|
||||
//
|
||||
// The above mappings also apply when marshalling a D or M to BSON. Some other useful marshalling mappings are:
|
||||
// The above mappings also apply when marshaling a D or M to BSON. Some other useful marshaling mappings are:
|
||||
//
|
||||
// 1. time.Time marshals to a BSON datetime.
|
||||
// 2. int8, int16, and int32 marshal to a BSON int32.
|
||||
// 3. int marshals to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, inclusive, and a BSON int64
|
||||
// otherwise.
|
||||
// 4. int64 marshals to BSON int64.
|
||||
// 4. int64 marshals to BSON int64 (unless [Encoder.IntMinSize] is set).
|
||||
// 5. uint8 and uint16 marshal to a BSON int32.
|
||||
// 6. uint, uint32, and uint64 marshal to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32,
|
||||
// inclusive, and BSON int64 otherwise.
|
||||
// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshalling a BSON null or
|
||||
// 6. uint, uint32, and uint64 marshal to a BSON int64 (unless [Encoder.IntMinSize] is set).
|
||||
// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshaling a BSON null or
|
||||
// undefined value into a string will yield the empty string.).
|
||||
//
|
||||
// # Structs
|
||||
//
|
||||
// Structs can be marshalled/unmarshalled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended
|
||||
// Structs can be marshaled/unmarshaled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended
|
||||
// JSON, the following rules apply:
|
||||
//
|
||||
// 1. Only exported fields in structs will be marshalled or unmarshalled.
|
||||
// 1. Only exported fields in structs will be marshaled or unmarshaled.
|
||||
//
|
||||
// 2. When marshalling a struct, each field will be lowercased to generate the key for the corresponding BSON element.
|
||||
// 2. When marshaling a struct, each field will be lowercased to generate the key for the corresponding BSON element.
|
||||
// For example, a struct field named "Foo" will generate key "foo". This can be overridden via a struct tag (e.g.
|
||||
// `bson:"fooField"` to generate key "fooField" instead).
|
||||
//
|
||||
// 3. An embedded struct field is marshalled as a subdocument. The key will be the lowercased name of the field's type.
|
||||
// 3. An embedded struct field is marshaled as a subdocument. The key will be the lowercased name of the field's type.
|
||||
//
|
||||
// 4. A pointer field is marshalled as the underlying type if the pointer is non-nil. If the pointer is nil, it is
|
||||
// marshalled as a BSON null value.
|
||||
// 4. A pointer field is marshaled as the underlying type if the pointer is non-nil. If the pointer is nil, it is
|
||||
// marshaled as a BSON null value.
|
||||
//
|
||||
// 5. When unmarshalling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents
|
||||
// unmarshalled into an interface{} field will be unmarshalled as a D.
|
||||
// 5. When unmarshaling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents
|
||||
// unmarshaled into an interface{} field will be unmarshaled as a D.
|
||||
//
|
||||
// The encoding of each struct field can be customized by the "bson" struct tag.
|
||||
//
|
||||
// This tag behavior is configurable, and different struct tag behavior can be configured by initializing a new
|
||||
// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON tags
|
||||
// are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below:
|
||||
// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON
|
||||
// tags are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below:
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser)
|
||||
//
|
||||
// The bson tag gives the name of the field, possibly followed by a comma-separated list of options.
|
||||
// The name may be empty in order to specify options without overriding the default field name. The following options can be used
|
||||
// to configure behavior:
|
||||
// The name may be empty in order to specify options without overriding the default field name. The following options can
|
||||
// be used to configure behavior:
|
||||
//
|
||||
// 1. omitempty: If the omitempty struct tag is specified on a field, the field will not be marshalled if it is set to
|
||||
// the zero value. Fields with language primitive types such as integers, booleans, and strings are considered empty if
|
||||
// their value is equal to the zero value for the type (i.e. 0 for integers, false for booleans, and "" for strings).
|
||||
// Slices, maps, and arrays are considered empty if they are of length zero. Interfaces and pointers are considered
|
||||
// empty if their value is nil. By default, structs are only considered empty if the struct type implements the
|
||||
// bsoncodec.Zeroer interface and the IsZero method returns true. Struct fields whose types do not implement Zeroer are
|
||||
// never considered empty and will be marshalled as embedded documents.
|
||||
// 1. omitempty: If the omitempty struct tag is specified on a field, the field will be omitted from the marshaling if
|
||||
// the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array,
|
||||
// slice, map, or string.
|
||||
// NOTE: It is recommended that this tag be used for all slice and map fields.
|
||||
//
|
||||
// 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of
|
||||
// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For other
|
||||
// types, this tag is ignored.
|
||||
// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For
|
||||
// other types, this tag is ignored.
|
||||
//
|
||||
// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles unmarshalled
|
||||
// into that field will be truncated at the decimal point. For example, if 3.14 is unmarshalled into a field of type int,
|
||||
// it will be unmarshalled as 3. If this tag is not specified, the decoder will throw an error if the value cannot be
|
||||
// decoded without losing precision. For float64 or non-numeric types, this tag is ignored.
|
||||
// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles
|
||||
// unmarshaled into that field will be truncated at the decimal point. For example, if 3.14 is unmarshaled into a
|
||||
// field of type int, it will be unmarshaled as 3. If this tag is not specified, the decoder will throw an error if
|
||||
// the value cannot be decoded without losing precision. For float64 or non-numeric types, this tag is ignored.
|
||||
//
|
||||
// 4. inline: If the inline struct tag is specified for a struct or map field, the field will be "flattened" when
|
||||
// marshalling and "un-flattened" when unmarshalling. This means that all of the fields in that struct/map will be
|
||||
// pulled up one level and will become top-level fields rather than being fields in a nested document. For example, if a
|
||||
// map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will be
|
||||
// {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If there are
|
||||
// duplicated fields in the resulting document when an inlined struct is marshalled, the inlined field will be overwritten.
|
||||
// If there are duplicated fields in the resulting document when an inlined map is marshalled, an error will be returned.
|
||||
// This tag can be used with fields that are pointers to structs. If an inlined pointer field is nil, it will not be
|
||||
// marshalled. For fields that are not maps or structs, this tag is ignored.
|
||||
// marshaling and "un-flattened" when unmarshaling. This means that all of the fields in that struct/map will be
|
||||
// pulled up one level and will become top-level fields rather than being fields in a nested document. For example,
|
||||
// if a map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will
|
||||
// be {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If
|
||||
// there are duplicated fields in the resulting document when an inlined struct is marshaled, the inlined field will
|
||||
// be overwritten. If there are duplicated fields in the resulting document when an inlined map is marshaled, an
|
||||
// error will be returned. This tag can be used with fields that are pointers to structs. If an inlined pointer field
|
||||
// is nil, it will not be marshaled. For fields that are not maps or structs, this tag is ignored.
|
||||
//
|
||||
// # Marshalling and Unmarshalling
|
||||
// # Marshaling and Unmarshaling
|
||||
//
|
||||
// Manually marshalling and unmarshalling can be done with the Marshal and Unmarshal family of functions.
|
||||
// Manually marshaling and unmarshaling can be done with the Marshal and Unmarshal family of functions.
|
||||
//
|
||||
// [Work with BSON]: https://www.mongodb.com/docs/drivers/go/current/fundamentals/bson/
|
||||
package bson
|
||||
|
|
|
@ -164,9 +164,6 @@ func (d Decimal128) BigInt() (*big.Int, int, error) {
|
|||
|
||||
// Would be handled by the logic below, but that's trivial and common.
|
||||
if high == 0 && low == 0 && exp == 0 {
|
||||
if posSign {
|
||||
return new(big.Int), 0, nil
|
||||
}
|
||||
return new(big.Int), 0, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ func processUniqueBytes() [5]byte {
|
|||
var b [5]byte
|
||||
_, err := io.ReadFull(rand.Reader, b[:])
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
|
||||
panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err))
|
||||
}
|
||||
|
||||
return b
|
||||
|
@ -193,7 +193,7 @@ func readRandomUint32() uint32 {
|
|||
var b [4]byte
|
||||
_, err := io.ReadFull(rand.Reader, b[:])
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
|
||||
panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err))
|
||||
}
|
||||
|
||||
return (uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24)
|
||||
|
|
|
@ -141,7 +141,7 @@ github.com/containernetworking/cni/pkg/version
|
|||
# github.com/containernetworking/plugins v1.4.0
|
||||
## explicit; go 1.20
|
||||
github.com/containernetworking/plugins/pkg/ns
|
||||
# github.com/containers/buildah v1.34.1-0.20240201124221-b850c711ff5c
|
||||
# github.com/containers/buildah v1.34.1-0.20240229193131-f5d7689ef4cd
|
||||
## explicit; go 1.20
|
||||
github.com/containers/buildah
|
||||
github.com/containers/buildah/bind
|
||||
|
@ -243,7 +243,7 @@ github.com/containers/conmon/runner/config
|
|||
# github.com/containers/gvisor-tap-vsock v0.7.3
|
||||
## explicit; go 1.20
|
||||
github.com/containers/gvisor-tap-vsock/pkg/types
|
||||
# github.com/containers/image/v5 v5.29.3-0.20240227090231-5bef5e1e1506
|
||||
# github.com/containers/image/v5 v5.29.3-0.20240229213915-cdc68020a24f
|
||||
## explicit; go 1.19
|
||||
github.com/containers/image/v5/copy
|
||||
github.com/containers/image/v5/directory
|
||||
|
@ -550,7 +550,7 @@ github.com/gin-gonic/gin/binding
|
|||
github.com/gin-gonic/gin/internal/bytesconv
|
||||
github.com/gin-gonic/gin/internal/json
|
||||
github.com/gin-gonic/gin/render
|
||||
# github.com/go-jose/go-jose/v3 v3.0.1
|
||||
# github.com/go-jose/go-jose/v3 v3.0.2
|
||||
## explicit; go 1.12
|
||||
github.com/go-jose/go-jose/v3
|
||||
github.com/go-jose/go-jose/v3/cipher
|
||||
|
@ -602,7 +602,7 @@ github.com/go-openapi/runtime/yamlpc
|
|||
# github.com/go-openapi/spec v0.20.9
|
||||
## explicit; go 1.13
|
||||
github.com/go-openapi/spec
|
||||
# github.com/go-openapi/strfmt v0.22.0
|
||||
# github.com/go-openapi/strfmt v0.22.1
|
||||
## explicit; go 1.19
|
||||
github.com/go-openapi/strfmt
|
||||
# github.com/go-openapi/swag v0.22.9
|
||||
|
@ -659,7 +659,7 @@ github.com/google/go-cmp/cmp/internal/diff
|
|||
github.com/google/go-cmp/cmp/internal/flags
|
||||
github.com/google/go-cmp/cmp/internal/function
|
||||
github.com/google/go-cmp/cmp/internal/value
|
||||
# github.com/google/go-containerregistry v0.17.0
|
||||
# github.com/google/go-containerregistry v0.19.0
|
||||
## explicit; go 1.18
|
||||
github.com/google/go-containerregistry/pkg/name
|
||||
github.com/google/go-containerregistry/pkg/v1
|
||||
|
@ -1000,7 +1000,7 @@ github.com/sigstore/rekor/pkg/generated/client/pubkey
|
|||
github.com/sigstore/rekor/pkg/generated/client/tlog
|
||||
github.com/sigstore/rekor/pkg/generated/models
|
||||
github.com/sigstore/rekor/pkg/util
|
||||
# github.com/sigstore/sigstore v1.8.1
|
||||
# github.com/sigstore/sigstore v1.8.2
|
||||
## explicit; go 1.20
|
||||
github.com/sigstore/sigstore/pkg/cryptoutils
|
||||
github.com/sigstore/sigstore/pkg/oauth
|
||||
|
@ -1101,8 +1101,8 @@ github.com/yusufpapurcu/wmi
|
|||
# go.etcd.io/bbolt v1.3.9
|
||||
## explicit; go 1.17
|
||||
go.etcd.io/bbolt
|
||||
# go.mongodb.org/mongo-driver v1.13.1
|
||||
## explicit; go 1.13
|
||||
# go.mongodb.org/mongo-driver v1.14.0
|
||||
## explicit; go 1.18
|
||||
go.mongodb.org/mongo-driver/bson
|
||||
go.mongodb.org/mongo-driver/bson/bsoncodec
|
||||
go.mongodb.org/mongo-driver/bson/bsonoptions
|
||||
|
|
Loading…
Reference in New Issue