@@ -15,24 +15,61 @@ import (
15
15
"github.com/99designs/keyring"
16
16
)
17
17
18
+ type tokenType string
19
+
20
+ const (
21
+ idToken tokenType = "ID_TOKEN"
22
+ mfaToken tokenType = "MFATOKEN"
23
+ )
24
+
18
25
const (
19
26
driverName = "SNOWFLAKE-GO-DRIVER"
20
27
credCacheDirEnv = "SF_TEMPORARY_CREDENTIAL_CACHE_DIR"
21
28
credCacheFileName = "temporary_credential.json"
22
29
)
23
30
31
+ type secureTokenSpec struct {
32
+ host , user string
33
+ tokenType tokenType
34
+ }
35
+
36
+ func (t * secureTokenSpec ) buildKey () string {
37
+ return buildCredentialsKey (t .host , t .user , t .tokenType )
38
+ }
39
+
40
+ func newMfaTokenSpec (host , user string ) * secureTokenSpec {
41
+ return & secureTokenSpec {
42
+ host ,
43
+ user ,
44
+ mfaToken ,
45
+ }
46
+ }
47
+
48
+ func newIDTokenSpec (host , user string ) * secureTokenSpec {
49
+ return & secureTokenSpec {
50
+ host ,
51
+ user ,
52
+ idToken ,
53
+ }
54
+ }
55
+
24
56
type secureStorageManager interface {
25
- setCredential (sc * snowflakeConn , credType , token string )
26
- getCredential (sc * snowflakeConn , credType string )
27
- deleteCredential (sc * snowflakeConn , credType string )
57
+ setCredential (tokenSpec * secureTokenSpec , value string )
58
+ getCredential (tokenSpec * secureTokenSpec ) string
59
+ deleteCredential (tokenSpec * secureTokenSpec )
28
60
}
29
61
30
62
var credentialsStorage = newSecureStorageManager ()
31
63
32
64
func newSecureStorageManager () secureStorageManager {
33
65
switch runtime .GOOS {
34
66
case "linux" :
35
- return newFileBasedSecureStorageManager ()
67
+ ssm , err := newFileBasedSecureStorageManager ()
68
+ if err != nil {
69
+ logger .Debugf ("failed to create credentials cache dir. %v" , err )
70
+ return newNoopSecureStorageManager ()
71
+ }
72
+ return ssm
36
73
case "darwin" , "windows" :
37
74
return newKeyringBasedSecureStorageManager ()
38
75
default :
@@ -46,20 +83,19 @@ type fileBasedSecureStorageManager struct {
46
83
credCacheLock sync.RWMutex
47
84
}
48
85
49
- func newFileBasedSecureStorageManager () secureStorageManager {
86
+ func newFileBasedSecureStorageManager () ( * fileBasedSecureStorageManager , error ) {
50
87
ssm := & fileBasedSecureStorageManager {
51
88
localCredCache : map [string ]string {},
52
89
credCacheLock : sync.RWMutex {},
53
90
}
54
91
credCacheDir := ssm .buildCredCacheDirPath ()
55
92
if err := ssm .createCacheDir (credCacheDir ); err != nil {
56
- logger .Debugf ("failed to create credentials cache dir. %v" , err )
57
- return newNoopSecureStorageManager ()
93
+ return nil , err
58
94
}
59
95
credCacheFilePath := filepath .Join (credCacheDir , credCacheFileName )
60
96
logger .Infof ("Credentials cache path: %v" , credCacheFilePath )
61
97
ssm .credCacheFilePath = credCacheFilePath
62
- return ssm
98
+ return ssm , nil
63
99
}
64
100
65
101
func (ssm * fileBasedSecureStorageManager ) createCacheDir (credCacheDir string ) error {
@@ -87,14 +123,14 @@ func (ssm *fileBasedSecureStorageManager) buildCredCacheDirPath() string {
87
123
return credCacheDir
88
124
}
89
125
90
- func (ssm * fileBasedSecureStorageManager ) setCredential (sc * snowflakeConn , credType , token string ) {
91
- if token == "" {
126
+ func (ssm * fileBasedSecureStorageManager ) setCredential (tokenSpec * secureTokenSpec , value string ) {
127
+ if value == "" {
92
128
logger .Debug ("no token provided" )
93
129
} else {
94
- credentialsKey := buildCredentialsKey ( sc . cfg . Host , sc . cfg . User , credType )
130
+ credentialsKey := tokenSpec . buildKey ( )
95
131
ssm .credCacheLock .Lock ()
96
132
defer ssm .credCacheLock .Unlock ()
97
- ssm .localCredCache [credentialsKey ] = token
133
+ ssm .localCredCache [credentialsKey ] = value
98
134
99
135
j , err := json .Marshal (ssm .localCredCache )
100
136
if err != nil {
@@ -135,8 +171,8 @@ func (ssm *fileBasedSecureStorageManager) setCredential(sc *snowflakeConn, credT
135
171
}
136
172
}
137
173
138
- func (ssm * fileBasedSecureStorageManager ) getCredential (sc * snowflakeConn , credType string ) {
139
- credentialsKey := buildCredentialsKey ( sc . cfg . Host , sc . cfg . User , credType )
174
+ func (ssm * fileBasedSecureStorageManager ) getCredential (tokenSpec * secureTokenSpec ) string {
175
+ credentialsKey := tokenSpec . buildKey ( )
140
176
ssm .credCacheLock .Lock ()
141
177
defer ssm .credCacheLock .Unlock ()
142
178
localCredCache := ssm .readTemporaryCacheFile ()
@@ -146,14 +182,7 @@ func (ssm *fileBasedSecureStorageManager) getCredential(sc *snowflakeConn, credT
146
182
} else {
147
183
logger .Debug ("Returned credential is empty" )
148
184
}
149
-
150
- if credType == idToken {
151
- sc .cfg .IDToken = cred
152
- } else if credType == mfaToken {
153
- sc .cfg .MfaToken = cred
154
- } else {
155
- logger .Debugf ("Unrecognized type %v for local cached credential" , credType )
156
- }
185
+ return cred
157
186
}
158
187
159
188
func (ssm * fileBasedSecureStorageManager ) readTemporaryCacheFile () map [string ]string {
@@ -171,10 +200,10 @@ func (ssm *fileBasedSecureStorageManager) readTemporaryCacheFile() map[string]st
171
200
return ssm .localCredCache
172
201
}
173
202
174
- func (ssm * fileBasedSecureStorageManager ) deleteCredential (sc * snowflakeConn , credType string ) {
203
+ func (ssm * fileBasedSecureStorageManager ) deleteCredential (tokenSpec * secureTokenSpec ) {
175
204
ssm .credCacheLock .Lock ()
176
205
defer ssm .credCacheLock .Unlock ()
177
- credentialsKey := buildCredentialsKey ( sc . cfg . Host , sc . cfg . User , credType )
206
+ credentialsKey := tokenSpec . buildKey ( )
178
207
delete (ssm .localCredCache , credentialsKey )
179
208
j , err := json .Marshal (ssm .localCredCache )
180
209
if err != nil {
@@ -220,37 +249,35 @@ func (ssm *fileBasedSecureStorageManager) writeTemporaryCacheFile(input []byte)
220
249
type keyringSecureStorageManager struct {
221
250
}
222
251
223
- func newKeyringBasedSecureStorageManager () secureStorageManager {
252
+ func newKeyringBasedSecureStorageManager () * keyringSecureStorageManager {
224
253
return & keyringSecureStorageManager {}
225
254
}
226
255
227
- func (ssm * keyringSecureStorageManager ) setCredential (sc * snowflakeConn , credType , token string ) {
228
- if token == "" {
256
+ func (ssm * keyringSecureStorageManager ) setCredential (tokenSpec * secureTokenSpec , value string ) {
257
+ if value == "" {
229
258
logger .Debug ("no token provided" )
230
259
} else {
231
- var credentialsKey string
260
+ credentialsKey := tokenSpec . buildKey ()
232
261
if runtime .GOOS == "windows" {
233
- credentialsKey = driverName + ":" + credType
234
262
ring , _ := keyring .Open (keyring.Config {
235
- WinCredPrefix : strings .ToUpper (sc . cfg . Host ),
236
- ServiceName : strings .ToUpper (sc . cfg . User ),
263
+ WinCredPrefix : strings .ToUpper (tokenSpec . host ),
264
+ ServiceName : strings .ToUpper (tokenSpec . user ),
237
265
})
238
266
item := keyring.Item {
239
267
Key : credentialsKey ,
240
- Data : []byte (token ),
268
+ Data : []byte (value ),
241
269
}
242
270
if err := ring .Set (item ); err != nil {
243
271
logger .Debugf ("Failed to write to Windows credential manager. Err: %v" , err )
244
272
}
245
273
} else if runtime .GOOS == "darwin" {
246
- credentialsKey = buildCredentialsKey (sc .cfg .Host , sc .cfg .User , credType )
247
274
ring , _ := keyring .Open (keyring.Config {
248
275
ServiceName : credentialsKey ,
249
276
})
250
- account := strings .ToUpper (sc . cfg . User )
277
+ account := strings .ToUpper (tokenSpec . user )
251
278
item := keyring.Item {
252
279
Key : account ,
253
- Data : []byte (token ),
280
+ Data : []byte (value ),
254
281
}
255
282
if err := ring .Set (item ); err != nil {
256
283
logger .Debugf ("Failed to write to keychain. Err: %v" , err )
@@ -259,26 +286,24 @@ func (ssm *keyringSecureStorageManager) setCredential(sc *snowflakeConn, credTyp
259
286
}
260
287
}
261
288
262
- func (ssm * keyringSecureStorageManager ) getCredential (sc * snowflakeConn , credType string ) {
263
- var credentialsKey string
289
+ func (ssm * keyringSecureStorageManager ) getCredential (tokenSpec * secureTokenSpec ) string {
264
290
cred := ""
291
+ credentialsKey := tokenSpec .buildKey ()
265
292
if runtime .GOOS == "windows" {
266
- credentialsKey = driverName + ":" + credType
267
293
ring , _ := keyring .Open (keyring.Config {
268
- WinCredPrefix : strings .ToUpper (sc . cfg . Host ),
269
- ServiceName : strings .ToUpper (sc . cfg . User ),
294
+ WinCredPrefix : strings .ToUpper (tokenSpec . host ),
295
+ ServiceName : strings .ToUpper (tokenSpec . user ),
270
296
})
271
297
i , err := ring .Get (credentialsKey )
272
298
if err != nil {
273
299
logger .Debugf ("Failed to read credentialsKey or could not find it in Windows Credential Manager. Error: %v" , err )
274
300
}
275
301
cred = string (i .Data )
276
302
} else if runtime .GOOS == "darwin" {
277
- credentialsKey = buildCredentialsKey (sc .cfg .Host , sc .cfg .User , credType )
278
303
ring , _ := keyring .Open (keyring.Config {
279
304
ServiceName : credentialsKey ,
280
305
})
281
- account := strings .ToUpper (sc . cfg . User )
306
+ account := strings .ToUpper (tokenSpec . user )
282
307
i , err := ring .Get (account )
283
308
if err != nil {
284
309
logger .Debugf ("Failed to find the item in keychain or item does not exist. Error: %v" , err )
@@ -290,59 +315,52 @@ func (ssm *keyringSecureStorageManager) getCredential(sc *snowflakeConn, credTyp
290
315
logger .Debug ("Successfully read token. Returning as string" )
291
316
}
292
317
}
293
-
294
- if credType == idToken {
295
- sc .cfg .IDToken = cred
296
- } else if credType == mfaToken {
297
- sc .cfg .MfaToken = cred
298
- } else {
299
- logger .Debugf ("Unrecognized type %v for local cached credential" , credType )
300
- }
318
+ return cred
301
319
}
302
320
303
- func (ssm * keyringSecureStorageManager ) deleteCredential (sc * snowflakeConn , credType string ) {
304
- credentialsKey := driverName + ":" + credType
321
+ func (ssm * keyringSecureStorageManager ) deleteCredential (tokenSpec * secureTokenSpec ) {
322
+ credentialsKey := tokenSpec . buildKey ()
305
323
if runtime .GOOS == "windows" {
306
324
ring , _ := keyring .Open (keyring.Config {
307
- WinCredPrefix : strings .ToUpper (sc . cfg . Host ),
308
- ServiceName : strings .ToUpper (sc . cfg . User ),
325
+ WinCredPrefix : strings .ToUpper (tokenSpec . host ),
326
+ ServiceName : strings .ToUpper (tokenSpec . user ),
309
327
})
310
- err := ring .Remove (credentialsKey )
328
+ err := ring .Remove (string ( credentialsKey ) )
311
329
if err != nil {
312
330
logger .Debugf ("Failed to delete credentialsKey in Windows Credential Manager. Error: %v" , err )
313
331
}
314
332
} else if runtime .GOOS == "darwin" {
315
- credentialsKey = buildCredentialsKey (sc .cfg .Host , sc .cfg .User , credType )
316
333
ring , _ := keyring .Open (keyring.Config {
317
334
ServiceName : credentialsKey ,
318
335
})
319
- account := strings .ToUpper (sc . cfg . User )
336
+ account := strings .ToUpper (tokenSpec . user )
320
337
err := ring .Remove (account )
321
338
if err != nil {
322
339
logger .Debugf ("Failed to delete credentialsKey in keychain. Error: %v" , err )
323
340
}
324
341
}
325
342
}
326
343
327
- func buildCredentialsKey (host , user , credType string ) string {
344
+ func buildCredentialsKey (host , user string , credType tokenType ) string {
328
345
host = strings .ToUpper (host )
329
346
user = strings .ToUpper (user )
330
- credType = strings .ToUpper (credType )
331
- return host + ":" + user + ":" + driverName + ":" + credType
347
+ credTypeStr : = strings .ToUpper (string ( credType ) )
348
+ return host + ":" + user + ":" + driverName + ":" + credTypeStr
332
349
}
333
350
334
351
type noopSecureStorageManager struct {
335
352
}
336
353
337
- func newNoopSecureStorageManager () secureStorageManager {
354
+ func newNoopSecureStorageManager () * noopSecureStorageManager {
338
355
return & noopSecureStorageManager {}
339
356
}
340
357
341
- func (ssm * noopSecureStorageManager ) setCredential (sc * snowflakeConn , credType , token string ) {
358
+ func (ssm * noopSecureStorageManager ) setCredential (_ * secureTokenSpec , _ string ) {
342
359
}
343
360
344
- func (ssm * noopSecureStorageManager ) getCredential (sc * snowflakeConn , credType string ) {
361
+ func (ssm * noopSecureStorageManager ) getCredential (_ * secureTokenSpec ) string {
362
+ return ""
345
363
}
346
364
347
- func (ssm * noopSecureStorageManager ) deleteCredential (sc * snowflakeConn , credType string ) { //TODO implement me
365
+ func (ssm * noopSecureStorageManager ) deleteCredential (_ * secureTokenSpec ) { //TODO implement me
348
366
}
0 commit comments