@@ -19,7 +19,11 @@ import (
1919 "go.k6.io/k6/cmd/state"
2020 "go.k6.io/k6/errext"
2121 "go.k6.io/k6/errext/exitcodes"
22+ "go.k6.io/k6/ext"
2223 "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
2327)
2428
2529const waitLoggerCloseTimeout = time .Second * 5
@@ -162,6 +166,10 @@ func rootCmdPersistentFlagSet(gs *state.GlobalState) *pflag.FlagSet {
162166 // `gs.DefaultFlags.<value>`, so that the `k6 --help` message is
163167 // not messed up...
164168
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+
165173 flags .StringVar (& gs .Flags .LogOutput , "log-output" , gs .Flags .LogOutput ,
166174 "change the output for k6 logs, possible values are stderr,stdout,none,loki[=host:port],file[=./path.fileformat]" )
167175 flags .Lookup ("log-output" ).DefValue = gs .DefaultFlags .LogOutput
@@ -257,6 +265,22 @@ func (c *rootCommand) setupLoggers(stop <-chan struct{}) error {
257265 c .globalState .Logger .Debug ("Logger format: TEXT" )
258266 }
259267
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+
260284 cancel := func () {} // noop as default
261285 if hook != nil {
262286 ctx := context .Background ()
@@ -289,3 +313,71 @@ func (c *rootCommand) setLoggerHook(ctx context.Context, h log.AsyncHook) {
289313 c .globalState .Logger .AddHook (h )
290314 c .globalState .Logger .SetOutput (io .Discard ) // don't output to anywhere else
291315}
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