Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): add internal --path-prefix flag for client/server mode #7321

Merged
merged 5 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions docs/docs/references/configuration/config-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ cache:
# Same as '--cache-backend'
backend: "fs"

# Same as '--clear-cache'
clear: false

redis:
# Same as '--redis-ca'
ca: ""
Expand Down Expand Up @@ -112,9 +109,6 @@ db:
# Same as '--skip-java-db-update'
java-skip-update: false

# Same as '--light'
light: false

# Same as '--no-progress'
no-progress: false

Expand All @@ -124,9 +118,6 @@ db:
# Same as '--skip-db-update'
skip-update: false

# Same as '--reset'
reset: false

```
## Image options

Expand Down Expand Up @@ -408,9 +399,6 @@ misconfiguration:
# Same as '--include-non-failures'
include-non-failures: false

# Same as '--reset-checks-bundle'
reset-checks-bundle: false

# Same as '--misconfig-scanners'
scanners:
- azure-arm
Expand Down Expand Up @@ -577,9 +565,6 @@ scan:
# Same as '--skip-files'
skip-files: []

# Same as '--slow'
slow: false

```
## Secret options

Expand Down
59 changes: 39 additions & 20 deletions integration/client_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type csArgs struct {
Input string
ClientToken string
ClientTokenHeader string
PathPrefix string
ListAllPackages bool
Target string
secretConfig string
Expand Down Expand Up @@ -443,19 +444,24 @@ func TestClientServerWithCycloneDX(t *testing.T) {
}
}

func TestClientServerWithToken(t *testing.T) {
func TestClientServerWithCustomOptions(t *testing.T) {
token := "token"
tokenHeader := "Trivy-Token"
pathPrefix := "prefix"

tests := []struct {
name string
args csArgs
golden string
wantErr string
}{
{
name: "alpine 3.9 with token",
name: "alpine 3.9 with token and prefix",
args: csArgs{
Input: "testdata/fixtures/images/alpine-39.tar.gz",
ClientToken: "token",
ClientTokenHeader: "Trivy-Token",
ClientToken: token,
ClientTokenHeader: tokenHeader,
PathPrefix: pathPrefix,
},
golden: "testdata/alpine-39.json.golden",
},
Expand All @@ -464,26 +470,37 @@ func TestClientServerWithToken(t *testing.T) {
args: csArgs{
Input: "testdata/fixtures/images/distroless-base.tar.gz",
ClientToken: "invalidtoken",
ClientTokenHeader: "Trivy-Token",
ClientTokenHeader: tokenHeader,
PathPrefix: pathPrefix,
},
wantErr: "twirp error unauthenticated: invalid token",
},
{
name: "invalid token header",
args: csArgs{
Input: "testdata/fixtures/images/distroless-base.tar.gz",
ClientToken: "token",
ClientToken: token,
ClientTokenHeader: "Unknown-Header",
PathPrefix: pathPrefix,
},
wantErr: "twirp error unauthenticated: invalid token",
},
{
name: "wrong path prefix",
args: csArgs{
Input: "testdata/fixtures/images/distroless-base.tar.gz",
ClientToken: token,
ClientTokenHeader: tokenHeader,
PathPrefix: "wrong",
},
wantErr: "HTTP status code 404",
},
}

serverToken := "token"
serverTokenHeader := "Trivy-Token"
addr, cacheDir := setup(t, setupOptions{
token: serverToken,
tokenHeader: serverTokenHeader,
token: token,
tokenHeader: tokenHeader,
pathPrefix: pathPrefix,
})

for _, tt := range tests {
Expand Down Expand Up @@ -539,6 +556,7 @@ func TestClientServerWithRedis(t *testing.T) {
type setupOptions struct {
token string
tokenHeader string
pathPrefix string
cacheBackend string
}

Expand All @@ -556,7 +574,7 @@ func setup(t *testing.T, options setupOptions) (string, string) {
addr := fmt.Sprintf("localhost:%d", port)

go func() {
osArgs := setupServer(addr, options.token, options.tokenHeader, cacheDir, options.cacheBackend)
osArgs := setupServer(addr, options.token, options.tokenHeader, options.pathPrefix, cacheDir, options.cacheBackend)

// Run Trivy server
require.NoError(t, execute(osArgs))
Expand All @@ -569,22 +587,20 @@ func setup(t *testing.T, options setupOptions) (string, string) {
return addr, cacheDir
}

func setupServer(addr, token, tokenHeader, cacheDir, cacheBackend string) []string {
func setupServer(addr, token, tokenHeader, pathPrefix, cacheDir, cacheBackend string) []string {
osArgs := []string{
"--cache-dir",
cacheDir,
"server",
"--skip-update",
"--skip-db-update",
"--listen",
addr,
}
if token != "" {
osArgs = append(osArgs, []string{
"--token",
token,
"--token-header",
tokenHeader,
}...)
osArgs = append(osArgs, "--token", token, "--token-header", tokenHeader)
}
if pathPrefix != "" {
osArgs = append(osArgs, "--path-prefix", pathPrefix)
}
if cacheBackend != "" {
osArgs = append(osArgs, "--cache-backend", cacheBackend)
Expand All @@ -593,13 +609,13 @@ func setupServer(addr, token, tokenHeader, cacheDir, cacheBackend string) []stri
}

func setupClient(t *testing.T, c csArgs, addr string, cacheDir string) []string {
t.Helper()
if c.Command == "" {
c.Command = "image"
}
if c.RemoteAddrOption == "" {
c.RemoteAddrOption = "--server"
}
t.Helper()
osArgs := []string{
"--cache-dir",
cacheDir,
Expand Down Expand Up @@ -639,6 +655,9 @@ func setupClient(t *testing.T, c csArgs, addr string, cacheDir string) []string
if c.ClientToken != "" {
osArgs = append(osArgs, "--token", c.ClientToken, "--token-header", c.ClientTokenHeader)
}
if c.PathPrefix != "" {
osArgs = append(osArgs, "--path-prefix", c.PathPrefix)
}
if c.Input != "" {
osArgs = append(osArgs, "--input", c.Input)
}
Expand Down
2 changes: 1 addition & 1 deletion magefiles/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func writeFlags(group flag.FlagGroup, w *os.File) {

var lastParts []string
for _, flg := range flags {
if flg.GetConfigName() == "" {
if flg.GetConfigName() == "" || flg.Hidden() {
continue
}
// We need to split the config name on `.` to make the indentations needed in yaml.
Expand Down
9 changes: 8 additions & 1 deletion pkg/cache/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/tls"
"net/http"

"github.com/twitchtv/twirp"
"golang.org/x/xerrors"

"github.com/aquasecurity/trivy/pkg/fanal/types"
Expand All @@ -19,6 +20,7 @@ type RemoteOptions struct {
ServerAddr string
CustomHeaders http.Header
Insecure bool
PathPrefix string
}

// RemoteCache implements remote cache
Expand All @@ -39,7 +41,12 @@ func NewRemoteCache(opts RemoteOptions) *RemoteCache {
},
},
}
c := rpcCache.NewCacheProtobufClient(opts.ServerAddr, httpClient)

var twirpOpts []twirp.ClientOption
if opts.PathPrefix != "" {
twirpOpts = append(twirpOpts, twirp.WithClientPathPrefix(opts.PathPrefix))
}
c := rpcCache.NewCacheProtobufClient(opts.ServerAddr, httpClient, twirpOpts...)
return &RemoteCache{
ctx: ctx,
client: c,
Expand Down
6 changes: 1 addition & 5 deletions pkg/commands/artifact/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
Target: target,
CacheOptions: opts.CacheOpts(),
RemoteCacheOptions: opts.RemoteCacheOpts(),
ServerOption: client.ScannerOption{
RemoteURL: opts.ServerAddr,
CustomHeaders: opts.CustomHeaders,
Insecure: opts.Insecure,
},
ServerOption: opts.ClientScannerOpts(),
ArtifactOption: artifact.Option{
DisabledAnalyzers: disabledAnalyzers(opts),
DisabledHandlers: disabledHandlers,
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/server/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
m.Register()

server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader,
opts.DBRepository, opts.RegistryOpts())
opts.PathPrefix, opts.DBRepository, opts.RegistryOpts())
return server.ListenAndServe(ctx, cacheClient, opts.SkipDBUpdate)
}
30 changes: 26 additions & 4 deletions pkg/flag/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/plugin"
"github.com/aquasecurity/trivy/pkg/result"
"github.com/aquasecurity/trivy/pkg/rpc/client"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/version/app"
)
Expand Down Expand Up @@ -56,15 +57,21 @@ type Flag[T FlagType] struct {
// Usage explains how to use the flag.
Usage string

// Persistent represents if the flag is persistent
// Persistent represents if the flag is persistent.
Persistent bool

// Deprecated represents if the flag is deprecated
// Deprecated represents if the flag is deprecated.
// It shows a warning message when the flag is used.
Deprecated string

// Removed represents if the flag is removed and no longer works
// Removed represents if the flag is removed and no longer works.
// It shows an error message when the flag is used.
Removed string

// Internal represents if the flag is for internal use only.
// It is not shown in the usage message.
Internal bool

// Aliases represents aliases
Aliases []Alias

Expand Down Expand Up @@ -208,6 +215,10 @@ func (f *Flag[T]) GetAliases() []Alias {
return f.Aliases
}

func (f *Flag[T]) Hidden() bool {
return f.Deprecated != "" || f.Removed != "" || f.Internal
}

func (f *Flag[T]) Value() (t T) {
if f == nil {
return t
Expand Down Expand Up @@ -249,7 +260,7 @@ func (f *Flag[T]) Add(cmd *cobra.Command) {
flags.Float64P(f.Name, f.Shorthand, v, f.Usage)
}

if f.Deprecated != "" || f.Removed != "" {
if f.Hidden() {
_ = flags.MarkHidden(f.Name)
}
}
Expand Down Expand Up @@ -313,6 +324,7 @@ type Flagger interface {
GetConfigName() string
GetDefaultValue() any
GetAliases() []Alias
Hidden() bool

Parse() error
Add(cmd *cobra.Command)
Expand Down Expand Up @@ -480,6 +492,16 @@ func (o *Options) RemoteCacheOpts() cache.RemoteOptions {
ServerAddr: o.ServerAddr,
CustomHeaders: o.CustomHeaders,
Insecure: o.Insecure,
PathPrefix: o.PathPrefix,
}
}

func (o *Options) ClientScannerOpts() client.ScannerOption {
return client.ScannerOption{
RemoteURL: o.ServerAddr,
CustomHeaders: o.CustomHeaders,
Insecure: o.Insecure,
PathPrefix: o.PathPrefix,
}
}

Expand Down
Loading