diff --git a/services/upgrader/pubkey.gpg b/services/upgrader/pubkey.gpg new file mode 100644 index 0000000000..173374ebda --- /dev/null +++ b/services/upgrader/pubkey.gpg @@ -0,0 +1,18 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFjZQxwBCAC6kNn3zDlq/aY83M9V7MHVPoK2jnZ3BfH7sA+ibQXsijCkPSR4 +5bCUJ9qVA4XKGK+cpO9vkolSNs10igCaaemaUZNB6ksu3gT737/SZcCAfRO+cLX7 +Q2la+jwTvu1YeT/M5xDZ1KHTFxsGskeIenz2rZHeuZwBl9qep34QszWtRX40eRts +fl6WltLrepiExTp6NMZ50k+Em4JGM6CWBMo22ucy0jYjZXO5hEGb3o6NGiG+Dx2z +b2J78LksCKGsSrn0F1rLJeA933bFL4g9ozv9asBlzmpgG77ESg6YE1N/Rh7WDzVA +prIR0MuB5JjElASw5LDVxDV6RZsxEVQr7ETLABEBAAG0KU1hdHRlcm1vc3QgQnVp +bGQgPGRldi1vcHNAbWF0dGVybW9zdC5jb20+iQFUBBMBCAA+AhsDBQsJCAcCBhUI +CQoLAgQWAgMBAh4BAheAFiEEobMdRvDzoQsCzy1E+PLDF0R3SygFAmJOqWgFCQ03 +zUwACgkQ+PLDF0R3Syg/rQf8D5BgvVFnGuHDYNu2eiasZdfxmuhg1C7JGSLHqoCT +SB/0SLLQyMeHsJLye/gbo3yhK8G9XYOm+obGF+NDxB0LtRaPv5Q6pIQYt88ZxOGA +Kh6RG2DjYA5j410wYrN0mNzhudqnS2yZdyq215nEr7Z6l1T7L9OPcz0u0mF9RraQ +nawzxbxc8mPuC5tMLTedViSkTYLgMY12TCSYhykseUIGrl/FBfMbmKwBHM52SZJh +maBevuNymlFbODTciyE9Q7mJHkaamGKTXaa3Enlcf16oSoemawSBJuspaS0sZOW8 +dgi5l3V5YvfFvSk45axiZbnGYfN81G5mkSGAENSGSKVtMA== +=kkvg +-----END PGP PUBLIC KEY BLOCK----- diff --git a/services/upgrader/upgrader_linux.go b/services/upgrader/upgrader_linux.go index 0cb2b6c881..fa45dd4951 100644 --- a/services/upgrader/upgrader_linux.go +++ b/services/upgrader/upgrader_linux.go @@ -7,6 +7,7 @@ import ( "archive/tar" "bytes" "compress/gzip" + _ "embed" "fmt" "io" "io/ioutil" @@ -17,6 +18,7 @@ import ( "runtime" "strconv" "strings" + "sync" "sync/atomic" "syscall" @@ -27,48 +29,65 @@ import ( "github.com/mattermost/mattermost-server/v6/shared/mlog" ) -const mattermostBuildPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +//go:embed pubkey.gpg +var mattermostBuildPublicKeys []byte -mQENBFjZQxwBCAC6kNn3zDlq/aY83M9V7MHVPoK2jnZ3BfH7sA+ibQXsijCkPSR4 -5bCUJ9qVA4XKGK+cpO9vkolSNs10igCaaemaUZNB6ksu3gT737/SZcCAfRO+cLX7 -Q2la+jwTvu1YeT/M5xDZ1KHTFxsGskeIenz2rZHeuZwBl9qep34QszWtRX40eRts -fl6WltLrepiExTp6NMZ50k+Em4JGM6CWBMo22ucy0jYjZXO5hEGb3o6NGiG+Dx2z -b2J78LksCKGsSrn0F1rLJeA933bFL4g9ozv9asBlzmpgG77ESg6YE1N/Rh7WDzVA -prIR0MuB5JjElASw5LDVxDV6RZsxEVQr7ETLABEBAAG0KU1hdHRlcm1vc3QgQnVp -bGQgPGRldi1vcHNAbWF0dGVybW9zdC5jb20+iQFUBBMBCAA+AhsDBQsJCAcCBhUI -CQoLAgQWAgMBAh4BAheAFiEEobMdRvDzoQsCzy1E+PLDF0R3SygFAmJOqWgFCQ03 -zUwACgkQ+PLDF0R3Syg/rQf8D5BgvVFnGuHDYNu2eiasZdfxmuhg1C7JGSLHqoCT -SB/0SLLQyMeHsJLye/gbo3yhK8G9XYOm+obGF+NDxB0LtRaPv5Q6pIQYt88ZxOGA -Kh6RG2DjYA5j410wYrN0mNzhudqnS2yZdyq215nEr7Z6l1T7L9OPcz0u0mF9RraQ -nawzxbxc8mPuC5tMLTedViSkTYLgMY12TCSYhykseUIGrl/FBfMbmKwBHM52SZJh -maBevuNymlFbODTciyE9Q7mJHkaamGKTXaa3Enlcf16oSoemawSBJuspaS0sZOW8 -dgi5l3V5YvfFvSk45axiZbnGYfN81G5mkSGAENSGSKVtMA== -=kkvg ------END PGP PUBLIC KEY BLOCK-----` - -var upgradePercentage int64 -var upgradeError error -var upgrading int32 +var ( + upgradePercentage int64 + m sync.Mutex + upgradeError error + upgrading int32 +) type writeCounter struct { - total int64 - readed int64 + total int64 + read int64 } func (wc *writeCounter) Write(p []byte) (int, error) { n := len(p) - wc.readed += int64(n) - percentage := (wc.readed * 100) / wc.total - if percentage == 0 { - upgradePercentage = 1 - } else if percentage == 100 { - upgradePercentage = 99 - } else { - upgradePercentage = percentage + wc.read += int64(n) + + if wc.total <= 0 { + // skip the percentage calculation for invalid totals + setUpgradePercentage(50) + return n, nil } + + percentage := (wc.read * 100) / wc.total + if percentage == 0 { + percentage = 1 + } else if percentage >= 100 { + percentage = 99 + } + + setUpgradePercentage(percentage) + return n, nil } +func getUpgradePercentage() int64 { + return atomic.LoadInt64(&upgradePercentage) +} + +func setUpgradePercentage(to int64) { + atomic.StoreInt64(&upgradePercentage, to) +} + +func getUpgradeError() error { + m.Lock() + defer m.Unlock() + + return upgradeError +} + +func setUpgradeError(err error) { + m.Lock() + defer m.Unlock() + + upgradeError = err +} + func getCurrentVersionTgzURL() string { version := model.CurrentVersion if strings.HasPrefix(model.BuildNumber, version+"-rc") { @@ -78,8 +97,8 @@ func getCurrentVersionTgzURL() string { return "https://releases.mattermost.com/" + version + "/mattermost-" + version + "-linux-amd64.tar.gz" } -func verifySignature(filename string, sigfilename string, publicKey string) error { - keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewReader([]byte(publicKey))) +func verifySignature(filename string, sigfilename string, publicKey []byte) error { + keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewReader(publicKey)) if err != nil { mlog.Debug("Unable to load the public key to verify the file signature", mlog.Err(err)) return NewInvalidSignature() @@ -173,14 +192,14 @@ func UpgradeToE0() error { } defer atomic.CompareAndSwapInt32(&upgrading, 1, 0) - upgradePercentage = 1 - upgradeError = nil + setUpgradePercentage(1) + setUpgradeError(nil) executablePath, err := os.Executable() if err != nil { - upgradePercentage = 0 - upgradeError = errors.New("error getting the executable path") + setUpgradeError(errors.New("error getting the executable path")) mlog.Error("Unable to get the path of the Mattermost executable", mlog.Err(err)) + setUpgradePercentage(0) return err } @@ -189,9 +208,9 @@ func UpgradeToE0() error { if filename != "" { os.Remove(filename) } - upgradeError = fmt.Errorf("error downloading the new Mattermost server binary file (percentage: %d)", upgradePercentage) - mlog.Error("Unable to download the Mattermost server binary file", mlog.Int64("percentage", upgradePercentage), mlog.String("url", getCurrentVersionTgzURL()), mlog.Err(err)) - upgradePercentage = 0 + setUpgradeError(fmt.Errorf("error downloading the new Mattermost server binary file (percentage: %d)", getUpgradePercentage())) + mlog.Error("Unable to download the Mattermost server binary file", mlog.Int64("percentage", getUpgradePercentage()), mlog.String("url", getCurrentVersionTgzURL()), mlog.Err(err)) + setUpgradePercentage(0) return err } defer os.Remove(filename) @@ -200,34 +219,35 @@ func UpgradeToE0() error { if sigfilename != "" { os.Remove(sigfilename) } - upgradeError = errors.New("error downloading the signature file of the new server") + setUpgradeError(errors.New("error downloading the signature file of the new server")) mlog.Error("Unable to download the signature file of the new Mattermost server", mlog.String("url", getCurrentVersionTgzURL()+".sig"), mlog.Err(err)) - upgradePercentage = 0 + setUpgradePercentage(0) return err } defer os.Remove(sigfilename) - err = verifySignature(filename, sigfilename, mattermostBuildPublicKey) + err = verifySignature(filename, sigfilename, mattermostBuildPublicKeys) if err != nil { - upgradePercentage = 0 - upgradeError = errors.New("unable to verify the signature of the downloaded file") + setUpgradeError(errors.New("unable to verify the signature of the downloaded file")) mlog.Error("Unable to verify the signature of the downloaded file", mlog.Err(err)) + setUpgradePercentage(0) return err } err = extractBinary(executablePath, filename) if err != nil { - upgradePercentage = 0 - upgradeError = err + setUpgradeError(err) mlog.Error("Unable to extract the binary from the downloaded file", mlog.Err(err)) + setUpgradePercentage(0) return err } - upgradePercentage = 100 + + setUpgradePercentage(100) return nil } func UpgradeToE0Status() (int64, error) { - return upgradePercentage, upgradeError + return getUpgradePercentage(), getUpgradeError() } func download(url string, limit int64) (string, error) {