Skip to content

Commit

Permalink
fix(scannercli): Pass temporary robot account credentials to scannerc…
Browse files Browse the repository at this point in the history
…li (#50)

Pass Robot Account credentials generated by Harbor for each scan
request through to the scannercli command as --robot-username
and --robot-password flags.

This feature is enabled by setting the value of the
SCANNER_CLI_OVERRIDE_REGISTRY_CREDENTIALS to true.

It has to be enable explicitly as not every version of scannercli
accepts the --robot-username and --robot-password flags.

Resolves: #37

Co-authored-by: Simarpreet Singh <[email protected]>
Signed-off-by: Daniel Pacak <[email protected]>
  • Loading branch information
danielpacak and simar7 committed Jun 5, 2020
1 parent b1f6de2 commit 3331143
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 136 deletions.
16 changes: 14 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
name: build
on:
- push
- pull_request
push:
branches:
- master
paths-ignore:
- '*.md'
- 'docs/**'
- 'LICENSE'
- 'NOTICE'
pull_request:
paths-ignore:
- '*.md'
- 'docs/**'
- 'LICENSE'
- 'NOTICE'
jobs:
build:
name: Build
Expand Down
1 change: 1 addition & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ changelog:
exclude:
- '^docs'
- '^test'
- '^release'
dockers:
- image_templates:
- "docker.io/aquasec/harbor-scanner-aqua:{{ .Version }}"
Expand Down
4 changes: 4 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
harbor-scanner-aqua
Copyright 2019-2020 Aqua Security Software Ltd.

This product includes software developed by Aqua Security (https://aquasec.com).
80 changes: 44 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[![GitHub release][release-img]][release]
[![Build Actions][build-action-img]][build-action]
[![GitHub Build Action][build-action-img]][actions]
[![GitHub Release Action][release-action-img]][actions]
[![Codecov][codecov-img]][codecov]
[![Go Report Card][report-card-img]][report-card]
[![License][license-img]][license]
Expand Down Expand Up @@ -95,6 +96,8 @@ $ scannercli scan \
--password=$SCANNER_AQUA_PASSWORD \
--host=$SCANNER_AQUA_HOST \
--registry=$SCANNER_AQUA_REGISTRY \
--robot-username=$HARBOR_ROBOT_ACCOUNT_NAME \
--robot-password=$HARBOR_ROBOT_ACCOUNT_PASSWORD \
--no-verify=$SCANNER_CLI_NO_VERIFY \
--show-negligible=$SCANNER_CLI_SHOW_NEGLIGIBLE \
--show-will-not-fix=$SCANNER_CLI_SHOW_WILL_NOT_FIX \
Expand Down Expand Up @@ -345,47 +348,51 @@ it out based on the following instructions.
Configuration of the adapter is done via environment variables at startup.
| Name | Default | Description |
|---------------------------------------|----------|---------------------------------------------------------------------------|
| `SCANNER_LOG_LEVEL` | `info` | The log level of `trace`, `debug`, `info`, `warn`, `warning`, `error`, `fatal` or `panic`. The standard logger logs entries with that level or anything above it. |
| `SCANNER_API_ADDR` | `:8080` | Binding address for the API HTTP server |
| `SCANNER_API_TLS_CERTIFICATE` | | The absolute path to the x509 certificate file |
| `SCANNER_API_TLS_KEY` | | The absolute path to the x509 private key file |
| `SCANNER_API_READ_TIMEOUT` | `15s` | The maximum duration for reading the entire request, including the body |
| `SCANNER_API_WRITE_TIMEOUT` | `15s` | The maximum duration before timing out writes of the response |
| `SCANNER_API_IDLE_TIMEOUT` | `60s` | The maximum amount of time to wait for the next request when keep-alives are enabled |
| `SCANNER_AQUA_USERNAME` | N/A | Aqua management console username (required) |
| `SCANNER_AQUA_PASSWORD` | N/A | Aqua management console password (required) |
| `SCANNER_AQUA_HOST` | `http://csp-console-svc.aqua:8080` | Aqua management console address |
| `SCANNER_AQUA_REGISTRY` | `Harbor` | The name of the Harbor registry configured in Aqua management console |
| `SCANNER_AQUA_REPORTS_DIR` | `/var/lib/scanner/reports` | Directory to save temporary scan reports |
| `SCANNER_AQUA_USE_IMAGE_TAG` | `true` | The flag to determine whether the image tag or digest is used in the image reference passed to `scannercli` |
| `SCANNER_CLI_NO_VERIFY` | `false` | The flag passed to `scannercli` to skip verifying TLS certificates |
| `SCANNER_CLI_SHOW_NEGLIGIBLE` | `true` | The flag passed to `scannercli` to show negligible/unknown severity vulnerabilities |
| `SCANNER_CLI_SHOW_WILL_NOT_FIX` | `false` | The flag passed to `scannercli` to show vulnerabilities that will not be fixed |
| `SCANNER_CLI_HIDE_BASE` | `true` | The flag passed to `scannercli` to hide vulnerabilities in the base image |
| `SCANNER_STORE_REDIS_URL` | `redis://harbor-harbor-redis:6379` | Redis server URI for a redis store |
| `SCANNER_STORE_REDIS_NAMESPACE` | `harbor.scanner.aqua:store` | A namespace for keys in a redis store |
| `SCANNER_STORE_REDIS_POOL_MAX_ACTIVE` | `5` | The max number of connections allocated by the pool for a redis store |
| `SCANNER_STORE_REDIS_POOL_MAX_IDLE` | `5` | The max number of idle connections in the pool for a redis store |
| `SCANNER_STORE_REDIS_SCAN_JOB_TTL` | `1h` | The time to live for persisting scan jobs and associated scan reports |
| Name | Default | Description |
|---------------------------------------------|----------|---------------------------------------------------------------------------|
| `SCANNER_LOG_LEVEL` | `info` | The log level of `trace`, `debug`, `info`, `warn`, `warning`, `error`, `fatal` or `panic`. The standard logger logs entries with that level or anything above it. |
| `SCANNER_API_ADDR` | `:8080` | Binding address for the API HTTP server |
| `SCANNER_API_TLS_CERTIFICATE` | | The absolute path to the x509 certificate file |
| `SCANNER_API_TLS_KEY` | | The absolute path to the x509 private key file |
| `SCANNER_API_READ_TIMEOUT` | `15s` | The maximum duration for reading the entire request, including the body |
| `SCANNER_API_WRITE_TIMEOUT` | `15s` | The maximum duration before timing out writes of the response |
| `SCANNER_API_IDLE_TIMEOUT` | `60s` | The maximum amount of time to wait for the next request when keep-alives are enabled |
| `SCANNER_AQUA_USERNAME` | N/A | Aqua management console username (required) |
| `SCANNER_AQUA_PASSWORD` | N/A | Aqua management console password (required) |
| `SCANNER_AQUA_HOST` | `http://csp-console-svc.aqua:8080` | Aqua management console address |
| `SCANNER_AQUA_REGISTRY` | `Harbor` | The name of the Harbor registry configured in Aqua management console |
| `SCANNER_AQUA_REPORTS_DIR` | `/var/lib/scanner/reports` | Directory to save temporary scan reports |
| `SCANNER_AQUA_USE_IMAGE_TAG` | `true` | The flag to determine whether the image tag or digest is used in the image reference passed to `scannercli` |
| `SCANNER_CLI_NO_VERIFY` | `false` | The flag passed to `scannercli` to skip verifying TLS certificates |
| `SCANNER_CLI_SHOW_NEGLIGIBLE` | `true` | The flag passed to `scannercli` to show negligible/unknown severity vulnerabilities |
| `SCANNER_CLI_SHOW_WILL_NOT_FIX` | `false` | The flag passed to `scannercli` to show vulnerabilities that will not be fixed |
| `SCANNER_CLI_HIDE_BASE` | `true` | The flag passed to `scannercli` to hide vulnerabilities in the base image |
| `SCANNER_CLI_OVERRIDE_REGISTRY_CREDENTIALS` | `false` | The flag to enable passing `--robot-username` and `--robot-password` flags to the `scannercli` executable binary |
| `SCANNER_STORE_REDIS_URL` | `redis://harbor-harbor-redis:6379` | Redis server URI for a redis store |
| `SCANNER_STORE_REDIS_NAMESPACE` | `harbor.scanner.aqua:store` | A namespace for keys in a redis store |
| `SCANNER_STORE_REDIS_POOL_MAX_ACTIVE` | `5` | The max number of connections allocated by the pool for a redis store |
| `SCANNER_STORE_REDIS_POOL_MAX_IDLE` | `5` | The max number of idle connections in the pool for a redis store |
| `SCANNER_STORE_REDIS_SCAN_JOB_TTL` | `1h` | The time to live for persisting scan jobs and associated scan reports |
## Troubleshooting
### Error: failed getting image manifest: 412 Precondition Failed
Currently, there's a limitation of `scannercli` which does not accept Harbor robot account credentials passed by a
Harbor scan job to the adapter service. This effectively means that the Aqua CSP scanner is using the credentials
provided in Aqua CSP management console under the **Integrations** / **Image Registries** section. However, these
credentials do not have enough permissions to bypass the deployment security checker when it's enabled in the Harbor
project configuration. In other words, the deployment security checker prevents the Aqua CSP scanner from pulling
an image, which it needs to be able to do in order to scan it.
Currently, there's a limitation of `scannercli` in Aqua CSP version < **TBD** which does not accept Harbor robot account
credentials passed by a Harbor scan job to the adapter service. This effectively means that the Aqua CSP scanner is
using the credentials provided in Aqua CSP management console under the **Integrations** / **Image Registries** section.
However, these credentials do not have enough permissions to bypass the deployment security checker when it's enabled in
the Harbor project configuration. In other words, the deployment security checker prevents the Aqua CSP scanner from
pulling an image, which it needs to be able to do in order to scan it.
![](docs/images/harbor_deployment_security.png)
The only available solution to that problem is disabling deployment security checks in Harbor.
The available solution depends on the version of your Aqua CSP deployment. In `scannercli` version >= **TBD** we've
introduced new `--rebot-username` and `--robot-password` args to respect credentials provided by Harbor.
> We're working with the Harbor team on the [enhancement to robot accounts](https://github.com/goharbor/harbor/issues/11574).
- For Aqua CSP version < **TBD** you can only disable deployment security checks in the Harbor interface under the
project configuration.
- For Aqua CSP version >= **TBD** set the value of the `SCANNER_CLI_OVERRIDE_REGISTRY_CREDENTIALS` env to `true`.
## Contributing
Expand All @@ -396,10 +403,11 @@ requests.
This project is licensed under the [Apache 2.0](LICENSE).
[release-img]: https://img.shields.io/github/release/aquasecurity/harbor-scanner-aqua.svg
[release-img]: https://img.shields.io/github/release/aquasecurity/harbor-scanner-aqua.svg?logo=github
[release]: https://github.com/aquasecurity/harbor-scanner-aqua/releases
[build-action-img]: https://github.com/aquasecurity/harbor-scanner-aqua/workflows/build/badge.svg
[build-action]: https://github.com/aquasecurity/harbor-scanner-aqua/actions
[release-action-img]: https://github.com/aquasecurity/harbor-scanner-aqua/workflows/release/badge.svg
[actions]: https://github.com/aquasecurity/harbor-scanner-aqua/actions
[codecov-img]: https://codecov.io/gh/aquasecurity/harbor-scanner-aqua/branch/master/graph/badge.svg
[codecov]: https://codecov.io/gh/aquasecurity/harbor-scanner-aqua
[report-card-img]: https://goreportcard.com/badge/github.com/aquasecurity/harbor-scanner-aqua
Expand Down
55 changes: 28 additions & 27 deletions helm/harbor-scanner-aqua/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ Aqua CSP Scanner as a plug-in vulnerability scanner in the Harbor registry.

```
$ helm install harbor-scanner-aqua . \
--namespace harbor \
--set aqua.version=$AQUA_VERSION \
--set aqua.registry.server=registry.aquasec.com \
--set aqua.registry.username=$AQUA_REGISTRY_USERNAME \
--set aqua.registry.password=$AQUA_REGISTRY_PASSWORD \
--set scanner.aqua.username=$AQUA_CONSOLE_USERNAME \
--set scanner.aqua.password=$AQUA_CONSOLE_PASSWORD \
--set scanner.aqua.host=http://csp-console-svc.aqua:8080
--namespace harbor \
--set aqua.version=$AQUA_VERSION \
--set aqua.registry.server=registry.aquasec.com \
--set aqua.registry.username=$AQUA_REGISTRY_USERNAME \
--set aqua.registry.password=$AQUA_REGISTRY_PASSWORD \
--set scanner.aqua.username=$AQUA_CONSOLE_USERNAME \
--set scanner.aqua.password=$AQUA_CONSOLE_PASSWORD \
--set scanner.aqua.host=http://csp-console-svc.aqua:8080
```

### With TLS
Expand All @@ -24,26 +24,26 @@ $ helm install harbor-scanner-aqua . \
```
$ openssl genrsa -out tls.key 2048
$ openssl req -new -x509 \
-key tls.key \
-out tls.crt \
-days 365 \
-subj /CN=harbor-scanner-aqua.harbor
-key tls.key \
-out tls.crt \
-days 365 \
-subj /CN=harbor-scanner-aqua.harbor
```
2. Install the `harbor-scanner-aqua` chart:
```
$ helm install harbor-scanner-aqua . \
--namespace harbor \
--set service.port=8443 \
--set scanner.api.tlsEnabled=true \
--set scanner.api.tlsCertificate="`cat tls.crt`" \
--set scanner.api.tlsKey="`cat tls.key`" \
--set aqua.version=$AQUA_VERSION \
--set aqua.registry.server=registry.aquasec.com \
--set aqua.registry.username=$AQUA_REGISTRY_USERNAME \
--set aqua.registry.password=$AQUA_REGISTRY_PASSWORD \
--set scanner.aqua.username=$AQUA_CONSOLE_USERNAME \
--set scanner.aqua.password=$AQUA_CONSOLE_PASSWORD \
--set scanner.aqua.host=http://csp-console-svc.aqua:8080
--namespace harbor \
--set service.port=8443 \
--set scanner.api.tlsEnabled=true \
--set scanner.api.tlsCertificate="`cat tls.crt`" \
--set scanner.api.tlsKey="`cat tls.key`" \
--set aqua.version=$AQUA_VERSION \
--set aqua.registry.server=registry.aquasec.com \
--set aqua.registry.username=$AQUA_REGISTRY_USERNAME \
--set aqua.registry.password=$AQUA_REGISTRY_PASSWORD \
--set scanner.aqua.username=$AQUA_CONSOLE_USERNAME \
--set scanner.aqua.password=$AQUA_CONSOLE_PASSWORD \
--set scanner.aqua.host=http://csp-console-svc.aqua:8080
```

## Introduction
Expand Down Expand Up @@ -102,6 +102,7 @@ The following table lists the configurable parameters of the scanner adapter cha
| `scanner.aqua.scannerCLIShowNegligible` | The flag passed to `scannercli` to show negligible/unknown severity vulnerabilities | `true` |
| `scanner.aqua.scannerCLIShowWillNotFix` | The flag passed to `scannercli` to show vulnerabilities that will not be fixed | `false` |
| `scanner.aqua.scannerCLIHideBase` | The flag passed to `scannercli` to hide vulnerabilities in the base image | `true` |
| `scanner.aqua.scannerCLIOverrideRegistryCredentials` | The flag to enable passing `--robot-username` and `--robot-password` flags to the `scannercli` executable binary | `false` |
| `scanner.aqua.reportsDir` | Directory to save temporary scan reports | `/var/lib/scanner/reports` |
| `scanner.aqua.useImageTag` | The flag to determine whether the image tag or digest is used in the image reference passed to `scannercli` | `true` |
| `scanner.api.tlsEnabled` | The flag to enable or disable TLS for HTTP | `true` |
Expand All @@ -125,7 +126,7 @@ Specify each parameter using the `--set key=value[,key=value]` argument to `helm

```
$ helm install my-release . \
--namespace my-namespace \
--set scanner.aqua.username=$AQUA_CONSOLE_USERNAME \
--set scanner.aqua.password=$AQUA_CONSOLE_PASSWORD
--namespace my-namespace \
--set scanner.aqua.username=$AQUA_CONSOLE_USERNAME \
--set scanner.aqua.password=$AQUA_CONSOLE_PASSWORD
```
2 changes: 2 additions & 0 deletions helm/harbor-scanner-aqua/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ spec:
value: {{ .Values.scanner.aqua.reportsDir | quote }}
- name: "SCANNER_CLI_HIDE_BASE"
value: {{ .Values.scanner.aqua.scannerCLIHideBase | default true | quote }}
- name: "SCANNER_CLI_OVERRIDE_REGISTRY_CREDENTIALS"
value: {{ .Values.scanner.aqua.scannerCLIOverrideRegistryCredentials | default false | quote }}
- name: "SCANNER_AQUA_USE_IMAGE_TAG"
value: {{ .Values.scanner.aqua.useImageTag | quote }}
- name: "SCANNER_STORE_REDIS_URL"
Expand Down
3 changes: 3 additions & 0 deletions helm/harbor-scanner-aqua/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ scanner:
scannerCLIShowWillNotFix: false
## scannerCLIHideBase the flag passed to `scannercli` to hide vulnerabilities in the base image
scannerCLIHideBase: true
## scannerCLIOverrideRegistryCredentials the flag to enable passing `--robot-username` and `--robot-password`
## flags to the `scannercli` executable binary
scannerCLIOverrideRegistryCredentials: false
store:
redisURL: "redis://harbor-harbor-redis:6379"
redisNamespace: "harbor.scanner.aqua:store"
Expand Down
26 changes: 20 additions & 6 deletions pkg/aqua/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ type ImageRef struct {
Repository string
Tag string
Digest string
Auth RegistryAuth
}

type RegistryAuth struct {
Username string
Password string
}

func (ir *ImageRef) WithTag() string {
Expand Down Expand Up @@ -82,24 +88,32 @@ func (c *command) Scan(imageRef ImageRef) (report ScanReport, err error) {

log.WithFields(log.Fields{"exec": executable, "args": args}).Debug("Running scannercli")

if c.cfg.ScannerCLIOverrideRegistryCredentials {
args = append(args, fmt.Sprintf("--robot-username=%s", imageRef.Auth.Username),
fmt.Sprintf("--robot-password=%s", imageRef.Auth.Password))
}
args = append(args, fmt.Sprintf("--password=%s", c.cfg.Password), image)

cmd := exec.Command(executable, args...)

stdout, exitCode, err := c.ambassador.RunCmd(cmd)
if err != nil {
log.WithFields(log.Fields{
"image_ref": imageRef,
"exit_code": exitCode,
"std_out": string(stdout),
"image_ref_repository": imageRef.Repository,
"image_ref_tag": imageRef.Tag,
"image_ref_digest": imageRef.Digest,
"exit_code": exitCode,
"std_out": string(stdout),
}).Error("Error while running scannercli command")
return report, fmt.Errorf("running command: %v: %v", err, string(stdout))
}

log.WithFields(log.Fields{
"image_ref": imageRef,
"exit_code": exitCode,
"std_out": string(stdout),
"image_ref_repository": imageRef.Repository,
"image_ref_tag": imageRef.Tag,
"image_ref_digest": imageRef.Digest,
"exit_code": exitCode,
"std_out": string(stdout),
}).Trace("Running scannercli command finished")

err = json.NewDecoder(reportFile).Decode(&report)
Expand Down
Loading

0 comments on commit 3331143

Please sign in to comment.