mirror of
https://github.com/siderolabs/kres.git
synced 2026-02-05 09:45:35 +01:00
feat: add govulncheck wrapper
This wrapper enables excluding vulnerabilities to pass scans, if we are unaffected. Signed-off-by: Mateusz Urbanek <mateusz.urbanek@siderolabs.com>
This commit is contained in:
@@ -400,6 +400,10 @@ func (generate *Generate) CompileTemplates(output *template.Output) error {
|
||||
WithLicenseText(generate.LicenseText).
|
||||
NoOverwrite()
|
||||
|
||||
output.Define(govulncheckPath, templates.GoVulnCheck).
|
||||
NoPreamble().
|
||||
NoOverwrite()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -5,20 +5,26 @@
|
||||
package golang
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/siderolabs/kres/internal/dag"
|
||||
"github.com/siderolabs/kres/internal/output/dockerfile"
|
||||
"github.com/siderolabs/kres/internal/output/dockerfile/step"
|
||||
"github.com/siderolabs/kres/internal/output/dockerignore"
|
||||
"github.com/siderolabs/kres/internal/output/makefile"
|
||||
"github.com/siderolabs/kres/internal/project/meta"
|
||||
)
|
||||
|
||||
const govulncheckPath = "hack/govulncheck.sh"
|
||||
|
||||
// GoVulnCheck provides GoVulnCheck linter.
|
||||
type GoVulnCheck struct { //nolint:govet
|
||||
dag.BaseNode
|
||||
|
||||
Disabled bool `yaml:"disabled"`
|
||||
Disabled bool `yaml:"disabled"`
|
||||
Ignore []string `yaml:"ignore,omitempty"`
|
||||
|
||||
meta *meta.Options
|
||||
projectPath string
|
||||
@@ -34,6 +40,13 @@ func NewGoVulnCheck(meta *meta.Options, projectPath string) *GoVulnCheck {
|
||||
}
|
||||
}
|
||||
|
||||
// CompileDockerignore implements dockerignore.Compiler.
|
||||
func (lint *GoVulnCheck) CompileDockerignore(output *dockerignore.Output) error {
|
||||
output.AllowLocalPath(govulncheckPath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompileMakefile implements makefile.Compiler.
|
||||
func (lint *GoVulnCheck) CompileMakefile(output *makefile.Output) error {
|
||||
if lint.Disabled {
|
||||
@@ -54,12 +67,18 @@ func (lint *GoVulnCheck) CompileDockerfile(output *dockerfile.Output) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
script := "./hack/govulncheck.sh ./..."
|
||||
if len(lint.Ignore) != 0 {
|
||||
script = fmt.Sprintf("./hack/govulncheck.sh -exclude '%s' ./...", strings.Join(lint.Ignore, ","))
|
||||
}
|
||||
|
||||
output.Stage(lint.Name()).
|
||||
Description("runs govulncheck").
|
||||
From("base").
|
||||
Step(step.Copy(govulncheckPath, "./hack/govulncheck.sh").Chmod(0o755)).
|
||||
Step(step.WorkDir(filepath.Join("/src", lint.projectPath))).
|
||||
Step(step.Script(
|
||||
`govulncheck ./...`,
|
||||
script,
|
||||
).
|
||||
MountCache(filepath.Join(lint.meta.CachePath, "go-build"), lint.meta.GitHubRepository).
|
||||
MountCache(filepath.Join(lint.meta.GoPath, "pkg"), lint.meta.GitHubRepository),
|
||||
|
||||
86
internal/project/golang/templates/govulncheck.sh
Normal file
86
internal/project/golang/templates/govulncheck.sh
Normal file
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# Source: https://github.com/tianon/gosu/blob/e157efb/govulncheck-with-excludes.sh
|
||||
# Licensed under the Apache License, Version 2.0
|
||||
# Copyright Tianon Gravi
|
||||
set -Eeuo pipefail
|
||||
|
||||
exclude_arg=""
|
||||
pass_args=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-exclude)
|
||||
exclude_arg="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
pass_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -n "$exclude_arg" ]]; then
|
||||
excludeVulns="$(jq -nc --arg list "$exclude_arg" '$list | split(",")')"
|
||||
else
|
||||
excludeVulns="[]"
|
||||
fi
|
||||
|
||||
export excludeVulns
|
||||
|
||||
# Debug print
|
||||
echo "excludeVulns = $excludeVulns"
|
||||
echo "Passing args: ${pass_args[*]}"
|
||||
|
||||
if ! command -v govulncheck > /dev/null; then
|
||||
printf "govulncheck not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if out="$(govulncheck "${pass_args[@]}")"; then
|
||||
printf '%s\n' "$out"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
json="$(govulncheck -json "${pass_args[@]}")"
|
||||
|
||||
vulns="$(jq <<<"$json" -cs '
|
||||
(
|
||||
map(
|
||||
.osv // empty
|
||||
| { key: .id, value: . }
|
||||
)
|
||||
| from_entries
|
||||
) as $meta
|
||||
# https://github.com/tianon/gosu/issues/144
|
||||
| map(
|
||||
.finding // empty
|
||||
# https://github.com/golang/vuln/blob/3740f5cb12a3f93b18dbe200c4bcb6256f8586e2/internal/scan/template.go#L97-L104
|
||||
| select((.trace[0].function // "") != "")
|
||||
| .osv
|
||||
)
|
||||
| unique
|
||||
| map($meta[.])
|
||||
')"
|
||||
if [ "$(jq <<<"$vulns" -r 'length')" -le 0 ]; then
|
||||
printf '%s\n' "$out"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
filtered="$(jq <<<"$vulns" -c '
|
||||
(env.excludeVulns | fromjson) as $exclude
|
||||
| map(select(
|
||||
.id as $id
|
||||
| $exclude | index($id) | not
|
||||
))
|
||||
')"
|
||||
|
||||
text="$(jq <<<"$filtered" -r 'map("- \(.id) (aka \(.aliases | join(", ")))\n\n\t\(.details | gsub("\n"; "\n\t"))") | join("\n\n")')"
|
||||
|
||||
if [ -z "$text" ]; then
|
||||
printf 'No vulnerabilities found.\n'
|
||||
exit 0
|
||||
else
|
||||
printf '%s\n' "$text"
|
||||
exit 1
|
||||
fi
|
||||
@@ -11,3 +11,8 @@ import _ "embed"
|
||||
//
|
||||
//go:embed version_go
|
||||
var VersionGo string
|
||||
|
||||
// GoVulnCheck govulncheck.sh
|
||||
//
|
||||
//go:embed govulncheck.sh
|
||||
var GoVulnCheck string
|
||||
|
||||
@@ -202,7 +202,7 @@ func (toolchain *Toolchain) CompileDockerfile(output *dockerfile.Output) error {
|
||||
From("--platform=${BUILDPLATFORM} ${TOOLCHAIN}")
|
||||
|
||||
if toolchain.Kind == ToolchainOfficial {
|
||||
packages := []string{"add", "bash", "curl", "build-base", "protoc", "protobuf-dev"}
|
||||
packages := []string{"add", "bash", "build-base", "curl", "jq", "protoc", "protobuf-dev"}
|
||||
packages = append(packages, toolchain.ExtraPackages...)
|
||||
|
||||
// automatically add git if we know we're going to have to deal with private repos
|
||||
|
||||
Reference in New Issue
Block a user