cloudflare/cloudflared

Public

mirrored from https://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2018.10.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

cmd/cloudflared/updater/update.go

119lines · modecode

1package updater
2
3import (
4 "os"
5 "runtime"
6 "time"
7
8 "golang.org/x/crypto/ssh/terminal"
9 "gopkg.in/urfave/cli.v2"
10
11 "github.com/cloudflare/cloudflared/log"
12 "github.com/equinox-io/equinox"
13 "github.com/facebookgo/grace/gracenet"
14)
15
16const (
17 appID = "app_idCzgxYerVD"
18 noUpdateInShellMessage = "cloudflared will not automatically update when run from the shell. To enable auto-updates, run cloudflared as a service: https://developers.cloudflare.com/argo-tunnel/reference/service/"
19 noUpdateOnWindowsMessage = "cloudflared will not automatically update on Windows systems."
20)
21
22var (
23 publicKey = []byte(`
24-----BEGIN ECDSA PUBLIC KEY-----
25MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4OWZocTVZ8Do/L6ScLdkV+9A0IYMHoOf
26dsCmJ/QZ6aw0w9qkkwEpne1Lmo6+0pGexZzFZOH6w5amShn+RXt7qkSid9iWlzGq
27EKx0BZogHSor9Wy5VztdFaAaVbsJiCbO
28-----END ECDSA PUBLIC KEY-----
29`)
30 logger = log.CreateLogger()
31)
32
33type ReleaseInfo struct {
34 Updated bool
35 Version string
36 Error error
37}
38
39func checkForUpdates() ReleaseInfo {
40 var opts equinox.Options
41 if err := opts.SetPublicKeyPEM(publicKey); err != nil {
42 return ReleaseInfo{Error: err}
43 }
44
45 resp, err := equinox.Check(appID, opts)
46 switch {
47 case err == equinox.NotAvailableErr:
48 return ReleaseInfo{}
49 case err != nil:
50 return ReleaseInfo{Error: err}
51 }
52
53 err = resp.Apply()
54 if err != nil {
55 return ReleaseInfo{Error: err}
56 }
57
58 return ReleaseInfo{Updated: true, Version: resp.ReleaseVersion}
59}
60
61func Update(_ *cli.Context) error {
62 if updateApplied() {
63 os.Exit(64)
64 }
65 return nil
66}
67
68func Autoupdate(freq time.Duration, listeners *gracenet.Net, shutdownC chan struct{}) error {
69 tickC := time.Tick(freq)
70 for {
71 if updateApplied() {
72 os.Args = append(os.Args, "--is-autoupdated=true")
73 pid, err := listeners.StartProcess()
74 if err != nil {
75 logger.WithError(err).Error("Unable to restart server automatically")
76 return err
77 }
78 // stop old process after autoupdate. Otherwise we create a new process
79 // after each update
80 logger.Infof("PID of the new process is %d", pid)
81 return nil
82 }
83 select {
84 case <-tickC:
85 case <-shutdownC:
86 return nil
87 }
88 }
89}
90
91func updateApplied() bool {
92 releaseInfo := checkForUpdates()
93 if releaseInfo.Updated {
94 logger.Infof("Updated to version %s", releaseInfo.Version)
95 return true
96 }
97 if releaseInfo.Error != nil {
98 logger.WithError(releaseInfo.Error).Error("Update check failed")
99 }
100 return false
101}
102
103func IsAutoupdateEnabled(c *cli.Context) bool {
104 if runtime.GOOS == "windows" {
105 logger.Info(noUpdateOnWindowsMessage)
106 return false
107 }
108
109 if isRunningFromTerminal() {
110 logger.Info(noUpdateInShellMessage)
111 return false
112 }
113
114 return !c.Bool("no-autoupdate") && c.Duration("autoupdate-freq") != 0
115}
116
117func isRunningFromTerminal() bool {
118 return terminal.IsTerminal(int(os.Stdout.Fd()))
119}
120