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  }