summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAnton Tolchanov <anton@tailscale.com>2024-05-09 09:57:44 +0100
committerAnton Tolchanov <anton@tailscale.com>2024-05-09 09:58:14 +0100
commit8625b9f3c5aa0bce994737fb717d090810a09b87 (patch)
tree7dd583d93188d36bf8b8a26d8c2e54b5c7bfab2c
parentb5dbf155b1b0fbd5947160d8bca4085c6ff039a5 (diff)
downloadtailscale-knyar/renew.tar.xz
tailscale-knyar/renew.zip
cmd/tailscale: add the renew commandknyar/renew
-rw-r--r--cmd/tailscale/cli/cli.go1
-rw-r--r--cmd/tailscale/cli/renew.go78
2 files changed, 79 insertions, 0 deletions
diff --git a/cmd/tailscale/cli/cli.go b/cmd/tailscale/cli/cli.go
index 929b63958..8e1658495 100644
--- a/cmd/tailscale/cli/cli.go
+++ b/cmd/tailscale/cli/cli.go
@@ -199,6 +199,7 @@ change in the future.
debugCmd,
driveCmd,
idTokenCmd,
+ renewCmd,
},
FlagSet: rootfs,
Exec: func(ctx context.Context, args []string) error {
diff --git a/cmd/tailscale/cli/renew.go b/cmd/tailscale/cli/renew.go
new file mode 100644
index 000000000..1c030be92
--- /dev/null
+++ b/cmd/tailscale/cli/renew.go
@@ -0,0 +1,78 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+package cli
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "os/signal"
+ "strings"
+ "syscall"
+
+ "github.com/peterbourgon/ff/v3/ffcli"
+)
+
+var renewCmd = &ffcli.Command{
+ Name: "renew",
+ ShortUsage: "tailscale renew",
+ ShortHelp: "Reauthenticate and renew the device key",
+
+ LongHelp: strings.TrimSpace(`
+HIDDEN: "tailscale renew" triggers reauthentication and renewal of the
+device key.)
+`),
+ FlagSet: upFlagSet,
+ Exec: func(ctx context.Context, args []string) error {
+ return runRenew(ctx)
+ },
+}
+
+func runRenew(ctx context.Context) (retErr error) {
+ st, err := localClient.Status(ctx)
+ if err != nil {
+ return fixTailscaledConnectError(err)
+ }
+ origAuthURL := st.AuthURL
+
+ watchCtx, cancelWatch := context.WithCancel(ctx)
+ defer cancelWatch()
+ watcher, err := localClient.WatchIPNBus(watchCtx, 0)
+ if err != nil {
+ return err
+ }
+ defer watcher.Close()
+
+ go func() {
+ interrupt := make(chan os.Signal, 1)
+ signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
+ select {
+ case <-interrupt:
+ cancelWatch()
+ case <-watchCtx.Done():
+ }
+ }()
+
+ if err := localClient.StartLoginInteractive(ctx); err != nil {
+ return fmt.Errorf("could not call localapi: %w", err)
+ }
+
+ for {
+ n, err := watcher.Next()
+ if err != nil {
+ return err
+ }
+ if n.ErrMessage != nil {
+ msg := *n.ErrMessage
+ fatalf("backend error: %v\n", msg)
+ }
+ if url := n.BrowseToURL; url != nil && *url != origAuthURL {
+ fmt.Fprintf(Stderr, "\nTo authenticate, visit:\n\n\t%s\n\n", *url)
+ }
+ if n.LoginFinished != nil {
+ fmt.Fprintf(Stderr, "Success.\n")
+ return nil
+ }
+ }
+}