1
4 package tokens
5
6 import (
7 "context"
8 "flag"
9 "fmt"
10 "golang.conradwood.net/go-easyops/cmdline"
11 "golang.conradwood.net/go-easyops/utils"
12 "google.golang.org/grpc/metadata"
13 "io/ioutil"
14 "os"
15 "os/user"
16 "strings"
17 "time"
18 )
19
20 var (
21 e_token = cmdline.ENV("GE_USERTOKEN", "a service token")
22 e_usertoken = cmdline.ENV("GE_USERTOKEN", "a usertoken")
23 token = flag.String("token", "", "service token")
24 disusertoken = flag.Bool("ge_disable_user_token", false, "if true disable reading of user token (for testing)")
25 tokenwasread = false
26 usertoken string
27 last_token_read_registry string
28 cloudname = "yacloud.eu"
29 debug = flag.Bool("ge_debug_tokens", false, "debug user token stuff")
30 )
31
32 const (
33 METANAME = "goeasyops_meta"
34
35 )
36
37 func DisableUserToken() {
38 tokenwasread = true
39 usertoken = ""
40 }
41
42
43 func buildMeta() metadata.MD {
44 panic("obsolete codepath")
45 }
46
47
48
49
50
51 func DISContextWithToken() context.Context {
52
53
58 md := buildMeta()
59 ctx, cnc := context.WithTimeout(context.Background(), time.Duration(10)*time.Second)
60 go func(cf context.CancelFunc) {
61 time.Sleep(time.Duration((10)+5) * time.Second)
62 cnc()
63 }(cnc)
64 return metadata.NewOutgoingContext(ctx, md)
65
66 }
67
68
69 func DISContextWithTokenAndTimeout(seconds uint64) context.Context {
70 if cmdline.ContextWithBuilder() {
71 utils.NotImpl("contextv2 incomplete")
72 }
73 md := buildMeta()
74 ctx, cnc := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
75 go func(cf context.CancelFunc, s uint64) {
76 time.Sleep(time.Duration(s+5) * time.Second)
77 cnc()
78 }(cnc, seconds)
79 return metadata.NewOutgoingContext(ctx, md)
80 }
81
82
83 func DISContext2WithTokenAndTimeout(seconds uint64) (context.Context, context.CancelFunc) {
84 if cmdline.ContextWithBuilder() {
85 panic("contextv2 incomplete")
86 }
87 md := buildMeta()
88 ctx, cnc := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
89 ctx = metadata.NewOutgoingContext(ctx, md)
90 return ctx, cnc
91 }
92
93 func SetServiceTokenParameter(tok string) {
94 *token = tok
95 }
96 func GetServiceTokenParameter() string {
97 if *token != "" {
98 return *token
99 }
100 return e_token.Value()
101 }
102 func readToken(token string) string {
103 if *disusertoken {
104 panic("codepath bug. user token is disabled but attempted to read it")
105 }
106 var tok string
107 var btok []byte
108 var fname string
109 fname = "n/a"
110 usr, err := user.Current()
111 if err != nil {
112 fmt.Printf("[go-easyops] Failed to determine current user: %s\n", err)
113 return ""
114 }
115 fnames := []string{
116 fmt.Sprintf("%s/.go-easyops/tokens/%s.%s", usr.HomeDir, token, cloudname),
117 fmt.Sprintf("%s/.go-easyops/tokens/%s.%s", usr.HomeDir, token, cmdline.GetRegistryAddress()),
118 fmt.Sprintf("%s/.go-easyops/tokens/%s", usr.HomeDir, token),
119 }
120 for _, fname = range fnames {
121 if _, err := os.Stat(fname); os.IsNotExist(err) {
122 if *debug {
123 fmt.Printf("File \"%s\" does not exist - ignoring.\n", fname)
124 }
125 continue
126 }
127 break
128 }
129
130 if _, err := os.Stat(fname); os.IsNotExist(err) {
131
132 return ""
133 }
134 if *debug {
135 fmt.Printf("[go-easyops] Reading file \"%s\", parsing as token\n", fname)
136 }
137 btok, err = ioutil.ReadFile(fname)
138 if err != nil {
139 fmt.Printf("[go-easyops] Failed to read user token: %s\n", err)
140 return ""
141 } else if len(btok) == 0 {
142 fmt.Printf("[go-easyops] Failed to read user token from %s\n", fname)
143 return ""
144
145 } else {
146 tok = string(btok)
147 }
148 tok = strings.TrimSpace(tok)
149
150 if *debug {
151 fmt.Printf("[go-easyops] token is empty\n")
152 if len(tok) < 5 {
153 fmt.Printf("[go-easyops] token is too short\n")
154 } else {
155 fmt.Printf("[go-easyops] token: %s...\n", tok[:3])
156 }
157 }
158 return tok
159 }
160
161
172 func GetUserTokenParameter() string {
173 if *disusertoken {
174
175 return ""
176 }
177
178 ut := e_usertoken.Value()
179 if ut != "" {
180 if *debug {
181 fmt.Printf("[go-easyops] tokens: getting user token from e_usertoken\n")
182 }
183 return ut
184 }
185
186
187
196 if e_token.Value() != "" {
197 return e_token.Value()
198 }
199
200 if tokenwasread && last_token_read_registry == cmdline.GetClientRegistryAddress() {
201 return usertoken
202 }
203 u := readToken("user_token")
204 usertoken = u
205 tokenwasread = true
206 last_token_read_registry = cmdline.GetClientRegistryAddress()
207
214 return usertoken
215 }
216
217 func SaveUserToken(token string) error {
218 usr, err := user.Current()
219 if err != nil {
220 err := fmt.Errorf("Failed to determine current operating system user: %s (are you logged in to your computer?)\n", err)
221 return err
222 }
223 dir := fmt.Sprintf("%s/.go-easyops/tokens", usr.HomeDir)
224 os.MkdirAll(dir, 0700)
225 fname := fmt.Sprintf("%s/.go-easyops/tokens/user_token", usr.HomeDir)
226 err = utils.WriteFile(fname, []byte(token))
227 if err != nil {
228 fmt.Printf("Failed to save access token: %s\n", err)
229 return err
230 }
231 tokenwasread = false
232 return nil
233 }
234 func GetCloudName() string {
235 return cloudname
236 }
237 func SetCloudName(xcloudname string) {
238 if xcloudname != "" && xcloudname != cloudname {
239 if *debug {
240 fmt.Printf("setting cloud name to \"%s\"\n", xcloudname)
241 }
242 cloudname = xcloudname
243 tokenwasread = false
244 }
245 }
246
View as plain text