/
cmd_deprovision.go
163 lines (139 loc) · 4.33 KB
/
cmd_deprovision.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package client
import (
"fmt"
"github.com/keybase/cli"
"github.com/adamwalz/keybase-client/go/libcmdline"
"github.com/adamwalz/keybase-client/go/libkb"
keybase1 "github.com/adamwalz/keybase-client/go/protocol/keybase1"
"github.com/keybase/go-framed-msgpack-rpc/rpc"
"golang.org/x/net/context"
)
type CmdDeprovision struct {
libkb.Contextified
loggedIn bool
}
func NewCmdDeprovision(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
return cli.Command{
Name: "deprovision",
Usage: "Revoke the current device, log out, and delete local state.",
Action: func(c *cli.Context) {
cl.ChooseCommand(&CmdDeprovision{
Contextified: libkb.NewContextified(g),
}, "deprovision", c)
},
}
}
func (c *CmdDeprovision) Run() (err error) {
protocols := []rpc.Protocol{
NewLogUIProtocol(c.G()),
NewSecretUIProtocol(c.G()),
}
if err = RegisterProtocolsWithContext(protocols, c.G()); err != nil {
return err
}
username, err := c.getUsernameToDeprovision()
if err != nil {
return err
}
warning, err := c.getBigScaryWarning(username)
if err != nil {
return err
}
if err = c.G().UI.GetTerminalUI().PromptForConfirmation(warning); err != nil {
return err
}
loginCli, err := GetLoginClient(c.G())
if err != nil {
return err
}
// XXX: This RPC deletes secret keys!
return loginCli.Deprovision(context.TODO(), keybase1.DeprovisionArg{
SessionID: 0,
Username: username,
DoRevoke: c.loggedIn,
})
}
func (c *CmdDeprovision) GetUsage() libkb.Usage {
return libkb.Usage{
API: true,
Config: true,
KbKeyring: true,
}
}
func (c *CmdDeprovision) ParseArgv(ctx *cli.Context) error {
return nil
}
func (c *CmdDeprovision) getUsernameToDeprovision() (string, error) {
configCli, err := GetConfigClient(c.G())
if err != nil {
return "", err
}
currentStatus, err := configCli.GetCurrentStatus(context.TODO(), 0)
if err != nil {
return "", err
}
// If there is a user logged in, just return that user.
if currentStatus.LoggedIn {
c.loggedIn = true
return currentStatus.User.Username, nil
}
// Otherwise, find all the users in the config file.
current, others, err := c.G().Env.GetConfig().GetAllUsernames()
if err != nil {
return "", err
}
allUsers := []libkb.NormalizedUsername{}
if current.String() != "" {
allUsers = append(allUsers, current)
}
allUsers = append(allUsers, others...)
// If there's no one in the config file, there's nothing to do.
if len(allUsers) == 0 {
return "", fmt.Errorf("Can't find a user to deprovision.")
}
// If there's only one user in the config file, just pick that one.
if len(allUsers) == 1 {
return allUsers[0].String(), nil
}
fmt.Printf("No one currently logged in. Which user would you like to deprovision?\n")
for i, user := range allUsers {
fmt.Printf("%d) %s\n", i+1, user.String())
}
choice, err := PromptSelectionOrCancel(PromptDescriptorDeprovisionWhichUser,
c.G().UI.GetTerminalUI(), "Choose a user", 1, len(allUsers))
if err != nil {
return "", err
}
return allUsers[choice-1].String(), nil
}
func (c *CmdDeprovision) getBigScaryWarning(username string) (string, error) {
// If the user is logged out, warn that we won't revoke their keys.
loggedOutWarning := ""
if !c.loggedIn {
loggedOutWarning = `
Note that you aren't currently logged in. That means we won't publicly revoke
this device's keys. To do that from another device, use 'keybase device remove'.`
}
// If the user has PGP secret keys in the SKBKeyring, print an additional warning.
mctx := libkb.NewMetaContextTODO(c.G())
keyring, err := libkb.LoadSKBKeyring(mctx, libkb.NewNormalizedUsername(username))
if err != nil {
return "", err
}
pgpWarning := ""
if keyring.HasPGPKeys() {
pgpWarning = fmt.Sprintf(`
Also, the secret keyring you're about to delete contains PGP keys. To list them
or copy them, use %s.`, "`keybase pgp export`")
}
// TODO: Print a list of the other devices on the user's account.
return fmt.Sprintf(`
%s, BE CAREFUL! \('o')/
You are about to delete this device from your account, including its secret
keys. You will not be able to reuse the device name for a new device.
If you don't have any other devices, you'll lose access to your account
and all your data!%s%s
Proceed?`, username, loggedOutWarning, pgpWarning), nil
}