Skip to content

Commit 24a4563

Browse files
authored
feat(server): add internal --path-prefix flag for client/server mode (#7321)
Signed-off-by: knqyf263 <[email protected]>
1 parent 3f0e7eb commit 24a4563

File tree

11 files changed

+130
-77
lines changed

11 files changed

+130
-77
lines changed

docs/docs/references/configuration/config-file.md

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ cache:
3333
# Same as '--cache-backend'
3434
backend: "fs"
3535

36-
# Same as '--clear-cache'
37-
clear: false
38-
3936
redis:
4037
# Same as '--redis-ca'
4138
ca: ""
@@ -112,9 +109,6 @@ db:
112109
# Same as '--skip-java-db-update'
113110
java-skip-update: false
114111

115-
# Same as '--light'
116-
light: false
117-
118112
# Same as '--no-progress'
119113
no-progress: false
120114

@@ -124,9 +118,6 @@ db:
124118
# Same as '--skip-db-update'
125119
skip-update: false
126120

127-
# Same as '--reset'
128-
reset: false
129-
130121
```
131122
## Image options
132123

@@ -411,9 +402,6 @@ misconfiguration:
411402
# Same as '--include-non-failures'
412403
include-non-failures: false
413404

414-
# Same as '--reset-checks-bundle'
415-
reset-checks-bundle: false
416-
417405
# Same as '--misconfig-scanners'
418406
scanners:
419407
- azure-arm
@@ -580,9 +568,6 @@ scan:
580568
# Same as '--skip-files'
581569
skip-files: []
582570

583-
# Same as '--slow'
584-
slow: false
585-
586571
```
587572
## Secret options
588573

integration/client_server_test.go

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type csArgs struct {
3232
Input string
3333
ClientToken string
3434
ClientTokenHeader string
35+
PathPrefix string
3536
ListAllPackages bool
3637
Target string
3738
secretConfig string
@@ -443,19 +444,24 @@ func TestClientServerWithCycloneDX(t *testing.T) {
443444
}
444445
}
445446

446-
func TestClientServerWithToken(t *testing.T) {
447+
func TestClientServerWithCustomOptions(t *testing.T) {
448+
token := "token"
449+
tokenHeader := "Trivy-Token"
450+
pathPrefix := "prefix"
451+
447452
tests := []struct {
448453
name string
449454
args csArgs
450455
golden string
451456
wantErr string
452457
}{
453458
{
454-
name: "alpine 3.9 with token",
459+
name: "alpine 3.9 with token and prefix",
455460
args: csArgs{
456461
Input: "testdata/fixtures/images/alpine-39.tar.gz",
457-
ClientToken: "token",
458-
ClientTokenHeader: "Trivy-Token",
462+
ClientToken: token,
463+
ClientTokenHeader: tokenHeader,
464+
PathPrefix: pathPrefix,
459465
},
460466
golden: "testdata/alpine-39.json.golden",
461467
},
@@ -464,26 +470,37 @@ func TestClientServerWithToken(t *testing.T) {
464470
args: csArgs{
465471
Input: "testdata/fixtures/images/distroless-base.tar.gz",
466472
ClientToken: "invalidtoken",
467-
ClientTokenHeader: "Trivy-Token",
473+
ClientTokenHeader: tokenHeader,
474+
PathPrefix: pathPrefix,
468475
},
469476
wantErr: "twirp error unauthenticated: invalid token",
470477
},
471478
{
472479
name: "invalid token header",
473480
args: csArgs{
474481
Input: "testdata/fixtures/images/distroless-base.tar.gz",
475-
ClientToken: "token",
482+
ClientToken: token,
476483
ClientTokenHeader: "Unknown-Header",
484+
PathPrefix: pathPrefix,
477485
},
478486
wantErr: "twirp error unauthenticated: invalid token",
479487
},
488+
{
489+
name: "wrong path prefix",
490+
args: csArgs{
491+
Input: "testdata/fixtures/images/distroless-base.tar.gz",
492+
ClientToken: token,
493+
ClientTokenHeader: tokenHeader,
494+
PathPrefix: "wrong",
495+
},
496+
wantErr: "HTTP status code 404",
497+
},
480498
}
481499

482-
serverToken := "token"
483-
serverTokenHeader := "Trivy-Token"
484500
addr, cacheDir := setup(t, setupOptions{
485-
token: serverToken,
486-
tokenHeader: serverTokenHeader,
501+
token: token,
502+
tokenHeader: tokenHeader,
503+
pathPrefix: pathPrefix,
487504
})
488505

489506
for _, tt := range tests {
@@ -539,6 +556,7 @@ func TestClientServerWithRedis(t *testing.T) {
539556
type setupOptions struct {
540557
token string
541558
tokenHeader string
559+
pathPrefix string
542560
cacheBackend string
543561
}
544562

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

558576
go func() {
559-
osArgs := setupServer(addr, options.token, options.tokenHeader, cacheDir, options.cacheBackend)
577+
osArgs := setupServer(addr, options.token, options.tokenHeader, options.pathPrefix, cacheDir, options.cacheBackend)
560578

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

572-
func setupServer(addr, token, tokenHeader, cacheDir, cacheBackend string) []string {
590+
func setupServer(addr, token, tokenHeader, pathPrefix, cacheDir, cacheBackend string) []string {
573591
osArgs := []string{
574592
"--cache-dir",
575593
cacheDir,
576594
"server",
577-
"--skip-update",
595+
"--skip-db-update",
578596
"--listen",
579597
addr,
580598
}
581599
if token != "" {
582-
osArgs = append(osArgs, []string{
583-
"--token",
584-
token,
585-
"--token-header",
586-
tokenHeader,
587-
}...)
600+
osArgs = append(osArgs, "--token", token, "--token-header", tokenHeader)
601+
}
602+
if pathPrefix != "" {
603+
osArgs = append(osArgs, "--path-prefix", pathPrefix)
588604
}
589605
if cacheBackend != "" {
590606
osArgs = append(osArgs, "--cache-backend", cacheBackend)
@@ -593,13 +609,13 @@ func setupServer(addr, token, tokenHeader, cacheDir, cacheBackend string) []stri
593609
}
594610

595611
func setupClient(t *testing.T, c csArgs, addr string, cacheDir string) []string {
612+
t.Helper()
596613
if c.Command == "" {
597614
c.Command = "image"
598615
}
599616
if c.RemoteAddrOption == "" {
600617
c.RemoteAddrOption = "--server"
601618
}
602-
t.Helper()
603619
osArgs := []string{
604620
"--cache-dir",
605621
cacheDir,
@@ -639,6 +655,9 @@ func setupClient(t *testing.T, c csArgs, addr string, cacheDir string) []string
639655
if c.ClientToken != "" {
640656
osArgs = append(osArgs, "--token", c.ClientToken, "--token-header", c.ClientTokenHeader)
641657
}
658+
if c.PathPrefix != "" {
659+
osArgs = append(osArgs, "--path-prefix", c.PathPrefix)
660+
}
642661
if c.Input != "" {
643662
osArgs = append(osArgs, "--input", c.Input)
644663
}

magefiles/docs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func writeFlags(group flag.FlagGroup, w *os.File) {
105105

106106
var lastParts []string
107107
for _, flg := range flags {
108-
if flg.GetConfigName() == "" {
108+
if flg.GetConfigName() == "" || flg.Hidden() {
109109
continue
110110
}
111111
// We need to split the config name on `.` to make the indentations needed in yaml.

pkg/cache/remote.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"crypto/tls"
66
"net/http"
77

8+
"github.com/twitchtv/twirp"
89
"golang.org/x/xerrors"
910

1011
"github.com/aquasecurity/trivy/pkg/fanal/types"
@@ -19,6 +20,7 @@ type RemoteOptions struct {
1920
ServerAddr string
2021
CustomHeaders http.Header
2122
Insecure bool
23+
PathPrefix string
2224
}
2325

2426
// RemoteCache implements remote cache
@@ -39,7 +41,12 @@ func NewRemoteCache(opts RemoteOptions) *RemoteCache {
3941
},
4042
},
4143
}
42-
c := rpcCache.NewCacheProtobufClient(opts.ServerAddr, httpClient)
44+
45+
var twirpOpts []twirp.ClientOption
46+
if opts.PathPrefix != "" {
47+
twirpOpts = append(twirpOpts, twirp.WithClientPathPrefix(opts.PathPrefix))
48+
}
49+
c := rpcCache.NewCacheProtobufClient(opts.ServerAddr, httpClient, twirpOpts...)
4350
return &RemoteCache{
4451
ctx: ctx,
4552
client: c,

pkg/commands/artifact/run.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -545,11 +545,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
545545
Target: target,
546546
CacheOptions: opts.CacheOpts(),
547547
RemoteCacheOptions: opts.RemoteCacheOpts(),
548-
ServerOption: client.ScannerOption{
549-
RemoteURL: opts.ServerAddr,
550-
CustomHeaders: opts.CustomHeaders,
551-
Insecure: opts.Insecure,
552-
},
548+
ServerOption: opts.ClientScannerOpts(),
553549
ArtifactOption: artifact.Option{
554550
DisabledAnalyzers: disabledAnalyzers(opts),
555551
DisabledHandlers: disabledHandlers,

pkg/commands/server/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
5050
m.Register()
5151

5252
server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader,
53-
opts.DBRepository, opts.RegistryOpts())
53+
opts.PathPrefix, opts.DBRepository, opts.RegistryOpts())
5454
return server.ListenAndServe(ctx, cacheClient, opts.SkipDBUpdate)
5555
}

pkg/flag/options.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/aquasecurity/trivy/pkg/log"
2424
"github.com/aquasecurity/trivy/pkg/plugin"
2525
"github.com/aquasecurity/trivy/pkg/result"
26+
"github.com/aquasecurity/trivy/pkg/rpc/client"
2627
"github.com/aquasecurity/trivy/pkg/types"
2728
"github.com/aquasecurity/trivy/pkg/version/app"
2829
)
@@ -56,15 +57,21 @@ type Flag[T FlagType] struct {
5657
// Usage explains how to use the flag.
5758
Usage string
5859

59-
// Persistent represents if the flag is persistent
60+
// Persistent represents if the flag is persistent.
6061
Persistent bool
6162

62-
// Deprecated represents if the flag is deprecated
63+
// Deprecated represents if the flag is deprecated.
64+
// It shows a warning message when the flag is used.
6365
Deprecated string
6466

65-
// Removed represents if the flag is removed and no longer works
67+
// Removed represents if the flag is removed and no longer works.
68+
// It shows an error message when the flag is used.
6669
Removed string
6770

71+
// Internal represents if the flag is for internal use only.
72+
// It is not shown in the usage message.
73+
Internal bool
74+
6875
// Aliases represents aliases
6976
Aliases []Alias
7077

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

218+
func (f *Flag[T]) Hidden() bool {
219+
return f.Deprecated != "" || f.Removed != "" || f.Internal
220+
}
221+
211222
func (f *Flag[T]) Value() (t T) {
212223
if f == nil {
213224
return t
@@ -249,7 +260,7 @@ func (f *Flag[T]) Add(cmd *cobra.Command) {
249260
flags.Float64P(f.Name, f.Shorthand, v, f.Usage)
250261
}
251262

252-
if f.Deprecated != "" || f.Removed != "" {
263+
if f.Hidden() {
253264
_ = flags.MarkHidden(f.Name)
254265
}
255266
}
@@ -313,6 +324,7 @@ type Flagger interface {
313324
GetConfigName() string
314325
GetDefaultValue() any
315326
GetAliases() []Alias
327+
Hidden() bool
316328

317329
Parse() error
318330
Add(cmd *cobra.Command)
@@ -480,6 +492,16 @@ func (o *Options) RemoteCacheOpts() cache.RemoteOptions {
480492
ServerAddr: o.ServerAddr,
481493
CustomHeaders: o.CustomHeaders,
482494
Insecure: o.Insecure,
495+
PathPrefix: o.PathPrefix,
496+
}
497+
}
498+
499+
func (o *Options) ClientScannerOpts() client.ScannerOption {
500+
return client.ScannerOption{
501+
RemoteURL: o.ServerAddr,
502+
CustomHeaders: o.CustomHeaders,
503+
Insecure: o.Insecure,
504+
PathPrefix: o.PathPrefix,
483505
}
484506
}
485507

0 commit comments

Comments
 (0)