/
githubmirror
/
trivy
Обзор
Документация
Войти
/
githubmirror
/
trivy
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
pkg/flag/remote_flags.go
189 строк
5 KB
Teppei Fukuda
feat(flag): add schema validation for `--server` flag (#9270)
30 июл 2025, 10:04
Не верифицирован
30 июл 2025, 10:04
ed4640e
Код
Авторство
О чём код?
package flag import ( "net/http" "net/url" "strings" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/log" ) const ( DefaultTokenHeader = "Trivy-Token" ) var ( ServerTokenFlag = Flag[string]{ Name: "token", ConfigName: "server.token", Usage: "for authentication in client/server mode", } ServerTokenHeaderFlag = Flag[string]{ Name: "token-header", ConfigName: "server.token-header", Default: DefaultTokenHeader, Usage: "specify a header name for token in client/server mode", } ServerAddrFlag = Flag[string]{ Name: "server", ConfigName: "server.addr", Usage: "server address in client mode", } ServerCustomHeadersFlag = Flag[[]string]{ Name: "custom-headers", ConfigName: "server.custom-headers", Usage: "custom headers in client mode", } ServerListenFlag = Flag[string]{ Name: "listen", ConfigName: "server.listen", Default: "localhost:4954", Usage: "listen address in server mode", } ServerPathPrefixFlag = Flag[string]{ Name: "path-prefix", ConfigName: "server.path-prefix", Usage: "prefix for the server endpoint", Internal: true, // Internal use } ) // RemoteFlagGroup composes common printer flag structs // used for commands requiring reporting logic. type RemoteFlagGroup struct { // for client/server Token *Flag[string] TokenHeader *Flag[string] PathPrefix *Flag[string] // for client ServerAddr *Flag[string] CustomHeaders *Flag[[]string] // for server Listen *Flag[string] } type RemoteOptions struct { Token string TokenHeader string ServerAddr string Listen string CustomHeaders http.Header // Server endpoint: <baseURL>[<prefix>]/<package>.<Service>/<Method> (default prefix: /twirp) // e.g., http://localhost:4954/twirp/trivy.scanner.v1.Scanner/Scan PathPrefix string } func NewClientFlags() *RemoteFlagGroup { return &RemoteFlagGroup{ Token: ServerTokenFlag.Clone(), TokenHeader: ServerTokenHeaderFlag.Clone(), PathPrefix: ServerPathPrefixFlag.Clone(), ServerAddr: ServerAddrFlag.Clone(), CustomHeaders: ServerCustomHeadersFlag.Clone(), } } func NewServerFlags() *RemoteFlagGroup { return &RemoteFlagGroup{ Token: ServerTokenFlag.Clone(), TokenHeader: ServerTokenHeaderFlag.Clone(), PathPrefix: ServerPathPrefixFlag.Clone(), Listen: ServerListenFlag.Clone(), } } func (f *RemoteFlagGroup) Name() string { return "Client/Server" } func (f *RemoteFlagGroup) Flags() []Flagger { return []Flagger{ f.Token, f.TokenHeader, f.PathPrefix, f.ServerAddr, f.CustomHeaders, f.Listen, } } func (f *RemoteFlagGroup) ToOptions(opts *Options) error { serverAddr := f.ServerAddr.Value() // Validate server schema if err := validateServerSchema(serverAddr); err != nil { return err } customHeaders := splitCustomHeaders(f.CustomHeaders.Value()) listen := f.Listen.Value() token := f.Token.Value() tokenHeader := f.TokenHeader.Value() if serverAddr == "" && listen == "" { switch { case len(customHeaders) > 0: log.Warn(`"--custom-header" can be used only with "--server"`) case token != "": log.Warn(`"--token" can be used only with "--server"`) case tokenHeader != "" && tokenHeader != DefaultTokenHeader: log.Warn(`"--token-header" can be used only with "--server"`) } } if token == "" && tokenHeader != DefaultTokenHeader { log.Warn(`"--token-header" should be used with "--token"`) } if token != "" && tokenHeader != "" { customHeaders.Set(tokenHeader, token) } opts.RemoteOptions = RemoteOptions{ Token: token, TokenHeader: tokenHeader, PathPrefix: f.PathPrefix.Value(), ServerAddr: serverAddr, CustomHeaders: customHeaders, Listen: listen, } return nil } func splitCustomHeaders(headers []string) http.Header { result := make(http.Header) for _, header := range headers { // e.g. x-api-token:XXX s := strings.SplitN(header, ":", 2) if len(s) != 2 { continue } result.Set(s[0], s[1]) } return result } func validateServerSchema(serverAddr string) error { if serverAddr == "" { return nil } parsedURL, err := url.Parse(serverAddr) if err != nil { return xerrors.Errorf("invalid server address format: %w", err) } if parsedURL.Scheme == "" { return xerrors.Errorf("server address must include HTTP or HTTPS schema (e.g., http://localhost:4954 or https://localhost:4954)") } else if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { return xerrors.Errorf("server address must use HTTP or HTTPS schema, got '%s' (e.g., use http://localhost:4954 instead of %s)", parsedURL.Scheme, serverAddr) } return nil }