github.com/adevinta/lava@v0.7.2/cmd/lava/internal/run/runflag.go (about) 1 // Copyright 2024 Adevinta 2 3 package run 4 5 import ( 6 "errors" 7 "fmt" 8 "io" 9 "log/slog" 10 "os" 11 "strings" 12 "time" 13 14 agentconfig "github.com/adevinta/vulcan-agent/config" 15 types "github.com/adevinta/vulcan-types" 16 17 "github.com/adevinta/lava/internal/assettypes" 18 "github.com/adevinta/lava/internal/config" 19 ) 20 21 // typeFlag represents the asset type provided with the -type flag. 22 type typeFlag types.AssetType 23 24 // Set parses the value provided with the -type flag. It returns error 25 // if it is not a know asset type. 26 func (typ *typeFlag) Set(s string) error { 27 if s == "" { 28 return errors.New("empty asset type") 29 } 30 31 at := types.AssetType(s) 32 if !at.IsValid() && !assettypes.IsValid(at) { 33 return fmt.Errorf("invalid asset type: %v", s) 34 } 35 *typ = typeFlag(at) 36 return nil 37 } 38 39 // String returns the string representation of a -type flag value. 40 func (typ typeFlag) String() string { 41 return types.AssetType(typ).String() 42 } 43 44 // varFlag represents the environment variables provided with the -var 45 // flag. 46 type varFlag map[string]string 47 48 // Set parses the values provided with the -var flag. The environment 49 // variable must follow the format "name[=value]". If there is no 50 // equal sign, the value of the variable is got from the environment. 51 func (envvar *varFlag) Set(s string) error { 52 if *envvar == nil { 53 *envvar = make(map[string]string) 54 } 55 56 if s == "" { 57 return errors.New("empty environment variable") 58 } 59 60 name, value, found := strings.Cut(s, "=") 61 if !found { 62 value = os.Getenv(name) 63 } 64 65 if name == "" { 66 return errors.New("empty envvar name") 67 } 68 69 (*envvar)[name] = value 70 return nil 71 } 72 73 // String returns the string representation of the provided 74 // environment variables. 75 func (envvar varFlag) String() string { 76 var vars []string 77 for k, v := range envvar { 78 vars = append(vars, fmt.Sprintf("%v=%v", k, v)) 79 } 80 return strings.Join(vars, ":") 81 } 82 83 // authFlag represents the container registry credentials provided 84 // with the -user flag. 85 type userFlag struct { 86 Username string 87 Password string 88 } 89 90 // osStdin is used to read the container registry password. It is used 91 // by tests. 92 var osStdin io.Reader = os.Stdin 93 94 // Set parses the values provided with the -user flag. The container 95 // registry credentials must follow the format 96 // "username[:[password]]". The username and password are split around 97 // the first instance of the colon. So the username cannot contain a 98 // colon. If there is no colon, the password is read from the standard 99 // input. 100 func (userinfo *userFlag) Set(s string) error { 101 if s == "" { 102 return errors.New("empty registry credentials") 103 } 104 105 username, password, found := strings.Cut(s, ":") 106 if !found { 107 b, err := io.ReadAll(osStdin) 108 if err != nil { 109 return fmt.Errorf("read password: %w", err) 110 } 111 password = string(b) 112 } 113 114 *userinfo = userFlag{ 115 Username: username, 116 Password: password, 117 } 118 return nil 119 } 120 121 // String returns the string representation of the provided container 122 // registry credentials. The password is masked. 123 func (userinfo userFlag) String() string { 124 return userinfo.Username + ":****" 125 } 126 127 func init() { 128 CmdRun.Flag.Var(&runType, "type", "target type") 129 CmdRun.Flag.DurationVar(&runTimeout, "timeout", 600*time.Second, "checktype timeout") 130 CmdRun.Flag.StringVar(&runOpt, "opt", "", "checktype options") 131 CmdRun.Flag.StringVar(&runOptfile, "optfile", "", "checktype options file") 132 CmdRun.Flag.Var(&runVar, "var", "checktype environment variable") 133 CmdRun.Flag.TextVar(&runPull, "pull", agentconfig.PullPolicyIfNotPresent, "container image pull policy") 134 CmdRun.Flag.StringVar(&runRegistry, "registry", "", "container registry") 135 CmdRun.Flag.Var(&runUser, "user", "container registry credentials") 136 CmdRun.Flag.TextVar(&runSeverity, "severity", config.SeverityHigh, "minimum severity required to report a finding") 137 CmdRun.Flag.StringVar(&runO, "o", "", "output file") 138 CmdRun.Flag.TextVar(&runFmt, "fmt", config.OutputFormatHuman, "output format") 139 CmdRun.Flag.StringVar(&runMetrics, "metrics", "", "metrics file") 140 CmdRun.Flag.TextVar(&runLog, "log", slog.LevelInfo, "log level") 141 }