Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
feat: Configure Trivy timeout (#191)
Browse files Browse the repository at this point in the history
Resolves: #186

Signed-off-by: Daniel Pacak <[email protected]>
  • Loading branch information
danielpacak authored Oct 1, 2021
1 parent de5045b commit 15a53a7
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 41 deletions.
8 changes: 6 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,17 @@
```
vagrant up
```
3. SSH into a running Vagrant machine.
If everything goes well Harbor will be accessible at http://localhost:8181 (admin/Harbor12345).

To SSH into a running Vagrant machine.
```
vagrant ssh
```
4. Change directory to `/vagrant` in the development machine, which is shared between host and guest.
The `/vagrant` directory in the development machine is shared between host and guest. This, for example, allows you
to rebuild a container image for testing.
```
vagrant@ubuntu-focal:~$ cd /vagrant
vagrant@ubuntu-focal:/vagrant$ make docker-build
```

## Build Binaries
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,11 @@ Configuration of the adapter is done via environment variables at startup.
| `SCANNER_TRIVY_VULN_TYPE` | `os,library` | Comma-separated list of vulnerability types. Possible values are `os` and `library`. |
| `SCANNER_TRIVY_SEVERITY` | `UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL` | Comma-separated list of vulnerabilities severities to be displayed |
| `SCANNER_TRIVY_IGNORE_UNFIXED` | `false` | The flag to display only fixed vulnerabilities |
| `SCANNER_TRIVY_IGNORE_POLICY` | `` | The path for the Trivy ignore policy OPA Rego file |
| `SCANNER_TRIVY_IGNORE_POLICY` | `` | The path for the Trivy ignore policy OPA Rego file |
| `SCANNER_TRIVY_SKIP_UPDATE` | `false` | The flag to enable or disable [Trivy DB][trivy-db] downloads from GitHub |
| `SCANNER_TRIVY_GITHUB_TOKEN` | N/A | The GitHub access token to download [Trivy DB][trivy-db] (see [GitHub rate limiting][gh-rate-limit]) |
| `SCANNER_TRIVY_INSECURE` | `false` | The flag to skip verifying registry certificate |
| `SCANNER_TRIVY_TIMEOUT` | `5m0s` | The duration to wait for scan completion |
| `SCANNER_STORE_REDIS_NAMESPACE` | `harbor.scanner.trivy:store` | The namespace for keys in the Redis store |
| `SCANNER_STORE_REDIS_SCAN_JOB_TTL` | `1h` | The time to live for persisting scan jobs and associated scan reports |
| `SCANNER_JOB_QUEUE_REDIS_NAMESPACE` | `harbor.scanner.trivy:job-queue` | The namespace for keys in the scan jobs queue backed by Redis |
Expand Down
2 changes: 1 addition & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Vagrant.configure("2") do |config|
vb.memory = "2096"
end

config.vm.provision "install-go", type: "shell", path: "vagrant/install-go.sh"
config.vm.provision "install-docker", type: "shell", path: "vagrant/install-docker.sh"
config.vm.provision "install-harbor", type: "shell", path: "vagrant/install-harbor.sh"
config.vm.provision "install-go", type: "shell", path: "vagrant/install-go.sh"

config.vm.network :forwarded_port, guest: 80, host: 8181
end
1 change: 1 addition & 0 deletions helm/harbor-scanner-trivy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ The following table lists the configurable parameters of the scanner adapter cha
| `scanner.trivy.ignorepolicy` | The OPA rego script used by Trivy to evaluate each vulnerability | ` ` |
| `scanner.trivy.severity` | Comma-separated list of vulnerabilities severities to be displayed | `UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL` |
| `scanner.trivy.ignoreUnfixed` | The flag to display only fixed vulnerabilities | `false` |
| `scanner.trivy.timeout` | The duration to wait for scan completion | `5m0s` |
| `scanner.trivy.skipUpdate` | The flag to enable or disable Trivy DB downloads from GitHub | `false` |
| `scanner.trivy.gitHubToken` | The GitHub access token to download Trivy DB | |
| `scanner.trivy.insecure` | The flag to skip verifying registry certificate | `false` |
Expand Down
2 changes: 2 additions & 0 deletions helm/harbor-scanner-trivy/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ spec:
value: {{ .Values.scanner.trivy.severity | default "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL" | quote }}
- name: "SCANNER_TRIVY_IGNORE_UNFIXED"
value: {{ .Values.scanner.trivy.ignoreUnfixed | default false | quote }}
- name: "SCANNER_TRIVY_TIMEOUT"
value: {{ .Values.scanner.trivy.timeout | quote }}
- name: "SCANNER_TRIVY_SKIP_UPDATE"
value: {{ .Values.scanner.trivy.skipUpdate | default false | quote }}
- name: "SCANNER_TRIVY_GITHUB_TOKEN"
Expand Down
2 changes: 2 additions & 0 deletions helm/harbor-scanner-trivy/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ scanner:
severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
## ignoreUnfixed the flag to display only fixed vulnerabilities
ignoreUnfixed: false
## timeout the duration to wait for scan completion
timeout: 5m0s
## skipUpdate the flag to enable or disable Trivy DB downloads from GitHub
##
## You might want to enable this flag in test or CI/CD environments to avoid GitHub rate limiting issues.
Expand Down
21 changes: 11 additions & 10 deletions pkg/etc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@ type Config struct {
}

type Trivy struct {
CacheDir string `env:"SCANNER_TRIVY_CACHE_DIR" envDefault:"/home/scanner/.cache/trivy"`
ReportsDir string `env:"SCANNER_TRIVY_REPORTS_DIR" envDefault:"/home/scanner/.cache/reports"`
DebugMode bool `env:"SCANNER_TRIVY_DEBUG_MODE" envDefault:"false"`
VulnType string `env:"SCANNER_TRIVY_VULN_TYPE" envDefault:"os,library"`
Severity string `env:"SCANNER_TRIVY_SEVERITY" envDefault:"UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"`
IgnoreUnfixed bool `env:"SCANNER_TRIVY_IGNORE_UNFIXED" envDefault:"false"`
IgnorePolicy string `env:"SCANNER_TRIVY_IGNORE_POLICY"`
SkipUpdate bool `env:"SCANNER_TRIVY_SKIP_UPDATE" envDefault:"false"`
GitHubToken string `env:"SCANNER_TRIVY_GITHUB_TOKEN"`
Insecure bool `env:"SCANNER_TRIVY_INSECURE" envDefault:"false"`
CacheDir string `env:"SCANNER_TRIVY_CACHE_DIR" envDefault:"/home/scanner/.cache/trivy"`
ReportsDir string `env:"SCANNER_TRIVY_REPORTS_DIR" envDefault:"/home/scanner/.cache/reports"`
DebugMode bool `env:"SCANNER_TRIVY_DEBUG_MODE" envDefault:"false"`
VulnType string `env:"SCANNER_TRIVY_VULN_TYPE" envDefault:"os,library"`
Severity string `env:"SCANNER_TRIVY_SEVERITY" envDefault:"UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"`
IgnoreUnfixed bool `env:"SCANNER_TRIVY_IGNORE_UNFIXED" envDefault:"false"`
IgnorePolicy string `env:"SCANNER_TRIVY_IGNORE_POLICY"`
SkipUpdate bool `env:"SCANNER_TRIVY_SKIP_UPDATE" envDefault:"false"`
GitHubToken string `env:"SCANNER_TRIVY_GITHUB_TOKEN"`
Insecure bool `env:"SCANNER_TRIVY_INSECURE" envDefault:"false"`
Timeout time.Duration `env:"SCANNER_TRIVY_TIMEOUT" envDefault:"5m0s"`
}

type API struct {
Expand Down
4 changes: 4 additions & 0 deletions pkg/etc/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func TestGetConfig(t *testing.T) {
Severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
Insecure: false,
GitHubToken: "",
Timeout: parseDuration(t, "5m0s"),
},
RedisPool: RedisPool{
URL: "redis://localhost:6379",
Expand Down Expand Up @@ -111,6 +112,7 @@ func TestGetConfig(t *testing.T) {
Severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
Insecure: false,
GitHubToken: "",
Timeout: parseDuration(t, "5m0s"),
},
RedisPool: RedisPool{
URL: "redis://localhost:6379",
Expand Down Expand Up @@ -153,6 +155,7 @@ func TestGetConfig(t *testing.T) {
"SCANNER_TRIVY_INSECURE": "true",
"SCANNER_TRIVY_SKIP_UPDATE": "true",
"SCANNER_TRIVY_GITHUB_TOKEN": "<GITHUB_TOKEN>",
"SCANNER_TRIVY_TIMEOUT": "15m30s",

"SCANNER_STORE_REDIS_NAMESPACE": "store.ns",
"SCANNER_STORE_REDIS_SCAN_JOB_TTL": "2h45m15s",
Expand Down Expand Up @@ -185,6 +188,7 @@ func TestGetConfig(t *testing.T) {
SkipUpdate: true,
Insecure: true,
GitHubToken: "<GITHUB_TOKEN>",
Timeout: parseDuration(t, "15m30s"),
},
RedisPool: RedisPool{
URL: "redis://harbor-harbor-redis:6379",
Expand Down
1 change: 1 addition & 0 deletions pkg/http/api/v1/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ func (h *requestHandler) GetMetadata(res http.ResponseWriter, _ *http.Request) {
"env.SCANNER_TRIVY_INSECURE": strconv.FormatBool(h.config.Trivy.Insecure),
"env.SCANNER_TRIVY_VULN_TYPE": h.config.Trivy.VulnType,
"env.SCANNER_TRIVY_SEVERITY": h.config.Trivy.Severity,
"env.SCANNER_TRIVY_TIMEOUT": h.config.Trivy.Timeout.String(),
}

vi, err := h.wrapper.GetVersion()
Expand Down
46 changes: 26 additions & 20 deletions pkg/http/api/v1/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,31 +428,32 @@ func TestRequestHandler_GetReady(t *testing.T) {
func TestRequestHandler_GetMetadata(t *testing.T) {
testCases := []struct {
name string
mockedBuildInfo etc.BuildInfo
mockedVersion trivy.VersionInfo
mockedConfig etc.Config
buildInfo etc.BuildInfo
version trivy.VersionInfo
config etc.Config
mockedError error
expectedHTTPCode int
expectedResp string
expectedError error
}{
{
name: "Should respond with a valid Metadata JSON and HTTP 200 OK",
mockedBuildInfo: etc.BuildInfo{Version: "0.1", Commit: "abc", Date: "2019-01-03T13:40"},
mockedVersion: trivy.VersionInfo{
name: "Should respond with a valid Metadata JSON and HTTP 200 OK",
buildInfo: etc.BuildInfo{Version: "0.1", Commit: "abc", Date: "2019-01-03T13:40"},
version: trivy.VersionInfo{
Version: "v0.5.2-17-g3c9af62",
VulnerabilityDB: &trivy.Metadata{
NextUpdate: time.Unix(1584507644, 0).UTC(),
UpdatedAt: time.Unix(1584517644, 0).UTC(),
},
},
mockedConfig: etc.Config{Trivy: etc.Trivy{
config: etc.Config{Trivy: etc.Trivy{
SkipUpdate: false,
IgnoreUnfixed: true,
DebugMode: true,
Insecure: true,
VulnType: "os,library",
Severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
Timeout: 5 * time.Minute,
}},
expectedHTTPCode: http.StatusOK,
expectedResp: `{
Expand Down Expand Up @@ -485,23 +486,25 @@ func TestRequestHandler_GetMetadata(t *testing.T) {
"env.SCANNER_TRIVY_DEBUG_MODE": "true",
"env.SCANNER_TRIVY_INSECURE": "true",
"env.SCANNER_TRIVY_VULN_TYPE": "os,library",
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
"env.SCANNER_TRIVY_TIMEOUT": "5m0s"
}
}`,
},
{
name: "Should respond with a valid Metadata JSON and HTTP 200 OK, when there's no trivy Metadata present",
mockedBuildInfo: etc.BuildInfo{Version: "0.1", Commit: "abc", Date: "2019-01-03T13:40"},
mockedVersion: trivy.VersionInfo{
name: "Should respond with a valid Metadata JSON and HTTP 200 OK, when there's no trivy Metadata present",
buildInfo: etc.BuildInfo{Version: "0.1", Commit: "abc", Date: "2019-01-03T13:40"},
version: trivy.VersionInfo{
Version: "v0.5.2-17-g3c9af62",
},
mockedConfig: etc.Config{Trivy: etc.Trivy{
config: etc.Config{Trivy: etc.Trivy{
SkipUpdate: false,
IgnoreUnfixed: true,
DebugMode: true,
Insecure: true,
VulnType: "os,library",
Severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
Timeout: 5 * time.Minute,
}},
expectedHTTPCode: http.StatusOK,
expectedResp: `{
Expand Down Expand Up @@ -532,18 +535,20 @@ func TestRequestHandler_GetMetadata(t *testing.T) {
"env.SCANNER_TRIVY_DEBUG_MODE": "true",
"env.SCANNER_TRIVY_INSECURE": "true",
"env.SCANNER_TRIVY_VULN_TYPE": "os,library",
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
"env.SCANNER_TRIVY_TIMEOUT": "5m0s"
}
}`,
},
{
name: "Should respond with a valid Metadata JSON and HTTP 200 OK when GetVersion fails",
mockedError: errors.New("get version failed"),
mockedBuildInfo: etc.BuildInfo{Version: "0.1", Commit: "abc", Date: "2019-01-03T13:40"},
mockedConfig: etc.Config{
name: "Should respond with a valid Metadata JSON and HTTP 200 OK when GetVersion fails",
mockedError: errors.New("get version failed"),
buildInfo: etc.BuildInfo{Version: "0.1", Commit: "abc", Date: "2019-01-03T13:40"},
config: etc.Config{
Trivy: etc.Trivy{
VulnType: "os,library",
Severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
Timeout: 5 * time.Minute,
},
},
expectedHTTPCode: http.StatusOK,
Expand Down Expand Up @@ -575,7 +580,8 @@ func TestRequestHandler_GetMetadata(t *testing.T) {
"env.SCANNER_TRIVY_DEBUG_MODE": "false",
"env.SCANNER_TRIVY_INSECURE": "false",
"env.SCANNER_TRIVY_VULN_TYPE": "os,library",
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
"env.SCANNER_TRIVY_TIMEOUT": "5m0s"
}
}`,
},
Expand All @@ -586,14 +592,14 @@ func TestRequestHandler_GetMetadata(t *testing.T) {
enqueuer := mock.NewEnqueuer()
store := mock.NewStore()
wrapper := trivy.NewMockWrapper()
wrapper.On("GetVersion").Return(tc.mockedVersion, tc.mockedError)
wrapper.On("GetVersion").Return(tc.version, tc.mockedError)

rr := httptest.NewRecorder()

r, err := http.NewRequest(http.MethodGet, "/api/v1/metadata", nil)
require.NoError(t, err, tc.name)

NewAPIHandler(tc.mockedBuildInfo, tc.mockedConfig, enqueuer, store, wrapper).ServeHTTP(rr, r)
NewAPIHandler(tc.buildInfo, tc.config, enqueuer, store, wrapper).ServeHTTP(rr, r)

rs := rr.Result()

Expand Down
4 changes: 3 additions & 1 deletion pkg/trivy/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ func (w *wrapper) prepareScanCmd(imageRef ImageRef, outputFile string) (*exec.Cm

cmd.Env = w.ambassador.Environ()

cmd.Env = append(cmd.Env, fmt.Sprintf("TRIVY_TIMEOUT=%s", w.config.Timeout.String()))

switch a := imageRef.Auth.(type) {
case NoAuth:
case BasicAuth:
Expand All @@ -144,7 +146,7 @@ func (w *wrapper) prepareScanCmd(imageRef ImageRef, outputFile string) (*exec.Cm
cmd.Env = append(cmd.Env,
fmt.Sprintf("TRIVY_REGISTRY_TOKEN=%s", a.Token))
default:
return nil, fmt.Errorf("invalid type %T", a)
return nil, fmt.Errorf("invalid auth type %T", a)
}

if imageRef.Insecure {
Expand Down
2 changes: 2 additions & 0 deletions pkg/trivy/wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func TestWrapper_Scan(t *testing.T) {
SkipUpdate: true,
GitHubToken: "<github_token>",
Insecure: true,
Timeout: 5 * time.Minute,
}

imageRef := ImageRef{
Expand Down Expand Up @@ -127,6 +128,7 @@ func TestWrapper_Scan(t *testing.T) {

expectedCmdEnvs := []string{
"HTTP_PROXY=http://someproxy:7777",
"TRIVY_TIMEOUT=5m0s",
"TRIVY_USERNAME=dave.loper",
"TRIVY_PASSWORD=s3cret",
"TRIVY_NON_SSL=true",
Expand Down
4 changes: 3 additions & 1 deletion test/integration/api/rest_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func TestRestApi(t *testing.T) {
Insecure: true,
VulnType: "os,library",
Severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
Timeout: 5 * time.Minute,
},
}, enqueuer, store, wrapper)

Expand Down Expand Up @@ -215,7 +216,8 @@ func TestRestApi(t *testing.T) {
"env.SCANNER_TRIVY_DEBUG_MODE": "true",
"env.SCANNER_TRIVY_INSECURE": "true",
"env.SCANNER_TRIVY_VULN_TYPE": "os,library",
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
"env.SCANNER_TRIVY_SEVERITY": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
"env.SCANNER_TRIVY_TIMEOUT": "5m0s"
}
}`, string(bodyBytes))
})
Expand Down
16 changes: 11 additions & 5 deletions vagrant/install-harbor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

HARBOR_VERSION="v2.3.2"

# Keep in sync with vagrant/harbor.yml.
HARBOR_HOSTNAME="harbor.dev.io"
HARBOR_USERNAME="admin"
HARBOR_PASSWORD="Harbor12345"

# Download the Harbor installer.
# The online installer downloads the Harbor images from DockerHub. For this reason, the installer is very small in size.
wget https://github.com/goharbor/harbor/releases/download/$HARBOR_VERSION/harbor-online-installer-$HARBOR_VERSION.tgz
Expand All @@ -17,12 +22,13 @@ gpg --verbose --keyserver hkps://keyserver.ubuntu.com --verify harbor-online-ins

tar -C /opt -xzf harbor-online-installer-$HARBOR_VERSION.tgz
rm harbor-online-installer-$HARBOR_VERSION.tgz
rm harbor-online-installer-$HARBOR_VERSION.tgz.asc

rm /opt/harbor/harbor.yml.tmpl
cp /vagrant/vagrant/harbor.yml /opt/harbor/harbor.yml

cat >> /etc/hosts <<EOF
127.0.0.1 harbor.dev.io
cat << EOF >> /etc/hosts
127.0.0.1 $HARBOR_HOSTNAME
EOF

cd /opt/harbor
Expand All @@ -31,8 +37,8 @@ cd /opt/harbor

sleep 30s

echo 'Harbor12345' | docker login --username=admin --password-stdin harbor.dev.io
echo "$HARBOR_PASSWORD" | docker login --username=$HARBOR_USERNAME --password-stdin $HARBOR_HOSTNAME

docker image pull nginx:1.16
docker image tag nginx:1.16 harbor.dev.io/library/nginx:1.16
docker image push harbor.dev.io/library/nginx:1.16
docker image tag nginx:1.16 $HARBOR_HOSTNAME/library/nginx:1.16
docker image push $HARBOR_HOSTNAME/library/nginx:1.16

0 comments on commit 15a53a7

Please sign in to comment.