@@ -19,10 +19,14 @@ import (
1919 "log"
2020 "net/http"
2121 "os"
22+ "regexp"
23+ "strconv"
2224
2325 "golang.org/x/tools/go/ast/astutil"
2426)
2527
28+ var kuberntesMinorRegex = regexp .MustCompile (`^.*\.(?P<Minor>\d+)\..*(kubelet|kubeadm|kubectl)+$` )
29+
2630func mustGetHash (url string ) string {
2731 // remove quotes around url
2832 url = url [1 : len (url )- 1 ]
@@ -78,9 +82,80 @@ func mustGetHash(url string) string {
7882 panic ("hash mismatch" )
7983 }
8084
85+ // Verify cosign signature if available
86+ // Currently, we verify the signature of kubeadm, kubelet and kubectl with minor version >=1.26.
87+ minorVersion := kuberntesMinorRegex .FindStringSubmatch (url )
88+ if minorVersion == nil {
89+ return fmt .Sprintf ("\" sha256:%x\" " , fileHash )
90+ }
91+ minorVersionIndex := kuberntesMinorRegex .SubexpIndex ("Minor" )
92+ if minorVersionIndex != - 1 {
93+ minorVersionNumber , err := strconv .Atoi (minorVersion [minorVersionIndex ])
94+ if err != nil {
95+ panic (err )
96+ }
97+ if minorVersionNumber >= 26 {
98+ content , err := io .ReadAll (resp .Body )
99+ if err != nil {
100+ panic (err )
101+ }
102+ if err := verifyCosignSignature (content , url ); err != nil {
103+ panic (err )
104+ }
105+ }
106+ }
107+
81108 return fmt .Sprintf ("\" sha256:%x\" " , fileHash )
82109}
83110
111+ func verifyCosignSignature (content []byte , url string ) error {
112+ // Get the signature
113+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , url + ".sig" , nil )
114+ if err != nil {
115+ panic (err )
116+ }
117+ resp , err := http .DefaultClient .Do (req )
118+ if err != nil {
119+ panic (err )
120+ }
121+ defer resp .Body .Close ()
122+
123+ // Check server response
124+ if resp .StatusCode != http .StatusOK {
125+ panic ("bad status: " + resp .Status )
126+ }
127+
128+ sig , err := io .ReadAll (resp .Body )
129+ if err != nil {
130+ panic (err )
131+ }
132+
133+ // Get the certificate
134+ req , err = http .NewRequestWithContext (context .Background (), http .MethodGet , url + ".cert" , nil )
135+ if err != nil {
136+ panic (err )
137+ }
138+ resp , err = http .DefaultClient .Do (req )
139+ if err != nil {
140+ panic (err )
141+ }
142+ defer resp .Body .Close ()
143+
144+ // Check server response
145+ if resp .StatusCode != http .StatusOK {
146+ panic ("bad status: " + resp .Status )
147+ }
148+
149+ base64Cert , err := io .ReadAll (resp .Body )
150+ if err != nil {
151+ panic (err )
152+ }
153+
154+ // TODO: implement https://github.com/sigstore/cosign/blob/v2.2.0/cmd/cosign/cli/verify/verify_blob.go keyless verification
155+
156+ return verifier .VerifySignature (content , sig )
157+ }
158+
84159func main () {
85160 fmt .Println ("Generating hashes..." )
86161
0 commit comments