github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/flag/remote_flags.go (about) 1 package flag 2 3 import ( 4 "net/http" 5 "strings" 6 7 "github.com/devseccon/trivy/pkg/log" 8 ) 9 10 const ( 11 DefaultTokenHeader = "Trivy-Token" 12 ) 13 14 var ( 15 ServerTokenFlag = Flag{ 16 Name: "token", 17 ConfigName: "server.token", 18 Default: "", 19 Usage: "for authentication in client/server mode", 20 } 21 ServerTokenHeaderFlag = Flag{ 22 Name: "token-header", 23 ConfigName: "server.token-header", 24 Default: DefaultTokenHeader, 25 Usage: "specify a header name for token in client/server mode", 26 } 27 ServerAddrFlag = Flag{ 28 Name: "server", 29 ConfigName: "server.addr", 30 Default: "", 31 Usage: "server address in client mode", 32 } 33 ServerCustomHeadersFlag = Flag{ 34 Name: "custom-headers", 35 ConfigName: "server.custom-headers", 36 Default: []string{}, 37 Usage: "custom headers in client mode", 38 } 39 ServerListenFlag = Flag{ 40 Name: "listen", 41 ConfigName: "server.listen", 42 Default: "localhost:4954", 43 Usage: "listen address in server mode", 44 } 45 ) 46 47 // RemoteFlagGroup composes common printer flag structs 48 // used for commands requiring reporting logic. 49 type RemoteFlagGroup struct { 50 // for client/server 51 Token *Flag 52 TokenHeader *Flag 53 54 // for client 55 ServerAddr *Flag 56 CustomHeaders *Flag 57 58 // for server 59 Listen *Flag 60 } 61 62 type RemoteOptions struct { 63 Token string 64 TokenHeader string 65 66 ServerAddr string 67 Listen string 68 CustomHeaders http.Header 69 } 70 71 func NewClientFlags() *RemoteFlagGroup { 72 return &RemoteFlagGroup{ 73 Token: &ServerTokenFlag, 74 TokenHeader: &ServerTokenHeaderFlag, 75 ServerAddr: &ServerAddrFlag, 76 CustomHeaders: &ServerCustomHeadersFlag, 77 } 78 } 79 80 func NewServerFlags() *RemoteFlagGroup { 81 return &RemoteFlagGroup{ 82 Token: &ServerTokenFlag, 83 TokenHeader: &ServerTokenHeaderFlag, 84 Listen: &ServerListenFlag, 85 } 86 } 87 88 func (f *RemoteFlagGroup) Name() string { 89 return "Client/Server" 90 } 91 92 func (f *RemoteFlagGroup) Flags() []*Flag { 93 return []*Flag{f.Token, f.TokenHeader, f.ServerAddr, f.CustomHeaders, f.Listen} 94 } 95 96 func (f *RemoteFlagGroup) ToOptions() RemoteOptions { 97 serverAddr := getString(f.ServerAddr) 98 customHeaders := splitCustomHeaders(getStringSlice(f.CustomHeaders)) 99 listen := getString(f.Listen) 100 token := getString(f.Token) 101 tokenHeader := getString(f.TokenHeader) 102 103 if serverAddr == "" && listen == "" { 104 switch { 105 case len(customHeaders) > 0: 106 log.Logger.Warn(`"--custom-header" can be used only with "--server"`) 107 case token != "": 108 log.Logger.Warn(`"--token" can be used only with "--server"`) 109 case tokenHeader != "" && tokenHeader != DefaultTokenHeader: 110 log.Logger.Warn(`"--token-header" can be used only with "--server"`) 111 } 112 } 113 114 if token == "" && tokenHeader != DefaultTokenHeader { 115 log.Logger.Warn(`"--token-header" should be used with "--token"`) 116 } 117 118 if token != "" && tokenHeader != "" { 119 customHeaders.Set(tokenHeader, token) 120 } 121 122 return RemoteOptions{ 123 Token: token, 124 TokenHeader: tokenHeader, 125 ServerAddr: serverAddr, 126 CustomHeaders: customHeaders, 127 Listen: listen, 128 } 129 } 130 131 func splitCustomHeaders(headers []string) http.Header { 132 result := make(http.Header) 133 for _, header := range headers { 134 // e.g. x-api-token:XXX 135 s := strings.SplitN(header, ":", 2) 136 if len(s) != 2 { 137 continue 138 } 139 result.Set(s[0], s[1]) 140 } 141 return result 142 }