Skip to content

Commit a23ea79

Browse files
probelabs[bot]Tyk Botkofoworola
authored
Merging to release-5.11.1: [TT-16554]: Change bundle loading logic when reloaded (#7745) (#7763)
Cherry-pick of `756e53cd32ff8340b528750bdc14287d049d9f26` from `master` to `release-5.11.1` requires manual resolution. **Conflicts detected:** 3 - gateway/server.go Tips: - Check out this branch locally and run: `git cherry-pick -x 756e53c` - Resolve conflicts (including submodules if any), then push back to this branch. Original commit: 756e53c --------- Co-authored-by: Tyk Bot <bot@tyk.io> Co-authored-by: Kofo Okesola <okesolakofo@gmail.com>
1 parent 4cb2e05 commit a23ea79

File tree

4 files changed

+335
-73
lines changed

4 files changed

+335
-73
lines changed

gateway/coprocess_bundle.go

Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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
)
@@ -36,6 +35,40 @@ var (
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.
4073
type 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

Comments
 (0)