forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
logout.go
149 lines (116 loc) · 4.22 KB
/
logout.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
package logout
import (
"errors"
"fmt"
"github.com/spf13/cobra"
"k8s.io/klog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
restclient "k8s.io/client-go/rest"
kclientcmd "k8s.io/client-go/tools/clientcmd"
kclientcmdapi "k8s.io/client-go/tools/clientcmd/api"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/util/templates"
oauthv1client "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1"
kubeconfiglib "github.com/openshift/origin/pkg/oc/lib/kubeconfig"
"github.com/openshift/origin/pkg/oc/util/project"
)
type LogoutOptions struct {
StartingKubeConfig *kclientcmdapi.Config
Config *restclient.Config
PathOptions *kclientcmd.PathOptions
genericclioptions.IOStreams
}
var (
logoutLong = templates.LongDesc(`
Log out of the active session out by clearing saved tokens
An authentication token is stored in the config file after login - this command will delete
that token on the server, and then remove the token from the configuration file.
If you are using an alternative authentication method like Kerberos or client certificates,
your ticket or client certificate will not be removed from the current system since these
are typically managed by other programs. Instead, you can delete your config file to remove
the local copy of that certificate or the record of your server login.
After logging out, if you want to log back into the server use '%[1]s'.`)
logoutExample = templates.Examples(`
# Logout
%[1]s`)
)
func NewLogoutOptions(streams genericclioptions.IOStreams) *LogoutOptions {
return &LogoutOptions{
IOStreams: streams,
}
}
// NewCmdLogout implements the OpenShift cli logout command
func NewCmdLogout(name, fullName, ocLoginFullCommand string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := NewLogoutOptions(streams)
cmds := &cobra.Command{
Use: name,
Short: "End the current server session",
Long: fmt.Sprintf(logoutLong, ocLoginFullCommand),
Example: fmt.Sprintf(logoutExample, fullName),
Run: func(cmd *cobra.Command, args []string) {
kcmdutil.CheckErr(o.Complete(f, cmd, args))
kcmdutil.CheckErr(o.Validate(args))
kcmdutil.CheckErr(o.RunLogout())
},
}
// TODO: support --all which performs the same logic on all users in your config file.
return cmds
}
func (o *LogoutOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error {
kubeconfig, err := f.ToRawKubeConfigLoader().RawConfig()
if err != nil {
return err
}
o.StartingKubeConfig = &kubeconfig
o.Config, err = f.ToRESTConfig()
if err != nil {
return err
}
o.PathOptions = kubeconfiglib.NewPathOptions(cmd)
return nil
}
func (o LogoutOptions) Validate(args []string) error {
if len(args) > 0 {
return errors.New("No arguments are allowed")
}
if o.StartingKubeConfig == nil {
return errors.New("Must have a config file already created")
}
if len(o.Config.BearerToken) == 0 {
return errors.New("You must have a token in order to logout.")
}
return nil
}
func (o LogoutOptions) RunLogout() error {
token := o.Config.BearerToken
client, err := oauthv1client.NewForConfig(o.Config)
if err != nil {
return err
}
userInfo, err := project.WhoAmI(o.Config)
if err != nil {
return err
}
if err := client.OAuthAccessTokens().Delete(token, &metav1.DeleteOptions{}); err != nil {
klog.V(1).Infof("%v", err)
}
configErr := deleteTokenFromConfig(*o.StartingKubeConfig, o.PathOptions, token)
if configErr == nil {
klog.V(1).Infof("Removed token from your local configuration.")
// only return error instead of successful message if removing token from client
// config fails. Any error that occurs deleting token using api is logged above.
fmt.Fprintf(o.Out, "Logged %q out on %q\n", userInfo.Name, o.Config.Host)
}
return configErr
}
func deleteTokenFromConfig(config kclientcmdapi.Config, pathOptions *kclientcmd.PathOptions, bearerToken string) error {
for key, value := range config.AuthInfos {
if value.Token == bearerToken {
value.Token = ""
config.AuthInfos[key] = value
// don't break, its possible that more than one user stanza has the same token.
}
}
return kclientcmd.ModifyConfig(pathOptions, config, true)
}