From 8e7aac2b5d52251b4e91d862152b6b6dc6f70646 Mon Sep 17 00:00:00 2001
From: lijianguo <lijianguo@zhumengyuan.com>
Date: Fri, 30 Jul 2021 08:29:14 +0800
Subject: [PATCH] feat(workflow-cli): use OIDC login

---
 cli/cli.go            |   2 -
 cmd/auth.go           | 294 +++++++++---------------------------------
 cmd/auth_test.go      | 144 ++-------------------
 cmd/cmd.go            |   6 +-
 cmd/shortcuts_test.go |   2 -
 go.mod                |   3 +-
 go.sum                |  47 +------
 parser/auth.go        | 152 +---------------------
 parser/auth_test.go   |  46 +------
 9 files changed, 81 insertions(+), 615 deletions(-)

diff --git a/cli/cli.go b/cli/cli.go
index 66ba2b928..24f59394c 100644
--- a/cli/cli.go
+++ b/cli/cli.go
@@ -9,9 +9,7 @@ var Shortcuts = map[string]string{
 	"logout":         "auth:logout",
 	"logs":           "apps:logs",
 	"open":           "apps:open",
-	"passwd":         "auth:passwd",
 	"pull":           "builds:create",
-	"register":       "auth:register",
 	"rollback":       "releases:rollback",
 	"run":            "apps:run",
 	"scale":          "ps:scale",
diff --git a/cmd/auth.go b/cmd/auth.go
index c163c67cb..44a12a879 100644
--- a/cmd/auth.go
+++ b/cmd/auth.go
@@ -3,108 +3,88 @@ package cmd
 import (
 	"errors"
 	"fmt"
-	"strings"
-	"syscall"
+	"net/url"
+	"os/exec"
+	"runtime"
+	"time"
 
 	drycc "github.com/drycc/controller-sdk-go"
+	"github.com/drycc/controller-sdk-go/api"
 	"github.com/drycc/controller-sdk-go/auth"
 	"github.com/drycc/workflow-cli/settings"
-	"golang.org/x/crypto/ssh/terminal"
 )
 
-// Register creates a account on a Drycc controller.
-func (d *DryccCmd) Register(controller string, username string, password string, email string,
-	sslVerify, login bool) error {
-
-	c, err := drycc.New(sslVerify, controller, "")
-
-	if err != nil {
+func (d *DryccCmd) doLogin(s settings.Settings) error {
+	URL, err := auth.Login(s.Client)
+	if d.checkAPICompatibility(s.Client, err) != nil {
 		return err
 	}
-
-	tempSettings, err := settings.Load(d.ConfigFile)
-
-	if err == nil && tempSettings.Client.ControllerURL.Host == c.ControllerURL.Host {
-		c.Token = tempSettings.Client.Token
-	}
-
-	// Set user agent for temporary client.
-	c.UserAgent = settings.UserAgent
-
-	if err = c.CheckConnection(); d.checkAPICompatibility(c, err) != nil {
-		return err
+	if err != nil {
+		return nil
 	}
-
-	if username == "" {
-		d.Print("username: ")
-		fmt.Scanln(&username)
+	fmt.Printf("Opening browser to %s\n", URL)
+	d.Print("Waiting for login... ")
+	err = d.openBrower(URL)
+	if err != nil {
+		d.Print("Cannot open browser, please visit the website in yourself")
 	}
-
-	if password == "" {
-		d.Print("password: ")
-		password, err = readPassword()
-		if err != nil {
-			return err
-		}
-
-		d.Printf("\npassword (confirm): ")
-		passwordConfirm, err := readPassword()
-		d.Println()
-
-		if err != nil {
-			return err
-		}
-
-		if password != passwordConfirm {
-			return errors.New("password mismatch, aborting registration")
-		}
+	u, err := url.Parse(URL)
+	if err != nil {
+		return err
 	}
+	key := u.Query()["key"][0]
+	quit := progress(d.WOut)
+	d.doToken(s, key)
+	quit <- true
+	<-quit
+	return nil
+}
 
-	if email == "" {
-		d.Print("email: ")
-		fmt.Scanln(&email)
+func (d *DryccCmd) openBrower(URL string) error {
+	var commands = map[string]string{
+		"windows": "start",
+		"darwin":  "open",
+		"linux":   "xdg-open",
 	}
-
-	err = auth.Register(c, username, password, email)
-
-	c.Token = ""
-
-	if d.checkAPICompatibility(c, err) != nil {
-		d.PrintErr("Registration failed: ")
-		return err
+	run, ok := commands[runtime.GOOS]
+	if !ok {
+		return errors.New("warning: Cannot open browser")
 	}
-
-	d.Printf("Registered %s\n", username)
-
-	if login {
-		return d.Login(controller, username, password, sslVerify)
+	cmd := exec.Command(run, URL)
+	err := cmd.Start()
+	if err != nil {
+		return errors.New("warning: Cannot open browser")
 	}
 
 	return nil
 }
 
-func (d *DryccCmd) doLogin(s settings.Settings, username, password string) error {
-	token, err := auth.Login(s.Client, username, password)
-	if d.checkAPICompatibility(s.Client, err) != nil {
-		return err
+func (d *DryccCmd) doToken(s settings.Settings, key string) error {
+	var token api.AuthLoginResponse
+	for i := 0; i <= 120; i++ {
+		token, _ = auth.Token(s.Client, key)
+		if token != (api.AuthLoginResponse{}) {
+			break
+		}
+		time.Sleep(time.Duration(5) * time.Second)
 	}
-
-	s.Client.Token = token
-	s.Username = username
-
-	filename, err := s.Save(d.ConfigFile)
-
-	if err != nil {
-		return nil
+	if token.Token == "" || token.Token == "fail" {
+		d.Printf("Logged fail")
+	} else {
+		s.Client.Token = token.Token
+		s.Username = token.Username
+		filename, err := s.Save(d.ConfigFile)
+		if err != nil {
+			return nil
+		}
+		d.Printf("Logged in as %s\n", token.Username)
+		d.Printf("Configuration file written to %s\n", filename)
 	}
-
-	d.Printf("Logged in as %s\n", username)
-	d.Printf("Configuration file written to %s\n", filename)
 	return nil
 }
 
 // Login to a Drycc controller.
-func (d *DryccCmd) Login(controller string, username string, password string, sslVerify bool) error {
+func (d *DryccCmd) Login(controller string, sslVerify bool) error {
 	c, err := drycc.New(sslVerify, controller, "")
 
 	if err != nil {
@@ -118,23 +98,8 @@ func (d *DryccCmd) Login(controller string, username string, password string, ss
 		return err
 	}
 
-	if username == "" {
-		d.Print("username: ")
-		fmt.Scanln(&username)
-	}
-
-	if password == "" {
-		d.Print("password: ")
-		password, err = readPassword()
-		d.Println()
-
-		if err != nil {
-			return err
-		}
-	}
-
 	s := settings.Settings{Client: c}
-	return d.doLogin(s, username, password)
+	return d.doLogin(s)
 }
 
 // Logout from a Drycc controller.
@@ -147,117 +112,6 @@ func (d *DryccCmd) Logout() error {
 	return nil
 }
 
-// Passwd changes a user's password.
-func (d *DryccCmd) Passwd(username, password, newPassword string) error {
-	s, err := settings.Load(d.ConfigFile)
-
-	if err != nil {
-		return err
-	}
-
-	if password == "" && username == "" {
-		d.Print("current password: ")
-		password, err = readPassword()
-		d.Println()
-
-		if err != nil {
-			return err
-		}
-	}
-
-	if newPassword == "" {
-		d.Print("new password: ")
-		newPassword, err = readPassword()
-		if err != nil {
-			return err
-		}
-
-		d.Printf("\nnew password (confirm): ")
-		passwordConfirm, err := readPassword()
-
-		d.Println()
-
-		if err != nil {
-			return err
-		}
-
-		if newPassword != passwordConfirm {
-			return errors.New("password mismatch, not changing")
-		}
-	}
-
-	err = auth.Passwd(s.Client, username, password, newPassword)
-	if d.checkAPICompatibility(s.Client, err) != nil {
-		d.PrintErr("Password change failed: ")
-		return err
-	}
-
-	d.Println("Password change succeeded.")
-	return nil
-}
-
-// Cancel deletes a user's account.
-func (d *DryccCmd) Cancel(username, password string, yes bool) error {
-	s, err := settings.Load(d.ConfigFile)
-
-	if err != nil {
-		return err
-	}
-
-	if username == "" || password != "" {
-		d.Println("Please log in again in order to cancel this account")
-
-		if err = d.Login(s.Client.ControllerURL.String(), username, password, s.Client.VerifySSL); err != nil {
-			return err
-		}
-	}
-
-	if !yes {
-		confirm := ""
-
-		s, err = settings.Load(d.ConfigFile)
-
-		if err != nil {
-			return err
-		}
-
-		deletedUser := username
-
-		if deletedUser == "" {
-			deletedUser = s.Username
-		}
-
-		d.Printf("cancel account %s at %s? (y/N): ", deletedUser, s.Client.ControllerURL.String())
-		fmt.Scanln(&confirm)
-
-		if strings.ToLower(confirm) == "y" {
-			yes = true
-		}
-	}
-
-	if !yes {
-		d.PrintErrln("Account not changed")
-		return nil
-	}
-
-	err = auth.Delete(s.Client, username)
-	if err == drycc.ErrConflict {
-		return fmt.Errorf("%s still has applications associated with it. Transfer ownership or delete them first", username)
-	} else if d.checkAPICompatibility(s.Client, err) != nil {
-		return err
-	}
-
-	// If user targets themselves, logout.
-	if username == "" || s.Username == username {
-		if err := settings.Delete(d.ConfigFile); err != nil {
-			return err
-		}
-	}
-
-	d.Println("Account cancelled")
-	return nil
-}
-
 // Whoami prints the logged in user. If all is true, it fetches info from the controller to know
 // more about the user.
 func (d *DryccCmd) Whoami(all bool) error {
@@ -278,35 +132,3 @@ func (d *DryccCmd) Whoami(all bool) error {
 	}
 	return nil
 }
-
-// Regenerate regenenerates a user's token.
-func (d *DryccCmd) Regenerate(username string, all bool) error {
-	s, err := settings.Load(d.ConfigFile)
-
-	if err != nil {
-		return err
-	}
-
-	token, err := auth.Regenerate(s.Client, username, all)
-	if d.checkAPICompatibility(s.Client, err) != nil {
-		return err
-	}
-
-	if username == "" && !all {
-		s.Client.Token = token
-		_, err = s.Save(d.ConfigFile)
-
-		if err != nil {
-			return err
-		}
-	}
-
-	d.Println("Token Regenerated")
-	return nil
-}
-
-func readPassword() (string, error) {
-	password, err := terminal.ReadPassword(int(syscall.Stdin))
-
-	return string(password), err
-}
diff --git a/cmd/auth_test.go b/cmd/auth_test.go
index eeb492278..84a04ee31 100644
--- a/cmd/auth_test.go
+++ b/cmd/auth_test.go
@@ -10,7 +10,8 @@ import (
 	"github.com/drycc/workflow-cli/pkg/testutil"
 )
 
-func TestRegister(t *testing.T) {
+func TestLogin(t *testing.T) {
+	t.Skip("Skip long running tests")
 	cf, server, err := testutil.NewTestServerAndClient()
 	if err != nil {
 		t.Fatal(err)
@@ -25,64 +26,23 @@ func TestRegister(t *testing.T) {
 		fmt.Fprintf(w, `{}`)
 	})
 
-	username := "test-user"
-	password := "test-password"
-	email := "test-email@example.com"
-
-	server.Mux.HandleFunc("/v2/auth/register/", func(w http.ResponseWriter, r *http.Request) {
-		testutil.SetHeaders(w)
-		fmt.Fprintf(w, `{
-  "email": "`+email+`",
-  "username": "`+username+`",
-  "first_name": "",
-  "last_name": "",
-  "is_superuser": false,
-  "is_staff": false,
-  "groups": [],
-  "user_permissions": [],
-  "last_login": "2016-09-13T18:55:54Z",
-  "date_joined": "2016-09-13T18:55:54Z",
-  "is_active": true
-}`)
-	})
-
 	server.Mux.HandleFunc("/v2/auth/login/", func(w http.ResponseWriter, r *http.Request) {
 		testutil.SetHeaders(w)
-		fmt.Fprintf(w, `{}`)
-	})
-
-	err = cmdr.Register(server.Server.URL, username, password, email, true, false)
-	assert.NoErr(t, err)
-	expected := fmt.Sprintf("Registered %s\n", username)
-
-	assert.Equal(t, b.String(), expected, "output")
-}
-
-func TestLogin(t *testing.T) {
-	cf, server, err := testutil.NewTestServerAndClient()
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer server.Close()
-	var b bytes.Buffer
-	cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
-
-	server.Mux.HandleFunc("/v2/", func(w http.ResponseWriter, r *http.Request) {
-		testutil.SetHeaders(w)
-		w.WriteHeader(http.StatusUnauthorized)
-		fmt.Fprintf(w, `{}`)
+		w.Header().Add("Location", "/v2/login/drycc/?key=fdbf3b34742e4ed2be4dfa848af13007/")
+		w.WriteHeader(http.StatusOK)
+		w.Write(nil)
 	})
 
-	server.Mux.HandleFunc("/v2/auth/login/", func(w http.ResponseWriter, r *http.Request) {
+	server.Mux.HandleFunc("/v2/auth/token/fdbf3b34742e4ed2be4dfa848af13007/", func(w http.ResponseWriter, r *http.Request) {
 		testutil.SetHeaders(w)
-		fmt.Fprintf(w, `{}`)
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(`{"username":"test-user","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}`))
+		w.Write(nil)
 	})
-
-	username := "test-user"
-	err = cmdr.Login(server.Server.URL, username, "test-pass", true)
+	err = cmdr.Login(server.Server.URL, false)
+	fmt.Println(err)
+	fmt.Println(t)
 	assert.NoErr(t, err)
-	expected := fmt.Sprintf("Logged in as %s\nConfiguration file written to %s\n", username, cf)
-	assert.Equal(t, b.String(), expected, "output")
 }
 
 func TestLogout(t *testing.T) {
@@ -99,65 +59,6 @@ func TestLogout(t *testing.T) {
 	assert.Equal(t, b.String(), "Logged out\n", "output")
 }
 
-func TestPasswd(t *testing.T) {
-	t.Parallel()
-
-	cf, server, err := testutil.NewTestServerAndClient()
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer server.Close()
-	var b bytes.Buffer
-	cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
-
-	server.Mux.HandleFunc("/v2/auth/passwd/", func(w http.ResponseWriter, r *http.Request) {
-		testutil.SetHeaders(w)
-		fmt.Fprintf(w, `{}`)
-	})
-
-	// Change own password.
-	err = cmdr.Passwd("", "old-pass", "new-pass")
-	assert.NoErr(t, err)
-	assert.Equal(t, b.String(), "Password change succeeded.\n", "output")
-	b.Reset()
-
-	// Change another user's password.
-	err = cmdr.Passwd("another-user", "old-pass", "new-pass")
-	assert.NoErr(t, err)
-	assert.Equal(t, b.String(), "Password change succeeded.\n", "output")
-}
-
-func TestCancel(t *testing.T) {
-	cf, server, err := testutil.NewTestServerAndClient()
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer server.Close()
-	var b bytes.Buffer
-	cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
-
-	server.Mux.HandleFunc("/v2/", func(w http.ResponseWriter, r *http.Request) {
-		testutil.SetHeaders(w)
-		w.WriteHeader(http.StatusUnauthorized)
-		fmt.Fprintf(w, `{}`)
-	})
-
-	server.Mux.HandleFunc("/v2/auth/cancel/", func(w http.ResponseWriter, r *http.Request) {
-		testutil.SetHeaders(w)
-		fmt.Fprintf(w, `{}`)
-	})
-
-	server.Mux.HandleFunc("/v2/auth/login/", func(w http.ResponseWriter, r *http.Request) {
-		testutil.SetHeaders(w)
-		fmt.Fprintf(w, `{}`)
-	})
-
-	username := "test-user"
-	err = cmdr.Cancel(username, "", true)
-	assert.NoErr(t, err)
-	assert.Equal(t, b.String(), "Account cancelled\n", "output")
-}
-
 func TestWhoami(t *testing.T) {
 	t.Parallel()
 
@@ -235,24 +136,3 @@ Date Joined: 2015-09-12T22:15:26Z
 `
 	assert.Equal(t, b.String(), expected, "output")
 }
-
-func TestRegenerate(t *testing.T) {
-	t.Parallel()
-
-	cf, server, err := testutil.NewTestServerAndClient()
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer server.Close()
-	var b bytes.Buffer
-	cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
-
-	server.Mux.HandleFunc("/v2/auth/tokens/", func(w http.ResponseWriter, r *http.Request) {
-		testutil.SetHeaders(w)
-		fmt.Fprintf(w, `{}`)
-	})
-
-	err = cmdr.Regenerate("test", false)
-	assert.NoErr(t, err)
-	assert.Equal(t, b.String(), "Token Regenerated\n", "output")
-}
diff --git a/cmd/cmd.go b/cmd/cmd.go
index f0fb0e3ac..bf9a9fda1 100644
--- a/cmd/cmd.go
+++ b/cmd/cmd.go
@@ -21,13 +21,9 @@ type Commander interface {
 	AutoscaleList(string) error
 	AutoscaleSet(string, string, int, int, int) error
 	AutoscaleUnset(string, string) error
-	Register(string, string, string, string, bool, bool) error
-	Login(string, string, string, bool) error
+	Login(string, bool) error
 	Logout() error
-	Passwd(string, string, string) error
-	Cancel(string, string, bool) error
 	Whoami(bool) error
-	Regenerate(string, bool) error
 	BuildsList(string, int) error
 	BuildsCreate(string, string, string, string) error
 	CertsList(int, time.Time) error
diff --git a/cmd/shortcuts_test.go b/cmd/shortcuts_test.go
index b0803b77a..0ca0fafc7 100644
--- a/cmd/shortcuts_test.go
+++ b/cmd/shortcuts_test.go
@@ -14,9 +14,7 @@ login -> auth:login
 logout -> auth:logout
 logs -> apps:logs
 open -> apps:open
-passwd -> auth:passwd
 pull -> builds:create
-register -> auth:register
 rollback -> releases:rollback
 run -> apps:run
 scale -> ps:scale
diff --git a/go.mod b/go.mod
index 621e2ebc9..82995f7e3 100644
--- a/go.mod
+++ b/go.mod
@@ -5,9 +5,8 @@ go 1.13
 require (
 	github.com/arschles/assert v1.0.1-0.20191213221312-71f210f9375a
 	github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
-	github.com/drycc/controller-sdk-go v0.0.0-20201117012836-c2e1396c3333
+	github.com/drycc/controller-sdk-go v0.0.0-20210730033940-19fd0982c928
 	github.com/drycc/pkg v0.0.0-20200811173146-1f2b2781a852
 	github.com/olekukonko/tablewriter v0.0.4
-	golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
 	gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
 )
diff --git a/go.sum b/go.sum
index 04b239da9..72b887938 100644
--- a/go.sum
+++ b/go.sum
@@ -17,8 +17,6 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
 github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
-github.com/arschles/assert v1.0.0 h1:NofQbRhtxcLgP+XoKunA7J6UMJNTqX7xR/19tej8UsA=
-github.com/arschles/assert v1.0.0/go.mod h1:m/u69zW43x0h8dTHcv3JJZljINyEYgBuf5fYJP6WikI=
 github.com/arschles/assert v1.0.1-0.20191213221312-71f210f9375a h1:AUuANVdPi2cfXwkiBWgLb+NWkMTVD5zdAIjvJg9bCBY=
 github.com/arschles/assert v1.0.1-0.20191213221312-71f210f9375a/go.mod h1:DEpb9dlSxnDdJFQLnLwJHnNNpB+Ssa3mrqTSJ/xuv3E=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -28,29 +26,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/drycc/controller-sdk-go v0.0.0-20190417134318-39a6c81f21f3 h1:SzH+2aP7vpfvyPWaKtkIPnGbhdTWIWL2mQzQuzqAS9k=
-github.com/drycc/controller-sdk-go v0.0.0-20190417134318-39a6c81f21f3/go.mod h1:bf3lPkMsCK+DmEd8wc1yk3Wj0pDPni6cqglR+jqo1Dc=
-github.com/drycc/controller-sdk-go v0.0.0-20200804054414-9d56a7f85205 h1:6agdZ9/RhBofiEfnBiMdJd2Rbwr9Q/wMGxBO2ulOtvM=
-github.com/drycc/controller-sdk-go v0.0.0-20200804054414-9d56a7f85205/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20200813035713-e73ce53533e7 h1:8tlFlmR2XE6IULo2gG7YcOycaFCSMOcnSMP5M/rhBLQ=
-github.com/drycc/controller-sdk-go v0.0.0-20200813035713-e73ce53533e7/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20200901021526-471d3aa9862b h1:scZpGVSBX32HcCQcqwGmH1TKuy1xEczyF0fDH0XP1xA=
-github.com/drycc/controller-sdk-go v0.0.0-20200901021526-471d3aa9862b/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20200910051502-0b84631ba397 h1:MbpNwDOmS0+YxR0S8AsmygAj2qsOy9PjmLUzI76OhZs=
-github.com/drycc/controller-sdk-go v0.0.0-20200910051502-0b84631ba397/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20200914062048-dcf027e6dd1a h1:sQEQ8KUgm3X1y8XVsGXqeAkeowMGdOtu+PwBgd4V2eU=
-github.com/drycc/controller-sdk-go v0.0.0-20200914062048-dcf027e6dd1a/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20201013084049-82230b1dc54f h1:Lwm3ijm8W+STLHOOmumLSQRvCkUTuya+XkGM+VNFfGA=
-github.com/drycc/controller-sdk-go v0.0.0-20201013084049-82230b1dc54f/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20201015015256-370f01036885 h1:lA6ERNPzsqPeEcoPX5s/G7eMu7NH6cJh8ZyOtXAcVxM=
-github.com/drycc/controller-sdk-go v0.0.0-20201015015256-370f01036885/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20201015065118-cb8f4f5e9745 h1:C3Byx1KvZtzuilCp5aikRa5hbXCUhiy8u4Iv6ATyDcI=
-github.com/drycc/controller-sdk-go v0.0.0-20201015065118-cb8f4f5e9745/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20201105013635-42fda9fec714/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/controller-sdk-go v0.0.0-20201117012836-c2e1396c3333 h1:BzGLCDwKVS1btrf2HhcNwtcDGwBYbGl0U6147IFfTUc=
-github.com/drycc/controller-sdk-go v0.0.0-20201117012836-c2e1396c3333/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
-github.com/drycc/pkg v0.0.0-20190129033019-bcdffff0fcb3 h1:QRAbL97/hJecXQzaSONMCiwt1JjBKAAMKK0qJW5sgIM=
-github.com/drycc/pkg v0.0.0-20190129033019-bcdffff0fcb3/go.mod h1:zNgTT6kuGZOKMIdSrjskIw5fctdbbszqiTPEt3ffxHw=
+github.com/drycc/controller-sdk-go v0.0.0-20210730033940-19fd0982c928 h1:7vFq/kxahidvkipa+pvLfmhpBH7yvr/O5NGjv7Z2s2I=
+github.com/drycc/controller-sdk-go v0.0.0-20210730033940-19fd0982c928/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
 github.com/drycc/pkg v0.0.0-20200811173146-1f2b2781a852 h1:OsWH7jrv2i32rkvHFuj3yVpGMR+A6heRge9tm01XR/U=
 github.com/drycc/pkg v0.0.0-20200811173146-1f2b2781a852/go.mod h1:ojTmgbTG5tOJcTirzcdyHwEDxV0OQTm5AqnnBgdOjYE=
 github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
@@ -93,8 +70,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
 github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
 github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
 github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
-github.com/goware/urlx v0.2.0 h1:E4bW8qSmhUgJ7Z5qY93mfN+IiUPXi66iua1Wza0wP7I=
-github.com/goware/urlx v0.2.0/go.mod h1:h8uwbJy68o+tQXCGZNa9D73WN8n0r9OBae5bUnLcgjw=
 github.com/goware/urlx v0.3.1 h1:BbvKl8oiXtJAzOzMqAQ0GfIhf96fKeNEZfm9ocNSUBI=
 github.com/goware/urlx v0.3.1/go.mod h1:h8uwbJy68o+tQXCGZNa9D73WN8n0r9OBae5bUnLcgjw=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -108,12 +83,12 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
-github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
 github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -122,8 +97,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
-github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
-github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
 github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -142,12 +115,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a h1:Igim7XhdOpBnWPuYJ70XcNpq8q3BCACtVgNfoJxOV7g=
-golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
-golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -160,8 +129,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190415214537-1da14a5a36f2 h1:iC0Y6EDq+rhnAePxGvJs2kzUAYcwESqdcGRPzEUfzTU=
-golang.org/x/net v0.0.0-20190415214537-1da14a5a36f2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
 golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -177,10 +144,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190416152802-12500544f89f h1:1ZH9RnjNgLzh6YrsRp/c6ddZ8Lq0fq9xztNOoWJ2sz4=
-golang.org/x/sys v0.0.0-20190416152802-12500544f89f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
 golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -215,6 +179,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
 google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
@@ -233,8 +198,10 @@ k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
 k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
+k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
 k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
diff --git a/parser/auth.go b/parser/auth.go
index 0db65dc15..0a0f15141 100644
--- a/parser/auth.go
+++ b/parser/auth.go
@@ -12,32 +12,20 @@ func Auth(argv []string, cmdr cmd.Commander) error {
 	usage := `
 Valid commands for auth:
 
-auth:register          register a new user
 auth:login             authenticate against a controller
 auth:logout            clear the current user session
-auth:passwd            change the password for the current user
 auth:whoami            display the current user
-auth:cancel            remove the current user account
-auth:regenerate        regenerate user tokens
 
 Use 'drycc help [command]' to learn more.
 `
 
 	switch argv[0] {
-	case "auth:register":
-		return authRegister(argv, cmdr)
 	case "auth:login":
 		return authLogin(argv, cmdr)
 	case "auth:logout":
 		return authLogout(argv, cmdr)
-	case "auth:passwd":
-		return authPasswd(argv, cmdr)
 	case "auth:whoami":
 		return authWhoami(argv, cmdr)
-	case "auth:cancel":
-		return authCancel(argv, cmdr)
-	case "auth:regenerate":
-		return authRegenerate(argv, cmdr)
 	case "auth":
 		fmt.Print(usage)
 		return nil
@@ -47,57 +35,6 @@ Use 'drycc help [command]' to learn more.
 	}
 }
 
-func authRegister(argv []string, cmdr cmd.Commander) error {
-	usage := `
-Registers a new user with a Drycc controller.
-
-Usage: drycc auth:register <controller> [options]
-
-Arguments:
-  <controller>
-    fully-qualified controller URI, e.g. 'http://drycc.local3.dryccapp.com/'
-
-Options:
-  --username=<username>
-    provide a username for the new account.
-  --password=<password>
-    provide a password for the new account.
-  --email=<email>
-    provide an email address.
-  --login=true
-    logs into the new account after registering.
-  --ssl-verify=true
-    enables/disables SSL certificate verification for API requests
-`
-
-	args, err := docopt.Parse(usage, argv, true, "", false, true)
-
-	if err != nil {
-		return err
-	}
-
-	controller := safeGetValue(args, "<controller>")
-	username := safeGetValue(args, "--username")
-	password := safeGetValue(args, "--password")
-	email := safeGetValue(args, "--email")
-	sslVerify := true
-	login := true
-
-	if args["--ssl-verify"] != nil && args["--ssl-verify"].(string) == "false" {
-		sslVerify = false
-	}
-
-	// NOTE(bacongobbler): two use cases to check here:
-	//
-	// 1) Legacy; calling `drycc auth:register` without --login
-	// 2) calling `drycc auth:register --login false`
-	if args["--login"] != nil && args["--login"].(string) == "false" {
-		login = false
-	}
-
-	return cmdr.Register(controller, username, password, email, sslVerify, login)
-}
-
 func authLogin(argv []string, cmdr cmd.Commander) error {
 	usage := `
 Logs in by authenticating against a controller.
@@ -109,10 +46,6 @@ Arguments:
     a fully-qualified controller URI, e.g. "http://drycc.local3.dryccapp.com/".
 
 Options:
-  --username=<username>
-    provide a username for the account.
-  --password=<password>
-    provide a password for the account.
   --ssl-verify=true
     enables/disables SSL certificate verification for API requests
 `
@@ -124,15 +57,13 @@ Options:
 	}
 
 	controller := safeGetValue(args, "<controller>")
-	username := safeGetValue(args, "--username")
-	password := safeGetValue(args, "--password")
 	sslVerify := true
 
 	if args["--ssl-verify"] != nil && args["--ssl-verify"].(string) == "false" {
 		sslVerify = false
 	}
 
-	return cmdr.Login(controller, username, password, sslVerify)
+	return cmdr.Login(controller, sslVerify)
 }
 
 func authLogout(argv []string, cmdr cmd.Commander) error {
@@ -151,34 +82,6 @@ Options:
 	return cmdr.Logout()
 }
 
-func authPasswd(argv []string, cmdr cmd.Commander) error {
-	usage := `
-Changes the password for the current user.
-
-Usage: drycc auth:passwd [options]
-
-Options:
-  --password=<password>
-    the current password for the account.
-  --new-password=<new-password>
-    the new password for the account.
-  --username=<username>
-    the account's username.
-`
-
-	args, err := docopt.Parse(usage, argv, true, "", false, true)
-
-	if err != nil {
-		return err
-	}
-
-	username := safeGetValue(args, "--username")
-	password := safeGetValue(args, "--password")
-	newPassword := safeGetValue(args, "--new-password")
-
-	return cmdr.Passwd(username, password, newPassword)
-}
-
 func authWhoami(argv []string, cmdr cmd.Commander) error {
 	usage := `
 Displays the currently logged in user.
@@ -198,56 +101,3 @@ Options:
 
 	return cmdr.Whoami(args["--all"].(bool))
 }
-
-func authCancel(argv []string, cmdr cmd.Commander) error {
-	usage := `
-Cancels and removes the current account.
-
-Usage: drycc auth:cancel [options]
-
-Options:
-  --username=<username>
-    provide a username for the account.
-  --password=<password>
-    provide a password for the account.
-  --yes
-    force "yes" when prompted.
-`
-
-	args, err := docopt.Parse(usage, argv, true, "", false, true)
-
-	if err != nil {
-		return err
-	}
-
-	username := safeGetValue(args, "--username")
-	password := safeGetValue(args, "--password")
-	yes := args["--yes"].(bool)
-
-	return cmdr.Cancel(username, password, yes)
-}
-
-func authRegenerate(argv []string, cmdr cmd.Commander) error {
-	usage := `
-Regenerates auth token, defaults to regenerating token for the current user.
-
-Usage: drycc auth:regenerate [options]
-
-Options:
-  -u --username=<username>
-    specify user to regenerate. Requires admin privileges.
-  --all
-    regenerate token for every user. Requires admin privileges.
-`
-
-	args, err := docopt.Parse(usage, argv, true, "", false, true)
-
-	if err != nil {
-		return err
-	}
-
-	username := safeGetValue(args, "--username")
-	all := args["--all"].(bool)
-
-	return cmdr.Regenerate(username, all)
-}
diff --git a/parser/auth_test.go b/parser/auth_test.go
index 1c5e00e9f..8820b77a4 100644
--- a/parser/auth_test.go
+++ b/parser/auth_test.go
@@ -12,11 +12,7 @@ import (
 // Create fake implementations of each method that return the argument
 // we expect to have called the function (as an error to satisfy the interface).
 
-func (d FakeDryccCmd) Register(string, string, string, string, bool, bool) error {
-	return errors.New("auth:register")
-}
-
-func (d FakeDryccCmd) Login(string, string, string, bool) error {
+func (d FakeDryccCmd) Login(string, bool) error {
 	return errors.New("auth:login")
 }
 
@@ -24,22 +20,10 @@ func (d FakeDryccCmd) Logout() error {
 	return errors.New("auth:logout")
 }
 
-func (d FakeDryccCmd) Passwd(string, string, string) error {
-	return errors.New("auth:passwd")
-}
-
-func (d FakeDryccCmd) Cancel(string, string, bool) error {
-	return errors.New("auth:cancel")
-}
-
 func (d FakeDryccCmd) Whoami(bool) error {
 	return errors.New("auth:whoami")
 }
 
-func (d FakeDryccCmd) Regenerate(string, bool) error {
-	return errors.New("auth:regenerate")
-}
-
 func TestAuth(t *testing.T) {
 	t.Parallel()
 
@@ -57,46 +41,18 @@ func TestAuth(t *testing.T) {
 		args     []string
 		expected string
 	}{
-		{
-			args:     []string{"auth:register", server.Server.URL},
-			expected: "",
-		},
-		{
-			args:     []string{"auth:register", server.Server.URL, "--ssl-verify=true"},
-			expected: "",
-		},
-		{
-			args:     []string{"auth:register", server.Server.URL, "--login=false"},
-			expected: "",
-		},
 		{
 			args:     []string{"auth:login", server.Server.URL},
 			expected: "",
 		},
-		{
-			args:     []string{"auth:login", server.Server.URL, "--ssl-verify=true"},
-			expected: "",
-		},
 		{
 			args:     []string{"auth:logout"},
 			expected: "",
 		},
-		{
-			args:     []string{"auth:passwd"},
-			expected: "",
-		},
 		{
 			args:     []string{"auth:whoami"},
 			expected: "",
 		},
-		{
-			args:     []string{"auth:cancel"},
-			expected: "",
-		},
-		{
-			args:     []string{"auth:regenerate"},
-			expected: "",
-		},
 	}
 
 	// For each case, check that calling the route with the arguments
