@@ -10,6 +10,7 @@ import (
1010 "encoding/json"
1111 "errors"
1212 "fmt"
13+ "hash"
1314 "io"
1415 "io/ioutil"
1516 "net/http"
@@ -25,8 +26,6 @@ import (
2526
2627 "github.com/sirupsen/logrus"
2728
28- "github.com/TykTechnologies/goverify"
29-
3029 "github.com/TykTechnologies/tyk/apidef"
3130 "github.com/TykTechnologies/tyk/internal/sanitize"
3231)
3635 bundleMaxBackoffRetries uint64 = 4
3736)
3837
38+ type bundleChecksumVerifyFunction func (bundle * Bundle , bundleFs afero.Fs ) (sha256Hash hash.Hash , err error )
39+
40+ func defaultBundleVerifyFunction (b * Bundle , bundleFs afero.Fs ) (sha256Hash hash.Hash , err error ) {
41+ md5Hash := md5 .New ()
42+ sha256Hash = sha256 .New ()
43+
44+ w := io .MultiWriter (sha256Hash , md5Hash )
45+ buf , ok := bundleVerifyPool .Get ().(* []byte )
46+ if ! ok {
47+ return nil , errors .New ("error verifying bundle, please try again" )
48+ }
49+ defer bundleVerifyPool .Put (buf )
50+
51+ for _ , f := range b .Manifest .FileList {
52+ extractedPath := filepath .Join (b .Path , f )
53+ file , err := bundleFs .Open (extractedPath )
54+ if err != nil {
55+ return nil , err
56+ }
57+ _ , err = io .CopyBuffer (w , file , * buf )
58+ file .Close ()
59+ if err != nil {
60+ return nil , err
61+ }
62+ }
63+
64+ checksum := fmt .Sprintf ("%x" , md5Hash .Sum (nil ))
65+ if checksum != b .Manifest .Checksum {
66+ return nil , errors .New ("invalid checksum" )
67+ }
68+
69+ return sha256Hash , nil
70+ }
71+
3972// Bundle is the basic bundle data structure, it holds the bundle name and the data.
4073type Bundle struct {
4174 Name string
@@ -53,67 +86,73 @@ var bundleVerifyPool = sync.Pool{
5386 },
5487}
5588
56- // Verify performs signature verification on the bundle file.
57- func (b * Bundle ) Verify (bundleFs afero.Fs ) error {
89+ func (b * Bundle ) DeepVerify (bundleFs afero.Fs ) error {
5890 log .WithFields (logrus.Fields {
5991 "prefix" : "main" ,
6092 }).Info ("----> Verifying bundle: " , b .Spec .CustomMiddlewareBundle )
93+ hasKey := b .Gw .GetConfig ().PublicKeyPath != ""
94+ hasSignature := b .Manifest .Signature != ""
6195
62- var useSignature = b .Gw .GetConfig ().PublicKeyPath != ""
63-
64- var (
65- verifier goverify.Verifier
66- err error
67- )
96+ if hasKey && ! hasSignature {
97+ return errors .New ("Bundle isn't signed" )
98+ }
6899
69- if useSignature {
70- // Perform signature verification if a public key path is set:
71- if b .Manifest .Signature == "" {
72- // Error: A public key is set, but the bundle isn't signed.
73- return errors .New ("Bundle isn't signed" )
100+ // check hash first then check signature
101+ sha256Hash , err := b .Gw .BundleChecksumVerifier (b , bundleFs )
102+ if err != nil {
103+ return err
104+ }
105+ if hasKey {
106+ verifier , err := b .Gw .SignatureVerifier ()
107+ if err != nil {
108+ return err
74109 }
75- verifier , err = b . Gw . SignatureVerifier ( )
110+ signed , err := base64 . StdEncoding . DecodeString ( b . Manifest . Signature )
76111 if err != nil {
77112 return err
78113 }
114+ if err := verifier .VerifyHash (sha256Hash .Sum (nil ), signed ); err != nil {
115+ return err
116+ }
79117 }
118+ return nil
119+ }
80120
81- md5Hash := md5 .New ()
82- sha256Hash := sha256 .New ()
121+ func (b * Bundle ) PartialVerify (bundleFs afero.Fs , skipVerify bool ) error {
122+ if skipVerify {
123+ return nil
124+ }
83125
84- var w io.Writer = md5Hash
85- if useSignature {
86- w = io .MultiWriter (md5Hash , sha256Hash )
126+ hasKey := b .Gw .GetConfig ().PublicKeyPath != ""
127+ hasSignature := b .Manifest .Signature != ""
128+
129+ if ! hasSignature {
130+ return nil
87131 }
88132
89- buf := bundleVerifyPool .Get ().(* []byte )
90- defer bundleVerifyPool .Put (buf )
133+ log .WithFields (logrus.Fields {
134+ "prefix" : "main" ,
135+ }).Info ("----> Verifying bundle: " , b .Spec .CustomMiddlewareBundle )
136+ // Make a single call to compute both hashes if needed
137+ sha256Hash , err := b .Gw .BundleChecksumVerifier (b , bundleFs )
138+ if err != nil {
139+ return err
140+ }
91141
92- for _ , f := range b .Manifest .FileList {
93- extractedPath := filepath .Join (b .Path , f )
94- file , err := bundleFs .Open (extractedPath )
142+ if hasKey {
143+ verifier , err := b .Gw .SignatureVerifier ()
95144 if err != nil {
96145 return err
97146 }
98- _ , err = io .CopyBuffer (w , file , * buf )
99- file .Close ()
147+ signed , err := base64 .StdEncoding .DecodeString (b .Manifest .Signature )
100148 if err != nil {
101149 return err
102150 }
103- }
104-
105- checksum := fmt .Sprintf ("%x" , md5Hash .Sum (nil ))
106- if checksum != b .Manifest .Checksum {
107- return errors .New ("Invalid checksum" )
108- }
109-
110- if useSignature {
111- signed , err := base64 .StdEncoding .DecodeString (b .Manifest .Signature )
112- if err != nil {
151+ if err := verifier .VerifyHash (sha256Hash .Sum (nil ), signed ); err != nil {
113152 return err
114153 }
115- return verifier .VerifyHash (sha256Hash .Sum (nil ), signed )
116154 }
155+
117156 return nil
118157}
119158
@@ -353,7 +392,7 @@ func saveBundle(bundleFs afero.Fs, bundle *Bundle, destPath string, spec *APISpe
353392}
354393
355394// loadBundleManifest will parse the manifest file and return the bundle parameters.
356- func loadBundleManifest (bundleFs afero.Fs , bundle * Bundle , spec * APISpec , skipVerification bool ) error {
395+ func loadBundleManifest (bundleFs afero.Fs , bundle * Bundle , spec * APISpec , partial bool , skipVerification bool ) error {
357396 log .WithFields (logrus.Fields {
358397 "prefix" : "main" ,
359398 }).Info ("----> Loading bundle: " , spec .CustomMiddlewareBundle )
@@ -372,16 +411,18 @@ func loadBundleManifest(bundleFs afero.Fs, bundle *Bundle, spec *APISpec, skipVe
372411 return err
373412 }
374413
375- if skipVerification {
376- return nil
414+ if partial {
415+ err = bundle .PartialVerify (bundleFs , skipVerification )
416+ } else {
417+ err = bundle .DeepVerify (bundleFs )
377418 }
378-
379- if err := bundle .Verify (bundleFs ); err != nil {
419+ if err != nil {
380420 log .WithFields (logrus.Fields {
381421 "prefix" : "main" ,
382422 }).Info ("----> Bundle verification failed: " , spec .CustomMiddlewareBundle )
383423 return err
384424 }
425+
385426 return nil
386427}
387428
@@ -443,7 +484,7 @@ func (gw *Gateway) loadBundleWithFs(spec *APISpec, bundleFs afero.Fs) error {
443484 Gw : gw ,
444485 }
445486
446- err = loadBundleManifest (bundleFs , & bundle , spec , gw .GetConfig ().SkipVerifyExistingPluginBundle )
487+ err = loadBundleManifest (bundleFs , & bundle , spec , true , gw .GetConfig ().SkipVerifyExistingPluginBundle )
447488 if err != nil {
448489 log .WithFields (logrus.Fields {
449490 "prefix" : "main" ,
@@ -484,7 +525,7 @@ func (gw *Gateway) loadBundleWithFs(spec *APISpec, bundleFs afero.Fs) error {
484525 // Set the destination path:
485526 bundle .Path = destPath
486527
487- if err := loadBundleManifest (bundleFs , & bundle , spec , false ); err != nil {
528+ if err := loadBundleManifest (bundleFs , & bundle , spec , false , false ); err != nil {
488529 bundleError (spec , err , "Couldn't load bundle" )
489530
490531 if removeErr := bundleFs .RemoveAll (bundle .Path ); removeErr != nil {
0 commit comments