ipn/{ipnlocal,localapi}, cmd/tailscale: add logout command

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2021-04-07 21:06:31 -07:00
committed by Brad Fitzpatrick
parent 11127666b2
commit 3167e55ddf
7 changed files with 176 additions and 38 deletions

View File

@@ -1961,19 +1961,28 @@ func (b *LocalBackend) requestEngineStatusAndWait() {
// transitions the local engine to the logged-out state without
// waiting for controlclient to be in that state.
//
// TODO(danderson): controlclient Logout does nothing useful, and we
// shouldn't be transitioning to a state based on what we believe
// controlclient may have done.
//
// NOTE(apenwarr): No easy way to persist logged-out status.
// Maybe that's for the better; if someone logs out accidentally,
// rebooting will fix it.
func (b *LocalBackend) Logout() {
b.logout(context.Background(), false)
}
func (b *LocalBackend) LogoutSync(ctx context.Context) error {
return b.logout(ctx, true)
}
func (b *LocalBackend) logout(ctx context.Context, sync bool) error {
b.mu.Lock()
cc := b.cc
b.setNetMapLocked(nil)
b.mu.Unlock()
b.EditPrefs(&ipn.MaskedPrefs{
WantRunningSet: true,
Prefs: ipn.Prefs{WantRunning: true},
})
if cc == nil {
// Double Logout can happen via repeated IPN
// connections to ipnserver making it repeatedly
@@ -1982,16 +1991,22 @@ func (b *LocalBackend) Logout() {
// on the transition to zero.
// Previously this crashed when we asserted that c was non-nil
// here.
return
return errors.New("no controlclient")
}
cc.Logout()
var err error
if sync {
err = cc.Logout(ctx)
} else {
cc.StartLogout()
}
b.mu.Lock()
b.setNetMapLocked(nil)
b.mu.Unlock()
b.stateMachine()
return err
}
// assertClientLocked crashes if there is no controlclient in this backend.

View File

@@ -87,6 +87,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.serveGoroutines(w, r)
case "/localapi/v0/status":
h.serveStatus(w, r)
case "/localapi/v0/logout":
h.serveLogout(w, r)
case "/localapi/v0/prefs":
h.servePrefs(w, r)
case "/localapi/v0/check-ip-forwarding":
@@ -200,6 +202,23 @@ func (h *Handler) serveStatus(w http.ResponseWriter, r *http.Request) {
e.Encode(st)
}
func (h *Handler) serveLogout(w http.ResponseWriter, r *http.Request) {
if !h.PermitWrite {
http.Error(w, "logout access denied", http.StatusForbidden)
return
}
if r.Method != "POST" {
http.Error(w, "want POST", 400)
return
}
err := h.b.LogoutSync(r.Context())
if err == nil {
w.WriteHeader(http.StatusNoContent)
return
}
http.Error(w, err.Error(), 500)
}
func (h *Handler) servePrefs(w http.ResponseWriter, r *http.Request) {
if !h.PermitRead {
http.Error(w, "prefs access denied", http.StatusForbidden)