Skip to content

Commit

Permalink
feat(trivy): Pass additional settings to Trivy client (#547)
Browse files Browse the repository at this point in the history
Resolves: #541
  • Loading branch information
xyoxo authored May 19, 2021
1 parent 1425f26 commit e1cb116
Show file tree
Hide file tree
Showing 5 changed files with 894 additions and 76 deletions.
9 changes: 7 additions & 2 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ The following tables list available configuration settings with their default va
used if `vulnerabilityReports.scanner` is set to `Trivy`). Check
[integrations](./integrations/vulnerability-scanners/index.md) page to see example configuration settings for common use cases.

| CONFIGMAP KEY | DEFAULT | DESCRIPTION |
| CONFIGMAP KEY | DEFAULT | DESCRIPTION |
| ------------------------------- | ------------------------------------------------------ | ----------- |
| `vulnerabilityReports.scanner` | `Trivy` | The name of the plugin that generates vulnerability reports. Either `Trivy` or `Aqua`. |
| `configAuditReports.scanner` | `Polaris` | The name of the plugin that generates config audit reports. Either `Polaris` or `Conftest`. |
Expand All @@ -66,6 +66,10 @@ The following tables list available configuration settings with their default va
| `trivy.severity` | `UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL` | A comma separated list of severity levels reported by Trivy |
| `trivy.imageRef` | `docker.io/aquasec/trivy:0.16.0` | Trivy image reference |
| `trivy.mode` | `Standalone` | Trivy client mode. Either `Standalone` or `ClientServer`. Depending on the active mode other settings might be applicable or required. |
| `trivy.ignoreUnfixed` | N/A | Whether to show only fixed vulnerabilities in vulnerabilities reported by Trivy. Set to `"true"` to enable it. |
| `trivy.skipFiles` | N/A | A comma separated list of file paths for Trivy to skip traversal. |
| `trivy.skipDirs` | N/A | A comma separated list of directories for Trivy to skip traversal. |
| `trivy.ignoreFile` | N/A | It specifies the `.trivyignore` file which contains a list of vulnerability IDs to be ignored from vulnerabilities reported by Trivy. |
| `trivy.serverURL` | N/A | The endpoint URL of the Trivy server. Required in `ClientServer` mode. |
| `trivy.serverTokenHeader` | `Trivy-Token` | The name of the HTTP header to send the authentication token to Trivy server. Only application in `ClientServer` mode when `trivy.serverToken` is specified. |
| `trivy.insecureRegistry.<id>` | N/A | The registry to which insecure connections are allowed. There can be multiple registries with different registry `<id>`. |
Expand All @@ -77,7 +81,7 @@ The following tables list available configuration settings with their default va
| `polaris.imageRef` | `quay.io/fairwinds/polaris:3.2` | Polaris image reference |
| `polaris.config.yaml` | [Check the default value here][default-polaris-config] | Polaris configuration file |
| `conftest.imageRef` | `docker.io/openpolicyagent/conftest:v0.25.0` | Conftest image reference |
| `scanJob.tolerations` | | JSON representation of the [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration) to be applied to the vulnerability scanner pods so that they can run on nodes with matching taints. Example: `'[{"key":"key1", "operator":"Equal", "value":"value1", "effect":"NoSchedule"}]'`|
| `scanJob.tolerations` | N/A | JSON representation of the [tolerations] to be applied to the vulnerability scanner pods so that they can run on nodes with matching taints. Example: `'[{"key":"key1", "operator":"Equal", "value":"value1", "effect":"NoSchedule"}]'`|

| SECRET KEY | DESCRIPTION |
| --------------------------- | ----------- |
Expand All @@ -97,3 +101,4 @@ The following tables list available configuration settings with their default va
```

[default-polaris-config]: https://raw.githubusercontent.com/aquasecurity/starboard/{{ var.tag }}/deploy/static/05-starboard-operator.config.yaml
[tolerations]: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration
193 changes: 170 additions & 23 deletions pkg/plugin/trivy/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Config interface {
GetTrivyMode() (starboard.TrivyMode, error)
GetTrivyServerURL() (string, error)
GetTrivyInsecureRegistries() map[string]bool
TrivyIgnoreFileExists() bool
}

// NewPlugin constructs a new vulnerabilityreport.Plugin, which is using an
Expand Down Expand Up @@ -88,7 +89,8 @@ func (s *scanner) newSecretWithAggregateImagePullCredentials(spec corev1.PodSpec
}

const (
sharedVolumeName = "data"
sharedVolumeName = "data"
ignoreFileVolumeName = "ignorefile"
)

// In the starboard.Standalone mode there is the init container responsible for
Expand Down Expand Up @@ -193,6 +195,49 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m

var containers []corev1.Container

volumeMounts := []corev1.VolumeMount{
{
Name: sharedVolumeName,
ReadOnly: false,
MountPath: "/var/lib/trivy",
},
}
volumes := []corev1.Volume{
{
Name: sharedVolumeName,
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumDefault,
},
},
},
}

if s.config.TrivyIgnoreFileExists() {
volumes = append(volumes, corev1.Volume{
Name: ignoreFileVolumeName,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Items: []corev1.KeyToPath{
{
Key: "trivy.ignoreFile",
Path: ".trivyignore",
},
},
},
},
})

volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: ignoreFileVolumeName,
MountPath: "/tmp/trivy/.trivyignore",
SubPath: ".trivyignore",
})
}

for _, c := range spec.Containers {

env := []corev1.EnvVar{
Expand All @@ -208,6 +253,42 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m
},
},
},
{
Name: "TRIVY_IGNORE_UNFIXED",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Key: "trivy.ignoreUnfixed",
Optional: pointer.BoolPtr(true),
},
},
},
{
Name: "TRIVY_SKIP_FILES",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Key: "trivy.skipFiles",
Optional: pointer.BoolPtr(true),
},
},
},
{
Name: "TRIVY_SKIP_DIRS",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Key: "trivy.skipDirs",
Optional: pointer.BoolPtr(true),
},
},
},
{
Name: "HTTP_PROXY",
ValueFrom: &corev1.EnvVarSource{
Expand Down Expand Up @@ -246,6 +327,13 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m
},
}

if s.config.TrivyIgnoreFileExists() {
env = append(env, corev1.EnvVar{
Name: "TRIVY_IGNOREFILE",
Value: "/tmp/trivy/.trivyignore",
})
}

if _, ok := credentials[c.Name]; ok && secret != nil {
registryUsernameKey := fmt.Sprintf("%s.username", c.Name)
registryPasswordKey := fmt.Sprintf("%s.password", c.Name)
Expand Down Expand Up @@ -296,14 +384,8 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m
"json",
c.Image,
},
Resources: defaultResourceRequirements,
VolumeMounts: []corev1.VolumeMount{
{
Name: sharedVolumeName,
ReadOnly: false,
MountPath: "/var/lib/trivy",
},
},
Resources: defaultResourceRequirements,
VolumeMounts: volumeMounts,
SecurityContext: &corev1.SecurityContext{
Privileged: pointer.BoolPtr(false),
AllowPrivilegeEscalation: pointer.BoolPtr(false),
Expand All @@ -319,19 +401,10 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m
Affinity: starboard.LinuxNodeAffinity(),
RestartPolicy: corev1.RestartPolicyNever,
AutomountServiceAccountToken: pointer.BoolPtr(false),
Volumes: []corev1.Volume{
{
Name: sharedVolumeName,
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumDefault,
},
},
},
},
InitContainers: []corev1.Container{initContainer},
Containers: containers,
SecurityContext: &corev1.PodSecurityContext{},
Volumes: volumes,
InitContainers: []corev1.Container{initContainer},
Containers: containers,
SecurityContext: &corev1.PodSecurityContext{},
}, secrets, nil
}

Expand All @@ -345,6 +418,8 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m
func (s *scanner) getPodSpecForClientServerMode(spec corev1.PodSpec, credentials map[string]docker.Auth) (corev1.PodSpec, []*corev1.Secret, error) {
var secret *corev1.Secret
var secrets []*corev1.Secret
var volumeMounts []corev1.VolumeMount
var volumes []corev1.Volume

trivyImageRef, err := s.config.GetTrivyImageRef()
if err != nil {
Expand Down Expand Up @@ -414,6 +489,42 @@ func (s *scanner) getPodSpecForClientServerMode(spec corev1.PodSpec, credentials
},
},
},
{
Name: "TRIVY_IGNORE_UNFIXED",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Key: "trivy.ignoreUnfixed",
Optional: pointer.BoolPtr(true),
},
},
},
{
Name: "TRIVY_SKIP_FILES",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Key: "trivy.skipFiles",
Optional: pointer.BoolPtr(true),
},
},
},
{
Name: "TRIVY_SKIP_DIRS",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Key: "trivy.skipDirs",
Optional: pointer.BoolPtr(true),
},
},
},
{
Name: "TRIVY_TOKEN_HEADER",
ValueFrom: &corev1.EnvVarSource{
Expand Down Expand Up @@ -484,6 +595,40 @@ func (s *scanner) getPodSpecForClientServerMode(spec corev1.PodSpec, credentials
return corev1.PodSpec{}, nil, err
}

if s.config.TrivyIgnoreFileExists() {
volumes = []corev1.Volume{
{
Name: ignoreFileVolumeName,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: starboard.ConfigMapName,
},
Items: []corev1.KeyToPath{
{
Key: "trivy.ignoreFile",
Path: ".trivyignore",
},
},
},
},
},
}

volumeMounts = []corev1.VolumeMount{
{
Name: ignoreFileVolumeName,
MountPath: "/tmp/trivy/.trivyignore",
SubPath: ".trivyignore",
},
}

env = append(env, corev1.EnvVar{
Name: "TRIVY_IGNOREFILE",
Value: "/tmp/trivy/.trivyignore",
})
}

containers = append(containers, corev1.Container{
Name: container.Name,
Image: trivyImageRef,
Expand All @@ -502,14 +647,16 @@ func (s *scanner) getPodSpecForClientServerMode(spec corev1.PodSpec, credentials
trivyServerURL,
container.Image,
},
Resources: defaultResourceRequirements,
VolumeMounts: volumeMounts,
Resources: defaultResourceRequirements,
})
}

return corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
AutomountServiceAccountToken: pointer.BoolPtr(false),
Containers: containers,
Volumes: volumes,
}, secrets, nil
}

Expand Down
Loading

0 comments on commit e1cb116

Please sign in to comment.