@@ -19,7 +19,11 @@ import (
19
19
"go.k6.io/k6/cmd/state"
20
20
"go.k6.io/k6/errext"
21
21
"go.k6.io/k6/errext/exitcodes"
22
+ "go.k6.io/k6/ext"
22
23
"go.k6.io/k6/internal/log"
24
+ "go.k6.io/k6/secretsource"
25
+
26
+ _ "go.k6.io/k6/internal/secretsource" // import it to register internal secret sources
23
27
)
24
28
25
29
const waitLoggerCloseTimeout = time .Second * 5
@@ -162,6 +166,10 @@ func rootCmdPersistentFlagSet(gs *state.GlobalState) *pflag.FlagSet {
162
166
// `gs.DefaultFlags.<value>`, so that the `k6 --help` message is
163
167
// not messed up...
164
168
169
+ // TODO(@mstoykov): likely needs work - no env variables and such. No config.json.
170
+ flags .StringArrayVar (& gs .Flags .SecretSource , "secret-source" , gs .Flags .SecretSource ,
171
+ "setting secret sources for k6 file[=./path.fileformat]," )
172
+
165
173
flags .StringVar (& gs .Flags .LogOutput , "log-output" , gs .Flags .LogOutput ,
166
174
"change the output for k6 logs, possible values are stderr,stdout,none,loki[=host:port],file[=./path.fileformat]" )
167
175
flags .Lookup ("log-output" ).DefValue = gs .DefaultFlags .LogOutput
@@ -257,6 +265,22 @@ func (c *rootCommand) setupLoggers(stop <-chan struct{}) error {
257
265
c .globalState .Logger .Debug ("Logger format: TEXT" )
258
266
}
259
267
268
+ secretsources , err := createSecretSources (c .globalState )
269
+ if err != nil {
270
+ return err
271
+ }
272
+ // it is important that we add this hook first as hooks are executed in order of addition
273
+ // and this means no other hook will get secrets
274
+ var secretsHook logrus.Hook
275
+ c .globalState .SecretsManager , secretsHook , err = secretsource .NewManager (secretsources )
276
+ if err != nil {
277
+ return err
278
+ }
279
+ if len (secretsources ) != 0 {
280
+ // don't actually filter anything if there will be no secrets
281
+ c .globalState .Logger .AddHook (secretsHook )
282
+ }
283
+
260
284
cancel := func () {} // noop as default
261
285
if hook != nil {
262
286
ctx := context .Background ()
@@ -289,3 +313,71 @@ func (c *rootCommand) setLoggerHook(ctx context.Context, h log.AsyncHook) {
289
313
c .globalState .Logger .AddHook (h )
290
314
c .globalState .Logger .SetOutput (io .Discard ) // don't output to anywhere else
291
315
}
316
+
317
+ func createSecretSources (gs * state.GlobalState ) (map [string ]secretsource.Source , error ) {
318
+ baseParams := secretsource.Params {
319
+ Logger : gs .Logger ,
320
+ Environment : gs .Env ,
321
+ FS : gs .FS ,
322
+ Usage : gs .Usage ,
323
+ }
324
+
325
+ result := make (map [string ]secretsource.Source )
326
+ for _ , line := range gs .Flags .SecretSource {
327
+ t , config , ok := strings .Cut (line , "=" )
328
+ if ! ok {
329
+ return nil , fmt .Errorf ("couldn't parse secret source configuration %q" , line )
330
+ }
331
+ secretSources := ext .Get (ext .SecretSourceExtension )
332
+ found , ok := secretSources [t ]
333
+ if ! ok {
334
+ return nil , fmt .Errorf ("no secret source for type %q for configuration %q" , t , line )
335
+ }
336
+ c := found .Module .(secretsource.Constructor ) //nolint:forcetypeassert
337
+ params := baseParams
338
+ name , isDefault , config := extractNameAndDefault (config )
339
+ params .ConfigArgument = config
340
+
341
+ secretSource , err := c (params )
342
+ if err != nil {
343
+ return nil , err
344
+ }
345
+ _ , alreadRegistered := result [name ]
346
+ if alreadRegistered {
347
+ return nil , fmt .Errorf ("secret source for name %q already registered before configuration %q" , t , line )
348
+ }
349
+ result [name ] = secretSource
350
+ if isDefault {
351
+ if _ , ok := result ["default" ]; ok {
352
+ return nil , fmt .Errorf ("can't have two secret sources that are default ones, second one was %q" , config )
353
+ }
354
+ result ["default" ] = secretSource
355
+ }
356
+ }
357
+
358
+ if len (result ) == 1 {
359
+ for _ , l := range result {
360
+ result ["default" ] = l
361
+ }
362
+ }
363
+
364
+ return result , nil
365
+ }
366
+
367
+ func extractNameAndDefault (config string ) (name string , isDefault bool , remaining string ) {
368
+ list := strings .Split (config , "," )
369
+ remainingArray := make ([]string , 0 , len (list ))
370
+ for _ , kv := range list {
371
+ if kv == "default" {
372
+ isDefault = true
373
+ continue
374
+ }
375
+ k , v , _ := strings .Cut (kv , "=" )
376
+ if k == "name" {
377
+ name = v
378
+ continue
379
+ }
380
+ remainingArray = append (remainingArray , kv )
381
+ }
382
+ return name , isDefault , strings .Join (remainingArray , "," )
383
+ }
0 commit comments