Repository: aquasecurity/starboard (go)

Issue:
Wrong arguments for Trivy client
**What steps did you take and what happened:**

Deploy Starboard Operator with the Helm chart with the following values:
```
values:
    targetNamespaces: default
    trivy:
      mode: ClientServer
      serverURL: http://trivy:4954
      httpProxy: http://proxy:3128
      httpsProxy: http://proxy:3128
      noProxy: localhost,127.0.0.1,proxy,trivy
```

**What did you expect to happen:**
I expected the images to be successfully scanned with the Trivy Server and VulnerabilityReports resources to be created.

** Actual behavior **
The images are not scanned (no job created) and no VulnerabilityReport resource is created.

**Anything else you would like to add:**

Here is an extract of the logs of the Starbord Operator pod:
```
Incorrect Usage: flag provided but not defined: -quiet
```

It seems the `--quiet` flag is wrongly positioned after the `client` subcommand: https://github.com/aquasecurity/starboard/blob/v0.10.0/pkg/plugin/trivy/plugin.go#L492

Current (broken) command:
```
trivy client --quiet --format json --remote trivyServerURL
```

Expected command:
```
trivy --quiet client --format json --remote trivyServerURL
```

**Environment:**

- Starboard version (use `starboard version`): 0.10.0
- Kubernetes version (use `kubectl version`): 1.20.4
- OS (macOS 10.15, Windows 10, Ubuntu 19.10 etc): Ubuntu 16.04


Pull request description:
Fix Trivy arguments
Fix #504 

Patch:
diff --git a/docs/further-reading.md b/docs/further-reading.md
new file mode 100644
index 0000000..d0db99a
--- /dev/null
+++ b/docs/further-reading.md
@@ -0,0 +1,7 @@
+# Further Reading
+
+- [Discover Security Risks with Starboard Extension for Lens Kubernetes IDE](https://blog.aquasec.com/lens-kubernete-ide-starboard) | Aqua Blog | March 3, 2021
+- [Automating Configuration Auditing with Starboard Operator By Aqua](https://blog.aquasec.com/automating-configuration-auditing-starboard-operator) | Aqua Blog | February 4, 2021
+- [Starboard: Putting all the Kubernetes Security Pieces into One Place](https://thenewstack.io/starboard-putting-all-the-kubernetes-security-pieces-into-one-place/) | The New Stack | November 30, 2020
+- [Automating Kubernetes Security Reporting with Starboard Operator by Aqua](https://blog.aquasec.com/automate-kubernetes-security-reporting-starboard-operator) | Aqua Blog | November 2, 2020
+- [Starboard: The Kubernetes-Native Toolkit for Unifying Security](https://blog.aquasec.com/starboard-kubernetes-tools) | Aqua Blog | June 1, 2020
diff --git a/docs/integrations/config-checkers/index.md b/docs/integrations/config-checkers/index.md
new file mode 100644
index 0000000..3e02172
--- /dev/null
+++ b/docs/integrations/config-checkers/index.md
@@ -0,0 +1,1 @@
+# Configuration Checkers
diff --git a/docs/integrations/vulnerability-scanners/index.md b/docs/integrations/vulnerability-scanners/index.md
index 05d9f56..2596929 100644
--- a/docs/integrations/vulnerability-scanners/index.md
+++ b/docs/integrations/vulnerability-scanners/index.md
@@ -1,3 +1,3 @@
-# Overview
+# Vulnerability Scanners
 
 ![](./../../images/integration-vulnerability-scanners.png)
diff --git a/docs/operator/configuration.md b/docs/operator/configuration.md
index c4a89b3..35040df 100644
--- a/docs/operator/configuration.md
+++ b/docs/operator/configuration.md
@@ -1,4 +1,4 @@
-Configuration of the operator's pod is done via environment variables at startup.
+Configuration of the operator's Pod is done via environment variables at startup.
 
 | NAME                                        | DEFAULT                | DESCRIPTION |
 | ------------------------------------------- | ---------------------- | ----------- |
diff --git a/docs/operator/getting-started.md b/docs/operator/getting-started.md
index 04a6d6d..299bc14 100644
--- a/docs/operator/getting-started.md
+++ b/docs/operator/getting-started.md
@@ -1,20 +1,18 @@
 # Getting Started
 
-## Scanning Workloads
+## Workloads Scanning
 
-Assuming that you installed the operator in the `starboard-operator` namespace,
-and it's configured to discover Kubernetes workloads in the `default` namespace,
-let's create the `nginx` Deployment that we know is vulnerable:
+Assuming that you installed the operator in the `starboard-operator` namespace, and it's configured to discover
+Kubernetes workloads in the `default` namespace, let's create the `nginx` Deployment that we know is vulnerable:
 
 ```
 kubectl create deployment nginx --image nginx:1.16
 ```
 
-When the first pod controlled by the `nginx` Deployment is started, the operator
-immediately detects that and creates the Kubernetes job in the `starboard-operator`
-namespace to scan the `nginx` container's image (`nginx:1.16`) for
-vulnerabilities. It also creates another job to audit the pod's template for
-common configuration pitfalls such as running the `nginx` container as root:
+When the first ReplicaSet controlled by the `nginx` Deployment is created, the operator immediately detects that and
+creates the Kubernetes Job in the `starboard-operator` namespace to scan the `nginx:1.16` image for vulnerabilities.
+It also creates the Job to audit the Deployment's configuration for common pitfalls such as running the `nginx`
+container as root:
 
 ```console
 $ kubectl get job -n starboard-operator
@@ -23,55 +21,83 @@ scan-configauditreport-c4956cb9d     0/1           1s         1s
 scan-vulnerabilityreport-c4956cb9d   0/1           1s         1s
 ```
 
-If everything goes fine, the scan jobs are deleted, and the operator saves scan
-reports as custom resources in the `default` namespace, named after the Deployment's active ReplicaSet. For image vulnerability scans, the operator creates a report for each different container defined in the active ReplicaSet. In this example there is just one container image called `nginx`:
+If everything goes fine, the scan Jobs are deleted, and the operator saves scan reports as custom resources in the
+`default` namespace, named after the Deployment's active ReplicaSet. For image vulnerability scans, the operator creates
+a VulnerabilityReport for each different container defined in the active ReplicaSet. In this example there is just one
+container image called `nginx`:
 
 ```console
 $ kubectl get vulnerabilityreports -o wide
-NAME                                REPOSITORY      TAG    SCANNER   AGE     CRITICAL   HIGH   MEDIUM   LOW   UNKNOWN
-replicaset-nginx-7ff78f74b9-nginx   library/nginx   1.16   Trivy     9m57s   1          33     22       86    0
+NAME                                REPOSITORY      TAG    SCANNER   AGE   CRITICAL   HIGH   MEDIUM   LOW   UNKNOWN
+replicaset-nginx-7ff78f74b9-nginx   library/nginx   1.16   Trivy     12s   4          40     26       90    0
 ```
 
-Similarly, the operator creates a `configauditreport` resource holding the result
-of auditing the configuration of the active ReplicaSet controlled by the `nginx`
-Deployment:
+Similarly, the operator creates a ConfigAuditReport holding the result of auditing the configuration of the active
+ReplicaSet controlled by the `nginx` Deployment:
 
 ```console
 $ kubectl get configauditreports -o wide
-NAME                          SCANNER   PASS   DANGER   WARNING
-replicaset-nginx-7ff78f74b9   Polaris   9      0        8
+NAME                          SCANNER   AGE   DANGER   WARNING   PASS
+replicaset-nginx-7ff78f74b9   Polaris   33s   1        9         7
 ```
 
-Notice that scan reports generated by the operator are owned by corresponding
-Kubernetes workloads. In our example, `vulnerabilityreports` and `configauditreports` objects
-are owned by the active ReplicaSet of the `nginx` Deployment:
+Notice that scan reports generated by the operator are controlled by Kubernetes workloads. In our example,
+VulnerabilityReport and ConfigAuditReport objects are controlled by the active ReplicaSet of the `nginx` Deployment:
 
 ```console
 $ kubectl tree deploy nginx
 NAMESPACE  NAME                                                       READY  REASON  AGE
-default    Deployment/nginx                                           -              44m
-default    └─ReplicaSet/nginx-7ff78f74b9                              -              44m
-default      ├─ConfigAuditReport/replicaset-nginx-7ff78f74b9          -              44m
-default      ├─Pod/nginx-7ff78f74b9-l6w8p                             True           44m
-default      └─VulnerabilityReport/replicaset-nginx-7ff78f74b9-nginx  -              43m
+default    Deployment/nginx                                           -              104s
+default    └─ReplicaSet/nginx-7ff78f74b9                              -              104s
+default      ├─Pod/nginx-7ff78f74b9-6bkmn                             True           104s
+default      ├─ConfigAuditReport/replicaset-nginx-7ff78f74b9          -              102s
+default      └─VulnerabilityReport/replicaset-nginx-7ff78f74b9-nginx  -              90s
 ```
 
 !!! note
     The [tree] command is a kubectl plugin to browse Kubernetes object hierarchies as a tree.
 
+Moving forward, let's update the container image of the `nginx` Deployment from `nginx:1.16` to `nginx:1.17`. This will
+trigger a rolling update of the Deployment and eventually create another ReplicaSet.
+
+```console
+kubectl set image deployment nginx nginx=nginx:1.17
+```
+
+Even this time the operator will pick up changes and rescan our Deployment with updated configuration:
+
+```console
+kubectl tree deploy nginx
+NAMESPACE  NAME                                                       READY  REASON  AGE
+default    Deployment/nginx                                           -              6m36s
+default    ├─ReplicaSet/nginx-549f5fcb58                              -              2m47s
+default    │ ├─Pod/nginx-549f5fcb58-l8dhc                             True           2m47s
+default    │ ├─ConfigAuditReport/replicaset-nginx-549f5fcb58          -              2m45s
+default    │ └─VulnerabilityReport/replicaset-nginx-549f5fcb58-nginx  -              2m37s
+default    └─ReplicaSet/nginx-7ff78f74b9                              -              6m36s
+default      ├─ConfigAuditReport/replicaset-nginx-7ff78f74b9          -              6m34s
+default      └─VulnerabilityReport/replicaset-nginx-7ff78f74b9-nginx  -              6m22s
+```
+
+By following this guide you could realize that the operator knows how to attach VulnerabilityReport and
+ConfigAuditReport objects to build-in Kubernetes objects so that looking them up is easy. What's more, in this
+approach where a custom resource inherits a life cycle of the built-in resource we could leverage Kubernetes garbage
+collection. For example, when the previous ReplicaSet named `nginx-7ff78f74b9` is deleted the VulnerabilityReport named
+`replicaset-nginx-7ff78f74b9-nginx` as well as the ConfigAuditReport named `replicaset-nginx-7ff78f74b9` are
+automatically garbage collected.
+
 !!! tip
-    You can get and describe `vulnerabilityreports` and `configauditreports` as
-    built-in Kubernetes objects:
+    You can get and describe `vulnerabilityreports` and `configauditreports` as built-in Kubernetes objects:
     ```
-    kubectl get vulnerabilityreports replicaset-nginx-7ff78f74b9-nginx -o json
-    kubectl describe configauditreports replicaset-nginx-7ff78f74b9
+    kubectl get vulnerabilityreport replicaset-nginx-7ff78f74b9-nginx -o json
+    kubectl describe configauditreport replicaset-nginx-7ff78f74b9
     ```
 
-## Scanning Nodes
+## Infrastructure Scanning
 
-The operator discovers also Kubernetes nodes and runs CIS Kubernetes Benchmark checks on each of them.
-The results are stored as `ciskubebenchreports` objects. In other words, for a cluster with 3 nodes the operator will
-eventually create 3 benchmark reports:
+The operator discovers also Kubernetes nodes and runs CIS Kubernetes Benchmark checks on each of them. The results are
+stored as CISKubeBenchReport objects. In other words, for a cluster with 3 nodes the operator will eventually create
+3 benchmark reports:
 
 ```console
 $ kubectl get node
@@ -89,4 +115,26 @@ kind-worker          kube-bench   9s    2      27     0      18
 kind-worker2         kube-bench   9s    2      27     0      18
 ```
 
+Notice that each CISKubeBenchReport is named after a node and is controlled by that node to inherit its life cycle:
+
+```console
+$ kubectl tree node kind-control-plane -A
+NAMESPACE        NAME                                              READY  REASON        AGE
+                 Node/kind-control-plane                           True   KubeletReady  48m
+                 ├─CISKubeBenchReport/kind-control-plane           -                    44m
+                 ├─CSINode/kind-control-plane                      -                    48m
+kube-node-lease  ├─Lease/kind-control-plane                        -                    48m
+kube-system      ├─Pod/etcd-kind-control-plane                     True                 48m
+kube-system      ├─Pod/kube-apiserver-kind-control-plane           True                 48m
+kube-system      ├─Pod/kube-controller-manager-kind-control-plane  True                 48m
+kube-system      └─Pod/kube-scheduler-kind-control-plane           True                 48m
+```
+
+## What's Next?
+
+- Find out how the operator scans workloads that use container images from [private registries](./../integrations/private-registries.md).
+- By default, the operator uses Trivy as [vulnerability scanner](./../integrations/vulnerability-scanners/index.md)
+  and Polaris as [configuration checker](./../integrations/config-checkers/index.md), but you can choose other tools that
+  are integrated with Starboard or even implement you own plugins.
+
 [tree]: https://github.com/ahmetb/kubectl-tree
diff --git a/docs/operator/index.md b/docs/operator/index.md
index 2979266..1a3c1d3 100644
--- a/docs/operator/index.md
+++ b/docs/operator/index.md
@@ -1,4 +1,6 @@
-# Overview
+# Starboard Operator
+
+## Overview
 
 This operator automatically updates security report resources in response to workload and other changes on a Kubernetes
 cluster - for example, initiating a vulnerability scan and configuration audit when a new Pod is started.
@@ -13,7 +15,7 @@ for each of them.
 
 <figure>
   <img src="../images/operator/starboard-operator-infrastructure.png" />
-  <figcaption>Infrastructure reconciler discovers K8s nodes, manage scan jobs, and create CISKubeBenchReport objects.</figcaption>
+  <figcaption>Infrastructure reconciler discovers K8s nodes, manages scan jobs, and creates CISKubeBenchReport objects.</figcaption>
 </figure>
 
 In other words, the desired state for the controllers managed by this operator is that for each workload or node there
@@ -32,7 +34,7 @@ with new plugin's configuration.
 
 <figure>
   <img src="../images/operator/starboard-operator-config.png" />
-  <figurecaption>Plugins' configuration reconciler deletes ConfigAuditReports whenever configuration changes.</figurecaption>
+  <figurecaption>Plugin configuration reconciler deletes ConfigAuditReports whenever the configuration changes.</figurecaption>
 </figure>
 
 !!! warning
@@ -40,6 +42,10 @@ with new plugin's configuration.
     resources. We plan to support [kubehunterreports]. We also plan to implement rescan on configurable schedule, for
     example every 24 hours.
 
+## What's Next?
+
+- Install the operator and follow the [getting started](./getting-started.md) guide.
+
 [vulnerabilityreports]: ./../crds.md#vulnerabilityreport
 [configauditreports]: ./../crds.md#configauditreport
 [ciskubebenchreports]: ./../crds.md#ciskubebenchreport
diff --git a/mkdocs.yml b/mkdocs.yml
index adfa773..ec0c8c0 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -31,12 +31,16 @@ nav:
           - Overview: integrations/vulnerability-scanners/index.md
           - Trivy: integrations/vulnerability-scanners/trivy.md
           - Aqua Enterprise: integrations/vulnerability-scanners/aqua-enterprise.md
+      - Configuration Checkers:
+          - Overview: integrations/config-checkers/index.md
+          - Conftest: integrations/config-checkers/conftest.md
       - Private Registries: integrations/private-registries.md
       - Managed Registries: integrations/managed-registries.md
       - Octant Plugin: integrations/octant.md
       - Lens Extension: integrations/lens.md
   - Custom Resource Definitions: crds.md
   - Frequently Asked Questions: faq.md
+  - Further Reading: further-reading.md
 
 theme:
   name: material
diff --git a/pkg/plugin/trivy/plugin.go b/pkg/plugin/trivy/plugin.go
index c40fc5f..68e64b5 100644
--- a/pkg/plugin/trivy/plugin.go
+++ b/pkg/plugin/trivy/plugin.go
@@ -488,8 +488,8 @@ func (s *scanner) getPodSpecForClientServerMode(spec corev1.PodSpec, credentials
 				"trivy",
 			},
 			Args: []string{
-				"client",
 				"--quiet",
+				"client",
 				"--format",
 				"json",
 				"--remote",


Test patch:
diff --git a/docs/integrations/config-checkers/conftest.md b/docs/integrations/config-checkers/conftest.md
new file mode 100644
index 0000000..d282890
--- /dev/null
+++ b/docs/integrations/config-checkers/conftest.md
@@ -0,0 +1,121 @@
+# Conftest
+
+[Conftest] helps you write tests against structured configuration data. Using Conftest you can write tests for your
+Kubernetes configuration. Conftest uses the Rego language from [Open Policy Agent][OPA] for writing the assertions.
+
+Here's a simple policy that checks whether a given container runs as root:
+
+```opa
+package main
+
+deny[res] {
+  input.kind == "Deployment"
+  not input.spec.template.spec.securityContext.runAsNonRoot
+
+  msg := "Containers must not run as root"
+  
+  res := {
+    "msg": msg,
+    "title": "Runs as root user"
+  }
+}
+```
+
+To integrate Conftest scanner change the value of the `configAuditReports.scanner` property to `Conftest`:
+
+```
+kubectl patch cm starboard -n <starboard_namespace> \
+  --type merge \
+  -p "$(cat <<EOF
+{
+  "data": {
+    "configAuditReports.scanner": "Conftest"
+  }
+}
+EOF
+)"
+```
+
+!!! warning
+    Starboard does not ship with any default policies that can be used with Conftest plugin, therefore you have to add
+    them manually.
+
+In the following example, we'll use OPA polices provided by the [AppShield] project.
+
+Start by cloning the AppShield repository and changing the current directory to the cloned repository:
+
+```
+git clone https://github.com/aquasecurity/appshield
+cd appshield
+```
+
+Most of the Kubernetes policies defined by the AppShield project refer to OPA libraries called [kubernetes.rego]
+and [utils.rego]. You must add such libraries to the `starboard-conftest-config` ConfigMap along with the actual
+policies.
+
+As an example, let's create the `starboard-conftest-config` ConfigMap with [file_system_not_read_only.rego] and
+[uses_image_tag_latest.rego] policies. Those two are very common checks performed by many other tools:
+
+```
+kubectl create configmap starboard-conftest-config -n <starboard_namespace> \
+--from-file=conftest.policy.kubernetes.rego=kubernetes/lib/kubernetes.rego \
+--from-file=conftest.policy.utils.rego=kubernetes/lib/utils.rego \
+--from-file=conftest.policy.file_system_not_read_only.rego=kubernetes/policies/general/file_system_not_read_only.rego \
+--from-file=conftest.policy.uses_image_tag_latest.rego=kubernetes/policies/general/uses_image_tag_latest.rego
+```
+
+To test this setup out with Starboard CLI you can create the `nginx` Deployment with the latest `nginx` image and check
+its configuration:
+
+```
+kubectl create deployment nginx --image nginx
+kubectl starboard scan configauditreports deployment/nginx
+```
+
+Finally, inspect the ConfigAuditReport to confirm that the Deployment is not compliant with test policies:
+
+```console
+$ kubectl get configauditreport deployment-nginx -o jsonpath='{.report}' | jq
+{
+  "containerChecks": {},
+  "podChecks": [
+    {
+      "category": "Security",
+      "checkID": "Root file system is not read-only",
+      "message": "container nginx of deployment nginx in default namespace should set securityContext.readOnlyRootFilesystem to true",
+      "severity": "DANGER",
+      "success": false
+    },
+    {
+      "category": "Security",
+      "checkID": "Image tag \":latest\" used",
+      "message": "container nginx of deployment nginx in default namespace should specify image tag",
+      "severity": "DANGER",
+      "success": false
+    }
+  ],
+  "scanner": {
+    "name": "Conftest",
+    "vendor": "Open Policy Agent",
+    "version": "v0.23.0"
+  },
+  "summary": {
+    "dangerCount": 2,
+    "passCount": 0,
+    "warningCount": 0
+  },
+  "updateTimestamp": "2021-04-15T13:54:49Z"
+}
+```
+
+!!! Tip
+    The steps for configuring Conftest with Starboard CLI and Starboard Operator are the same except the namespace
+    in which the `starboard-conftest-config` ConfigMap is created.
+
+[OPA]: https://www.openpolicyagent.org
+[Conftest]: https://github.com/open-policy-agent/conftest
+[AppShield]: https://github.com/aquasecurity/appshield
+[kubernetes.rego]: https://raw.githubusercontent.com/aquasecurity/appshield/master/kubernetes/lib/kubernetes.rego
+[utils.rego]: https://raw.githubusercontent.com/aquasecurity/appshield/master/kubernetes/lib/utils.rego
+[file_system_not_read_only.rego]: https://raw.githubusercontent.com/aquasecurity/appshield/master/kubernetes/policies/general/file_system_not_read_only.rego
+[uses_image_tag_latest.rego]: https://raw.githubusercontent.com/aquasecurity/appshield/master/kubernetes/policies/general/uses_image_tag_latest.rego
\ No newline at end of file
diff --git a/pkg/plugin/trivy/plugin_test.go b/pkg/plugin/trivy/plugin_test.go
index d57a93e..6295fee 100644
--- a/pkg/plugin/trivy/plugin_test.go
+++ b/pkg/plugin/trivy/plugin_test.go
@@ -350,8 +350,8 @@ func TestScanner_GetScanJobSpec(t *testing.T) {
 							"trivy",
 						},
 						Args: []string{
-							"client",
 							"--quiet",
+							"client",
 							"--format",
 							"json",
 							"--remote",