@@ -21,10 +21,15 @@ import (
2121 "log"
2222 "net/http"
2323 "os"
24+ "regexp"
25+ "strconv"
2426
27+ "github.com/edgelesssys/constellation/v2/internal/sigstore"
2528 "golang.org/x/tools/go/ast/astutil"
2629)
2730
31+ var kuberntesMinorRegex = regexp .MustCompile (`^.*\.(?P<Minor>\d+)\..*(kubelet|kubeadm|kubectl)+$` )
32+
2833func mustGetHash (url string ) string {
2934 // remove quotes around url
3035 url = url [1 : len (url )- 1 ]
@@ -80,9 +85,78 @@ func mustGetHash(url string) string {
8085 panic ("hash mismatch" )
8186 }
8287
88+ // Verify cosign signature if available
89+ // Currently, we verify the signature of kubeadm, kubelet and kubectl with minor version >=1.26.
90+ minorVersion := kuberntesMinorRegex .FindStringSubmatch (url )
91+ if minorVersion == nil {
92+ return fmt .Sprintf ("\" sha256:%x\" " , fileHash )
93+ }
94+ minorVersionIndex := kuberntesMinorRegex .SubexpIndex ("Minor" )
95+ if minorVersionIndex != - 1 {
96+ minorVersionNumber , err := strconv .Atoi (minorVersion [minorVersionIndex ])
97+ if err != nil {
98+ panic (err )
99+ }
100+ if minorVersionNumber >= 26 {
101+ content , err := io .ReadAll (resp .Body )
102+ if err != nil {
103+ panic (err )
104+ }
105+ if err := verifyCosignSignature (content , url ); err != nil {
106+ panic (err )
107+ }
108+ }
109+ }
110+
83111 return fmt .Sprintf ("\" sha256:%x\" " , fileHash )
84112}
85113
114+ func verifyCosignSignature (content []byte , url string ) error {
115+ // Get the signature
116+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , url + ".sig" , nil )
117+ if err != nil {
118+ panic (err )
119+ }
120+ resp , err := http .DefaultClient .Do (req )
121+ if err != nil {
122+ panic (err )
123+ }
124+ defer resp .Body .Close ()
125+
126+ // Check server response
127+ if resp .StatusCode != http .StatusOK {
128+ panic ("bad status: " + resp .Status )
129+ }
130+
131+ sig , err := io .ReadAll (resp .Body )
132+ if err != nil {
133+ panic (err )
134+ }
135+
136+ // Get the certificate
137+ req , err = http .NewRequestWithContext (context .Background (), http .MethodGet , url + ".cert" , nil )
138+ if err != nil {
139+ panic (err )
140+ }
141+ resp , err = http .DefaultClient .Do (req )
142+ if err != nil {
143+ panic (err )
144+ }
145+ defer resp .Body .Close ()
146+
147+ // Check server response
148+ if resp .StatusCode != http .StatusOK {
149+ panic ("bad status: " + resp .Status )
150+ }
151+
152+ cert , err := io .ReadAll (resp .Body )
153+ if err != nil {
154+ panic (err )
155+ }
156+
157+ return sigstore .VerifySignature (content , sig , cert )
158+ }
159+
86160func main () {
87161 fmt .Println ("Generating hashes..." )
88162
0 commit comments