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

@@ -261,15 +261,14 @@ const (
func (c *Direct) TryLogout(ctx context.Context) error {
c.logf("direct.TryLogout()")
c.mu.Lock()
defer c.mu.Unlock()
mustRegen, newURL, err := c.doLogin(ctx, loginOpt{Logout: true})
c.logf("TryLogout control response: mustRegen=%v, newURL=%v, err=%v", mustRegen, newURL, err)
// TODO(crawshaw): Tell the server. This node key should be
// immediately invalidated.
//if !c.persist.PrivateNodeKey.IsZero() {
//}
c.mu.Lock()
c.persist = persist.Persist{}
return nil
c.mu.Unlock()
return err
}
func (c *Direct) TryLogin(ctx context.Context, t *tailcfg.Oauth2Token, flags LoginFlags) (url string, err error) {
@@ -298,10 +297,11 @@ func (c *Direct) doLoginOrRegen(ctx context.Context, opt loginOpt) (newURL strin
}
type loginOpt struct {
Token *tailcfg.Oauth2Token
Flags LoginFlags
Regen bool
URL string
Token *tailcfg.Oauth2Token
Flags LoginFlags
Regen bool
URL string
Logout bool
}
func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, newURL string, err error) {
@@ -324,14 +324,18 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
}
regen := opt.Regen
if expired {
c.logf("Old key expired -> regen=true")
systemd.Status("key expired; run 'tailscale up' to authenticate")
regen = true
}
if (opt.Flags & LoginInteractive) != 0 {
c.logf("LoginInteractive -> regen=true")
regen = true
if opt.Logout {
c.logf("logging out...")
} else {
if expired {
c.logf("Old key expired -> regen=true")
systemd.Status("key expired; run 'tailscale up' to authenticate")
regen = true
}
if (opt.Flags & LoginInteractive) != 0 {
c.logf("LoginInteractive -> regen=true")
regen = true
}
}
c.logf("doLogin(regen=%v, hasUrl=%v)", regen, opt.URL != "")
@@ -348,8 +352,12 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
}
var oldNodeKey wgkey.Key
if opt.URL != "" {
} else if regen || persist.PrivateNodeKey.IsZero() {
switch {
case opt.Logout:
tryingNewKey = persist.PrivateNodeKey
case opt.URL != "":
// Nothing.
case regen || persist.PrivateNodeKey.IsZero():
c.logf("Generating a new nodekey.")
persist.OldPrivateNodeKey = persist.PrivateNodeKey
key, err := wgkey.NewPrivate()
@@ -358,7 +366,7 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
return regen, opt.URL, err
}
tryingNewKey = key
} else {
default:
// Try refreshing the current key first
tryingNewKey = persist.PrivateNodeKey
}
@@ -367,6 +375,9 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
}
if tryingNewKey.IsZero() {
if opt.Logout {
return false, "", errors.New("no nodekey to log out")
}
log.Fatalf("tryingNewKey is empty, give up")
}
if backendLogID == "" {
@@ -382,6 +393,9 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
Followup: opt.URL,
Timestamp: &now,
}
if opt.Logout {
request.Expiry = time.Unix(123, 0) // far in the past
}
c.logf("RegisterReq: onode=%v node=%v fup=%v",
request.OldNodeKey.ShortString(),
request.NodeKey.ShortString(), opt.URL != "")
@@ -403,6 +417,11 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
c.logf("RegisterReq sign error: %v", err)
}
}
if debugRegister {
j, _ := json.MarshalIndent(request, "", "\t")
c.logf("RegisterRequest: %s", j)
}
bodyData, err := encode(request, &serverKey, &machinePrivKey)
if err != nil {
return regen, opt.URL, err
@@ -431,6 +450,11 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
c.logf("error decoding RegisterResponse with server key %s and machine key %s: %v", serverKey, machinePrivKey.Public(), err)
return regen, opt.URL, fmt.Errorf("register request: %v", err)
}
if debugRegister {
j, _ := json.MarshalIndent(resp, "", "\t")
c.logf("RegisterResponse: %s", j)
}
// Log without PII:
c.logf("RegisterReq: got response; nodeKeyExpired=%v, machineAuthorized=%v; authURL=%v",
resp.NodeKeyExpired, resp.MachineAuthorized, resp.AuthURL != "")
@@ -902,7 +926,10 @@ func decode(res *http.Response, v interface{}, serverKey *wgkey.Key, mkey *wgkey
return decodeMsg(msg, v, serverKey, mkey)
}
var debugMap, _ = strconv.ParseBool(os.Getenv("TS_DEBUG_MAP"))
var (
debugMap, _ = strconv.ParseBool(os.Getenv("TS_DEBUG_MAP"))
debugRegister, _ = strconv.ParseBool(os.Getenv("TS_DEBUG_REGISTER"))
)
var jsonEscapedZero = []byte(`\u0000`)