7
7
"errors"
8
8
"fmt"
9
9
"io/ioutil"
10
+ "os"
10
11
"regexp"
11
12
"strings"
12
13
"time"
@@ -21,11 +22,12 @@ type ConfigurationProvider interface {
21
22
UserOCID () (string , error )
22
23
KeyFingerprint () (string , error )
23
24
Region () (string , error )
25
+ SecurityTokenFile () (string , error )
24
26
}
25
27
26
28
// IsConfigurationProviderValid Tests all parts of the configuration provider do not return an error
27
29
func IsConfigurationProviderValid (conf ConfigurationProvider ) (ok bool , err error ) {
28
- baseFn := []func () (string , error ){conf .TenancyOCID , conf .UserOCID , conf . KeyFingerprint , conf .KeyID }
30
+ baseFn := []func () (string , error ){conf .TenancyOCID , conf .KeyFingerprint , conf .KeyID }
29
31
for _ , fn := range baseFn {
30
32
_ , err = fn ()
31
33
ok = err == nil
@@ -39,6 +41,20 @@ func IsConfigurationProviderValid(conf ConfigurationProvider) (ok bool, err erro
39
41
if err != nil {
40
42
return
41
43
}
44
+
45
+ // if using session token, user is not required
46
+ sFile , err := conf .SecurityTokenFile ()
47
+ if err == nil && sFile != "" {
48
+ return true , nil
49
+ }
50
+
51
+ // otherwise user ocid is required
52
+ _ , err = conf .UserOCID ()
53
+ ok = err == nil
54
+ if err != nil {
55
+ return
56
+ }
57
+
42
58
return true , nil
43
59
}
44
60
@@ -99,6 +115,10 @@ func (p rawConfigurationProvider) UserOCID() (string, error) {
99
115
return p .user , nil
100
116
}
101
117
118
+ func (p rawConfigurationProvider ) SecurityTokenFile () (string , error ) {
119
+ return "" , fmt .Errorf ("RawConfigurationProvider does not support SecurityTokenFile" )
120
+ }
121
+
102
122
func (p rawConfigurationProvider ) KeyFingerprint () (string , error ) {
103
123
if p .fingerprint == "" {
104
124
return "" , fmt .Errorf ("fingerprint can not be empty" )
@@ -150,8 +170,8 @@ func ConfigurationProviderFromFileWithProfile(configFilePath, profile, privateKe
150
170
}
151
171
152
172
type configFileInfo struct {
153
- UserOcid , Fingerprint , KeyFilePath , TenancyOcid , Region , Passphrase string
154
- PresentConfiguration byte
173
+ UserOcid , Fingerprint , KeyFilePath , TenancyOcid , Region , Passphrase , SecurityTokenFile string
174
+ PresentConfiguration byte
155
175
}
156
176
157
177
const (
@@ -161,6 +181,7 @@ const (
161
181
hasRegion
162
182
hasKeyFile
163
183
hasPassphrase
184
+ hasSecurityTokenFile
164
185
none
165
186
)
166
187
@@ -216,6 +237,9 @@ func parseConfigAtLine(start int, content []string) (info *configFileInfo, err e
216
237
case "tenancy" :
217
238
configurationPresent = configurationPresent | hasTenancy
218
239
info .TenancyOcid = value
240
+ case "security_token_file" :
241
+ configurationPresent = configurationPresent | hasSecurityTokenFile
242
+ info .SecurityTokenFile = value
219
243
case "region" :
220
244
configurationPresent = configurationPresent | hasRegion
221
245
info .Region = value
@@ -241,6 +265,23 @@ func openConfigFile(configFilePath string) (data []byte, err error) {
241
265
return
242
266
}
243
267
268
+ func readTokenFromFile (tokenFilePath string ) (string , error ) {
269
+ expandedPath , err := sdkutil .ExpandPath (tokenFilePath )
270
+ if err != nil {
271
+ err = fmt .Errorf ("can not read token file: %s due to: %s" , tokenFilePath , err .Error ())
272
+ return "" , err
273
+ }
274
+
275
+ data , err := ioutil .ReadFile (expandedPath )
276
+ if err != nil {
277
+ err = fmt .Errorf ("can not read token file: %s due to: %s" , tokenFilePath , err .Error ())
278
+ return "" , err
279
+ }
280
+
281
+ token := strings .Replace (string (data ), "\r \n " , "" , - 1 )
282
+ return strings .Replace (token , "\n " , "" , - 1 ), nil
283
+ }
284
+
244
285
func (p fileConfigurationProvider ) String () string {
245
286
return fmt .Sprintf ("Configuration provided by file: %s" , p .ConfigPath )
246
287
}
@@ -286,6 +327,18 @@ func (p fileConfigurationProvider) TenancyOCID() (value string, err error) {
286
327
return
287
328
}
288
329
330
+ func (p fileConfigurationProvider ) SecurityTokenFile () (value string , err error ) {
331
+ info , err := p .readAndParseConfigFile ()
332
+ if err != nil {
333
+ err = fmt .Errorf ("can not read security token configuration due to: %s" , err .Error ())
334
+ return
335
+ }
336
+
337
+ value , err = presentOrError (info .SecurityTokenFile , hasSecurityTokenFile ,
338
+ info .PresentConfiguration , "security_token_file" )
339
+ return
340
+ }
341
+
289
342
func (p fileConfigurationProvider ) UserOCID () (value string , err error ) {
290
343
info , err := p .readAndParseConfigFile ()
291
344
if err != nil {
@@ -312,11 +365,22 @@ func (p fileConfigurationProvider) ExpirationTime() time.Time {
312
365
return time .Now ().Add (24 * time .Hour )
313
366
}
314
367
315
- func (p fileConfigurationProvider ) KeyID () (keyID string , err error ) {
368
+ func (p fileConfigurationProvider ) KeyID () (string , error ) {
316
369
info , err := p .readAndParseConfigFile ()
317
370
if err != nil {
318
371
err = fmt .Errorf ("can not read tenancy configuration due to: %s" , err .Error ())
319
- return
372
+ return "" , err
373
+ }
374
+
375
+ // SecurityTokenFile providers return different format for KeyID
376
+ sFile , err := p .SecurityTokenFile ()
377
+ if sFile != "" && err == nil {
378
+ // open/read file, return "ST$" + value (minus newlines)
379
+ token , err := readTokenFromFile (sFile )
380
+ if err != nil {
381
+ return "" , err
382
+ }
383
+ return "ST$" + token , nil
320
384
}
321
385
322
386
return fmt .Sprintf ("%s/%s/%s" , info .TenancyOcid , info .UserOcid , info .Fingerprint ), nil
@@ -365,7 +429,11 @@ func (p fileConfigurationProvider) Region() (value string, err error) {
365
429
366
430
value , err = presentOrError (info .Region , hasRegion , info .PresentConfiguration , "region" )
367
431
if err != nil {
368
- return
432
+ // Attempt to read region from environment variable
433
+ value = os .Getenv ("OCI_REGION" )
434
+ if value == "" {
435
+ return
436
+ }
369
437
}
370
438
371
439
return canStringBeRegion (value )
@@ -379,3 +447,24 @@ func canStringBeRegion(stringRegion string) (region string, err error) {
379
447
}
380
448
return stringRegion , nil
381
449
}
450
+
451
+ func SessionTokenProviderFromFileWithProfile (configFilePath , profile , privateKeyPassword string ) (ConfigurationProvider , error ) {
452
+ if profile == "" {
453
+ profile = "DEFAULT"
454
+ }
455
+ provider , err := ConfigurationProviderFromFileWithProfile (configFilePath , profile , privateKeyPassword )
456
+ if err != nil {
457
+ return nil , err
458
+ }
459
+ // verify that the config specifies a security token file
460
+ _ , err = provider .SecurityTokenFile ()
461
+ if err != nil {
462
+ return nil , err
463
+ }
464
+ // read the session token file, verify it has contents
465
+ _ , err = provider .KeyID ()
466
+ if err != nil {
467
+ return nil , err
468
+ }
469
+ return provider , nil
470
+ }
0 commit comments