mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-13 00:00:19 -08:00
feat(client): configure TLS InsecureSkipVerify for server connection (#1287)
Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
@@ -19,6 +19,10 @@ linters-settings:
|
||||
locale: US
|
||||
goimports:
|
||||
local-prefixes: github.com/aquasecurity
|
||||
gosec:
|
||||
excludes:
|
||||
- G204
|
||||
- G402
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
@@ -53,9 +57,6 @@ issues:
|
||||
- linters:
|
||||
- gosec
|
||||
text: "Deferring unsafe method"
|
||||
- linters:
|
||||
- gosec
|
||||
text: "G204: Subprocess launched with variable"
|
||||
- linters:
|
||||
- errcheck
|
||||
text: "Close` is not checked"
|
||||
|
||||
17
pkg/cache/remote.go
vendored
17
pkg/cache/remote.go
vendored
@@ -2,6 +2,7 @@ package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
@@ -19,13 +20,19 @@ type RemoteCache struct {
|
||||
client rpcCache.Cache
|
||||
}
|
||||
|
||||
// RemoteURL to hold remote host
|
||||
type RemoteURL string
|
||||
|
||||
// NewRemoteCache is the factory method for RemoteCache
|
||||
func NewRemoteCache(url RemoteURL, customHeaders http.Header) cache.ArtifactCache {
|
||||
func NewRemoteCache(url string, customHeaders http.Header, insecure bool) cache.ArtifactCache {
|
||||
ctx := client.WithCustomHeaders(context.Background(), customHeaders)
|
||||
c := rpcCache.NewCacheProtobufClient(string(url), &http.Client{})
|
||||
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: insecure,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
c := rpcCache.NewCacheProtobufClient(url, httpClient)
|
||||
return &RemoteCache{ctx: ctx, client: c}
|
||||
}
|
||||
|
||||
|
||||
52
pkg/cache/remote_test.go
vendored
52
pkg/cache/remote_test.go
vendored
@@ -135,7 +135,7 @@ func TestRemoteCache_PutArtifact(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := cache.NewRemoteCache(cache.RemoteURL(ts.URL), tt.args.customHeaders)
|
||||
c := cache.NewRemoteCache(ts.URL, tt.args.customHeaders, false)
|
||||
err := c.PutArtifact(tt.args.imageID, tt.args.imageInfo)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err, tt.name)
|
||||
@@ -196,7 +196,7 @@ func TestRemoteCache_PutBlob(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := cache.NewRemoteCache(cache.RemoteURL(ts.URL), tt.args.customHeaders)
|
||||
c := cache.NewRemoteCache(ts.URL, tt.args.customHeaders, false)
|
||||
err := c.PutBlob(tt.args.diffID, tt.args.layerInfo)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err, tt.name)
|
||||
@@ -274,7 +274,7 @@ func TestRemoteCache_MissingBlobs(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := cache.NewRemoteCache(cache.RemoteURL(ts.URL), tt.args.customHeaders)
|
||||
c := cache.NewRemoteCache(ts.URL, tt.args.customHeaders, false)
|
||||
gotMissingImage, gotMissingLayerIDs, err := c.MissingBlobs(tt.args.imageID, tt.args.layerIDs)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err, tt.name)
|
||||
@@ -289,3 +289,49 @@ func TestRemoteCache_MissingBlobs(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoteCache_PutArtifactInsecure(t *testing.T) {
|
||||
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
|
||||
defer ts.Close()
|
||||
|
||||
type args struct {
|
||||
imageID string
|
||||
imageInfo types.ArtifactInfo
|
||||
insecure bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
args: args{
|
||||
imageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
|
||||
imageInfo: types.ArtifactInfo{},
|
||||
insecure: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path",
|
||||
args: args{
|
||||
imageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
|
||||
imageInfo: types.ArtifactInfo{},
|
||||
insecure: false,
|
||||
},
|
||||
wantErr: "certificate signed by unknown authority",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := cache.NewRemoteCache(ts.URL, nil, tt.args.insecure)
|
||||
err := c.PutArtifact(tt.args.imageID, tt.args.imageInfo)
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err, tt.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,6 +309,7 @@ var (
|
||||
insecureFlag = cli.BoolFlag{
|
||||
Name: "insecure",
|
||||
Usage: "allow insecure server connections when using SSL",
|
||||
Value: false,
|
||||
EnvVars: []string{"TRIVY_INSECURE"},
|
||||
}
|
||||
|
||||
@@ -585,6 +586,7 @@ func NewClientCommand() *cli.Command {
|
||||
stringSliceFlag(configPolicy),
|
||||
&listAllPackages,
|
||||
&offlineScan,
|
||||
&insecureFlag,
|
||||
|
||||
// original flags
|
||||
&token,
|
||||
|
||||
@@ -18,14 +18,14 @@ import (
|
||||
)
|
||||
|
||||
func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders,
|
||||
url client.RemoteURL, dockerOpt types.DockerOption, artifactOption artifact.Option, configScannerOption config.ScannerOption) (
|
||||
url client.RemoteURL, insecure client.Insecure, dockerOpt types.DockerOption, artifactOption artifact.Option, configScannerOption config.ScannerOption) (
|
||||
scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteDockerSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
}
|
||||
|
||||
func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache,
|
||||
customHeaders client.CustomHeaders, url client.RemoteURL, artifactOption artifact.Option,
|
||||
customHeaders client.CustomHeaders, url client.RemoteURL, insecure client.Insecure, artifactOption artifact.Option,
|
||||
configScannerOption config.ScannerOption) (scanner.Scanner, error) {
|
||||
wire.Build(scanner.RemoteArchiveSet)
|
||||
return scanner.Scanner{}, nil
|
||||
|
||||
@@ -138,7 +138,7 @@ func disabledAnalyzers(opt Option) []analyzer.Type {
|
||||
}
|
||||
|
||||
func initializeScanner(ctx context.Context, opt Option) (scanner.Scanner, func(), error) {
|
||||
remoteCache := cache.NewRemoteCache(cache.RemoteURL(opt.RemoteAddr), opt.CustomHeaders)
|
||||
remoteCache := cache.NewRemoteCache(opt.RemoteAddr, opt.CustomHeaders, opt.Insecure)
|
||||
|
||||
// ScannerOptions is filled only when config scanning is enabled.
|
||||
var configScannerOptions config.ScannerOption
|
||||
@@ -168,7 +168,7 @@ func initializeScanner(ctx context.Context, opt Option) (scanner.Scanner, func()
|
||||
if opt.Input != "" {
|
||||
// Scan tar file
|
||||
s, err := initializeArchiveScanner(ctx, opt.Input, remoteCache, client.CustomHeaders(opt.CustomHeaders),
|
||||
client.RemoteURL(opt.RemoteAddr), artifactOpt, configScannerOptions)
|
||||
client.RemoteURL(opt.RemoteAddr), client.Insecure(opt.Insecure), artifactOpt, configScannerOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, xerrors.Errorf("unable to initialize the archive scanner: %w", err)
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func initializeScanner(ctx context.Context, opt Option) (scanner.Scanner, func()
|
||||
}
|
||||
|
||||
s, cleanup, err := initializeDockerScanner(ctx, opt.Target, remoteCache, client.CustomHeaders(opt.CustomHeaders),
|
||||
client.RemoteURL(opt.RemoteAddr), dockerOpt, artifactOpt, configScannerOptions)
|
||||
client.RemoteURL(opt.RemoteAddr), client.Insecure(opt.Insecure), dockerOpt, artifactOpt, configScannerOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, xerrors.Errorf("unable to initialize the docker scanner: %w", err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by Wire. DO NOT EDIT.
|
||||
|
||||
//go:generate go run github.com/google/wire/cmd/wire
|
||||
//go:generate wire
|
||||
//go:build !wireinject
|
||||
// +build !wireinject
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
|
||||
// Injectors from inject.go:
|
||||
|
||||
func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, dockerOpt types.DockerOption, artifactOption artifact.Option, configScannerOption config.ScannerOption) (scanner.Scanner, func(), error) {
|
||||
scannerScanner := client.NewProtobufClient(url)
|
||||
func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, insecure client.Insecure, dockerOpt types.DockerOption, artifactOption artifact.Option, configScannerOption config.ScannerOption) (scanner.Scanner, func(), error) {
|
||||
scannerScanner := client.NewProtobufClient(url, insecure)
|
||||
clientScanner := client.NewScanner(customHeaders, scannerScanner)
|
||||
typesImage, cleanup, err := image.NewDockerImage(ctx, imageName, dockerOpt)
|
||||
if err != nil {
|
||||
@@ -40,8 +40,8 @@ func initializeDockerScanner(ctx context.Context, imageName string, artifactCach
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, artifactOption artifact.Option, configScannerOption config.ScannerOption) (scanner.Scanner, error) {
|
||||
scannerScanner := client.NewProtobufClient(url)
|
||||
func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, insecure client.Insecure, artifactOption artifact.Option, configScannerOption config.ScannerOption) (scanner.Scanner, error) {
|
||||
scannerScanner := client.NewProtobufClient(url, insecure)
|
||||
clientScanner := client.NewScanner(customHeaders, scannerScanner)
|
||||
typesImage, err := image.NewArchiveImage(filePath)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,15 +2,15 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
|
||||
ftypes "github.com/aquasecurity/fanal/types"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
|
||||
"github.com/google/wire"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
ftypes "github.com/aquasecurity/fanal/types"
|
||||
r "github.com/aquasecurity/trivy/pkg/rpc"
|
||||
rpc "github.com/aquasecurity/trivy/rpc/scanner"
|
||||
)
|
||||
@@ -24,9 +24,20 @@ var SuperSet = wire.NewSet(
|
||||
// RemoteURL for RPC remote host
|
||||
type RemoteURL string
|
||||
|
||||
// Insecure for RPC remote host
|
||||
type Insecure bool
|
||||
|
||||
// NewProtobufClient is the factory method to return RPC scanner
|
||||
func NewProtobufClient(remoteURL RemoteURL) rpc.Scanner {
|
||||
return rpc.NewScannerProtobufClient(string(remoteURL), &http.Client{})
|
||||
func NewProtobufClient(remoteURL RemoteURL, insecure Insecure) rpc.Scanner {
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: bool(insecure),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return rpc.NewScannerProtobufClient(string(remoteURL), httpClient)
|
||||
}
|
||||
|
||||
// CustomHeaders for holding HTTP headers
|
||||
|
||||
@@ -3,6 +3,8 @@ package client
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
@@ -283,3 +285,48 @@ func TestScanner_Scan(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanner_ScanServerInsecure(t *testing.T) {
|
||||
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
|
||||
defer ts.Close()
|
||||
|
||||
type args struct {
|
||||
request *scanner.ScanRequest
|
||||
insecure bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
args: args{
|
||||
request: &scanner.ScanRequest{},
|
||||
insecure: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path",
|
||||
args: args{
|
||||
request: &scanner.ScanRequest{},
|
||||
insecure: false,
|
||||
},
|
||||
wantErr: "certificate signed by unknown authority",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
s := NewProtobufClient(RemoteURL(ts.URL), Insecure(tt.args.insecure))
|
||||
_, err := s.Scan(context.Background(), tt.args.request)
|
||||
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.wantErr)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user