Option -gui-address should accept scheme prefixes (fixes #2371)

This commit is contained in:
Jakob Borg
2015-10-12 22:27:57 +09:00
parent 240e7b0835
commit 953a67bc3a
5 changed files with 123 additions and 73 deletions

View File

@@ -83,12 +83,7 @@ func newAPISvc(id protocol.DeviceID, cfg *config.Wrapper, assetDir string, m *mo
return svc, err
}
func (s *apiSvc) getListener(cfg config.GUIConfiguration) (net.Listener, error) {
if guiAddress != "" {
// Override from the environment
cfg.Address = guiAddress
}
func (s *apiSvc) getListener(guiCfg config.GUIConfiguration) (net.Listener, error) {
cert, err := tls.LoadX509KeyPair(locations[locHTTPSCertFile], locations[locHTTPSKeyFile])
if err != nil {
l.Infoln("Loading HTTPS certificate:", err)
@@ -125,11 +120,13 @@ func (s *apiSvc) getListener(cfg config.GUIConfiguration) (net.Listener, error)
},
}
rawListener, err := net.Listen("tcp", cfg.Address)
rawListener, err := net.Listen("tcp", guiCfg.Address())
if err != nil {
return nil, err
}
l.Infoln("Starting web GUI on", guiCfg.URL())
listener := &tlsutil.DowngradingListener{rawListener, tlsCfg}
return listener, nil
}
@@ -202,14 +199,10 @@ func (s *apiSvc) Serve() {
})
guiCfg := s.cfg.GUI()
if guiAPIKey != "" {
// Override from the environment
guiCfg.APIKey = guiAPIKey
}
// Wrap everything in CSRF protection. The /rest prefix should be
// protected, other requests will grant cookies.
handler := csrfMiddleware(s.id.String()[:5], "/rest", guiCfg.APIKey, mux)
handler := csrfMiddleware(s.id.String()[:5], "/rest", guiCfg.APIKey(), mux)
// Add our version and ID as a header to responses
handler = withDetailsMiddleware(s.id, handler)
@@ -220,7 +213,7 @@ func (s *apiSvc) Serve() {
}
// Redirect to HTTPS if we are supposed to
if guiCfg.UseTLS {
if guiCfg.UseTLS() {
handler = redirectToHTTPSMiddleware(handler)
}

View File

@@ -25,8 +25,9 @@ var (
)
func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguration, next http.Handler) http.Handler {
apiKey := cfg.APIKey()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if cfg.APIKey != "" && r.Header.Get("X-API-Key") == cfg.APIKey {
if apiKey != "" && r.Header.Get("X-API-Key") == apiKey {
next.ServeHTTP(w, r)
return
}

View File

@@ -205,8 +205,6 @@ var (
paused bool
noRestart = os.Getenv("STNORESTART") != ""
noUpgrade = os.Getenv("STNOUPGRADE") != ""
guiAddress = os.Getenv("STGUIADDRESS") // legacy
guiAPIKey = os.Getenv("STGUIAPIKEY") // legacy
profiler = os.Getenv("STPROFILER")
guiAssets = os.Getenv("STGUIASSETS")
cpuProfile = os.Getenv("STCPUPROFILE") != ""
@@ -226,6 +224,7 @@ func main() {
flag.StringVar(&logFile, "logfile", "-", "Log file name (use \"-\" for stdout)")
}
var guiAddress, guiAPIKey string
flag.StringVar(&generateDir, "generate", "", "Generate key and config in specified dir, then exit")
flag.StringVar(&guiAddress, "gui-address", guiAddress, "Override GUI address")
flag.StringVar(&guiAPIKey, "gui-apikey", guiAPIKey, "Override GUI API key")
@@ -246,6 +245,15 @@ func main() {
flag.Usage = usageFor(flag.CommandLine, usage, longUsage)
flag.Parse()
if guiAddress != "" {
// The config picks this up from the environment.
os.Setenv("STGUIADDRESS", guiAddress)
}
if guiAPIKey != "" {
// The config picks this up from the environment.
os.Setenv("STGUIAPIKEY", guiAPIKey)
}
if noConsole {
osutil.HideConsole()
}
@@ -422,14 +430,9 @@ func upgradeViaRest() error {
if err != nil {
return err
}
target := cfg.GUI().Address
if cfg.GUI().UseTLS {
target = "https://" + target
} else {
target = "http://" + target
}
target := cfg.GUI().URL()
r, _ := http.NewRequest("POST", target+"/rest/system/upgrade", nil)
r.Header.Set("X-API-Key", cfg.GUI().APIKey)
r.Header.Set("X-API-Key", cfg.GUI().APIKey())
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
@@ -910,48 +913,18 @@ func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, a
if !guiCfg.Enabled {
return
}
if guiCfg.Address == "" {
return
}
addr, err := net.ResolveTCPAddr("tcp", guiCfg.Address)
api, err := newAPISvc(myID, cfg, guiAssets, m, apiSub, discoverer, relaySvc, errors, systemLog)
if err != nil {
l.Fatalf("Cannot start GUI on %q: %v", guiCfg.Address, err)
} else {
var hostOpen, hostShow string
switch {
case addr.IP == nil:
hostOpen = "localhost"
hostShow = "0.0.0.0"
case addr.IP.IsUnspecified():
hostOpen = "localhost"
hostShow = addr.IP.String()
default:
hostOpen = addr.IP.String()
hostShow = hostOpen
}
l.Fatalln("Cannot start GUI:", err)
}
cfg.Subscribe(api)
mainSvc.Add(api)
var proto = "http"
if guiCfg.UseTLS {
proto = "https"
}
urlShow := fmt.Sprintf("%s://%s/", proto, net.JoinHostPort(hostShow, strconv.Itoa(addr.Port)))
l.Infoln("Starting web GUI on", urlShow)
api, err := newAPISvc(myID, cfg, guiAssets, m, apiSub, discoverer, relaySvc, errors, systemLog)
if err != nil {
l.Fatalln("Cannot start GUI:", err)
}
cfg.Subscribe(api)
mainSvc.Add(api)
if cfg.Options().StartBrowser && !noBrowser && !stRestarting {
urlOpen := fmt.Sprintf("%s://%s/", proto, net.JoinHostPort(hostOpen, strconv.Itoa(addr.Port)))
// Can potentially block if the utility we are invoking doesn't
// fork, and just execs, hence keep it in it's own routine.
go openURL(urlOpen)
}
if cfg.Options().StartBrowser && !noBrowser && !stRestarting {
// Can potentially block if the utility we are invoking doesn't
// fork, and just execs, hence keep it in it's own routine.
go openURL(guiCfg.URL())
}
}
@@ -978,7 +951,7 @@ func defaultConfig(myName string) config.Configuration {
if err != nil {
l.Fatalln("get free port (GUI):", err)
}
newCfg.GUI.Address = fmt.Sprintf("127.0.0.1:%d", port)
newCfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port)
port, err = getFreePort("0.0.0.0", 22000)
if err != nil {