fix(build): mirror the Trivy Java DB — jar-bearing builds failed closed at the scan gate (#72)
This commit is contained in:
9 files changed
+77
-30
No files matched your search
+2
-1
@@ -423,7 +423,8 @@ func buildConfig(cfg *config.Config) build.Config {
|
||||
MemLimit: cfg.Registry.BuildMemLimit,
|
||||
// Empty keeps Trivy's own default; an install with builds points this at
|
||||
// the internal DB mirror (see config.RegistryConfig.TrivyDBRepository).
|
||||
TrivyDBRepository: cfg.Registry.TrivyDBRepository,
|
||||
TrivyDBRepository: cfg.Registry.TrivyDBRepository,
|
||||
TrivyJavaDBRepository: cfg.Registry.TrivyJavaDBRepository,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2188,7 +2188,7 @@ persisted_registry_block() {
|
||||
out="$(awk '
|
||||
/^[[:space:]]*\[/ { sect = $0; next }
|
||||
sect ~ /^[[:space:]]*\[registry\][[:space:]]*$/ &&
|
||||
/^[[:space:]]*(kaniko_image|trivy_image|trivy_db_repository|build_cpu_limit|build_mem_limit|user_uploads_context)[[:space:]]*=/ { print }
|
||||
/^[[:space:]]*(kaniko_image|trivy_image|trivy_db_repository|trivy_java_db_repository|build_cpu_limit|build_mem_limit|user_uploads_context)[[:space:]]*=/ { print }
|
||||
sect ~ /^[[:space:]]*\[registry\.s3\][[:space:]]*$/ && /^[[:space:]]*[A-Za-z_]+[[:space:]]*=/ {
|
||||
if (!s3hdr) { printf "[registry.s3]\n"; s3hdr = 1 }
|
||||
print
|
||||
|
||||
@@ -878,6 +878,7 @@ url = "stale.invalid:5000"
|
||||
build_namespace = "stale-ns"
|
||||
kaniko_image = "registry.felis.svc:5000/mirror/kaniko-executor:v1.24.0"
|
||||
trivy_db_repository = "registry.felis.svc:5000/mirror/trivy-db:2"
|
||||
trivy_java_db_repository = "registry.felis.svc:5000/mirror/trivy-java-db:1"
|
||||
|
||||
[registry.s3]
|
||||
endpoint = "https://s3.example"
|
||||
@@ -905,6 +906,10 @@ run_write "$rdir/out.toml"
|
||||
out="$(cat "$rdir/out.toml")"
|
||||
expect "a re-run carries the build-lane executor mirrors" \
|
||||
'kaniko_image = "registry.felis.svc:5000/mirror/kaniko-executor:v1.24.0"' "$out"
|
||||
expect "a re-run carries the trivy vulnerability-DB mirror" \
|
||||
'trivy_db_repository = "registry.felis.svc:5000/mirror/trivy-db:2"' "$out"
|
||||
expect "a re-run carries the trivy java-DB mirror" \
|
||||
'trivy_java_db_repository = "registry.felis.svc:5000/mirror/trivy-java-db:1"' "$out"
|
||||
expect "a re-run carries the [registry.s3] uploads subtable" "[registry.s3]" "$out"
|
||||
expect "the carried subtable keeps its keys" 'endpoint = "https://s3.example"' "$out"
|
||||
expect "url stays installer-owned" 'url = "registry.felis.svc:5000"' "$out"
|
||||
|
||||
@@ -57,10 +57,12 @@ A grep across `*.md` and `*.go` returns both sets; only the Go ones are seams.
|
||||
build_cpu_limit / build_mem_limit` override them for mirrored or air-gapped
|
||||
installs. Trivy's vulnerability DB is the same story, and now has its own knob:
|
||||
`[registry] trivy_db_repository` points `--db-repository` at an internal mirror
|
||||
(recipe in docs/troubleshooting.md §8e). Left unset on an egress-locked box the
|
||||
scan step fails closed — Kaniko pushes, Trivy exits on the DB download — which
|
||||
is the correct fail direction but leaves the build unfinished, so the mirror is
|
||||
part of a production build install.
|
||||
(recipe in docs/troubleshooting.md §8e); `trivy_java_db_repository` does the
|
||||
same for the Java DB, which Trivy fetches so soon as the scanned image contains
|
||||
a jar — i.e. for every real modpack build. Left unset on an egress-locked box
|
||||
the scan step fails closed — Kaniko pushes, Trivy exits on the DB download —
|
||||
which is the correct fail direction but leaves the build unfinished, so the
|
||||
mirrors are part of a production build install.
|
||||
|
||||
## Built; only its I/O is unverifiable from this repo
|
||||
|
||||
|
||||
@@ -411,6 +411,7 @@ build_namespace = "felis-build"
|
||||
kaniko_image = "registry.felis.svc:5000/mirror/kaniko-executor:v1.24.0"
|
||||
trivy_image = "registry.felis.svc:5000/mirror/trivy:0.74.0"
|
||||
trivy_db_repository = "registry.felis.svc:5000/mirror/trivy-db:2"
|
||||
trivy_java_db_repository = "registry.felis.svc:5000/mirror/trivy-java-db:1"
|
||||
build_cpu_limit = "2"
|
||||
build_mem_limit = "4Gi"
|
||||
```
|
||||
@@ -423,10 +424,13 @@ through the loopback hostPort the registry Deployment binds (docker treats
|
||||
```sh
|
||||
docker pull gcr.io/kaniko-project/executor:v1.24.0 # any versions you pin
|
||||
docker pull aquasec/trivy:0.74.0
|
||||
docker pull mirror.gcr.io/aquasec/trivy-java-db:1
|
||||
docker tag gcr.io/kaniko-project/executor:v1.24.0 127.0.0.1:5000/mirror/kaniko-executor:v1.24.0
|
||||
docker tag aquasec/trivy:0.74.0 127.0.0.1:5000/mirror/trivy:0.74.0
|
||||
docker tag mirror.gcr.io/aquasec/trivy-java-db:1 127.0.0.1:5000/mirror/trivy-java-db:1
|
||||
docker push 127.0.0.1:5000/mirror/kaniko-executor:v1.24.0
|
||||
docker push 127.0.0.1:5000/mirror/trivy:0.74.0
|
||||
docker push 127.0.0.1:5000/mirror/trivy-java-db:1
|
||||
```
|
||||
|
||||
From another machine, port-forward the registry instead (`kubectl -n felis
|
||||
@@ -469,6 +473,13 @@ registry's plain HTTP works for the DB pull exactly as it does for the scanned
|
||||
image. Re-mirror the tag periodically (Trivy refreshes the DB several times a
|
||||
day upstream; a stale mirror only means stale CVE data, never a failed gate).
|
||||
|
||||
`trivy_java_db_repository` is the same story one step lazier: Trivy downloads
|
||||
the Java DB on demand the first time it scans an image containing Java
|
||||
artifacts — every real modpack — and that download fails closed too. Mirror
|
||||
`mirror.gcr.io/aquasec/trivy-java-db:1` alongside the vulnerability DB (commands
|
||||
above); the Java DB refreshes far less often than the vulnerability DB, so a
|
||||
one-off mirror is usually fine.
|
||||
|
||||
---
|
||||
|
||||
## 9. Registry push/pull failures (spec §15)
|
||||
|
||||
+19
-13
@@ -225,6 +225,11 @@ type Config struct {
|
||||
// egress lock denies — an install with builds must point this at an internal
|
||||
// mirror (see config.RegistryConfig.TrivyDBRepository).
|
||||
TrivyDBRepository string
|
||||
// TrivyJavaDBRepository overrides where Trivy fetches its Java DB
|
||||
// (--java-db-repository), downloaded lazily for images that contain Java
|
||||
// artifacts — i.e. every real modpack. Same egress story as the
|
||||
// vulnerability DB (see config.RegistryConfig.TrivyJavaDBRepository).
|
||||
TrivyJavaDBRepository string
|
||||
// KanikoImage / TrivyImage are the executor images.
|
||||
KanikoImage string
|
||||
TrivyImage string
|
||||
@@ -359,19 +364,20 @@ func (b *Builder) Submit(ctx context.Context, req Request) (*Build, error) {
|
||||
// jobParams projects a build + config onto the inputs jobspec.go renders.
|
||||
func (b *Builder) jobParams(bld *Build, cfg Config) JobParams {
|
||||
return JobParams{
|
||||
BuildID: bld.ID,
|
||||
ImageRef: bld.ImageRef,
|
||||
ContextRef: bld.ContextRef,
|
||||
Namespace: cfg.Namespace,
|
||||
ServiceAccount: cfg.ServiceAccount,
|
||||
RegistryURL: cfg.RegistryURL,
|
||||
FelisImage: cfg.FelisImage,
|
||||
TrivyDBRepository: cfg.TrivyDBRepository,
|
||||
KanikoImage: cfg.KanikoImage,
|
||||
TrivyImage: cfg.TrivyImage,
|
||||
Deadline: cfg.Deadline,
|
||||
CPULimit: cfg.CPULimit,
|
||||
MemLimit: cfg.MemLimit,
|
||||
BuildID: bld.ID,
|
||||
ImageRef: bld.ImageRef,
|
||||
ContextRef: bld.ContextRef,
|
||||
Namespace: cfg.Namespace,
|
||||
ServiceAccount: cfg.ServiceAccount,
|
||||
RegistryURL: cfg.RegistryURL,
|
||||
FelisImage: cfg.FelisImage,
|
||||
TrivyDBRepository: cfg.TrivyDBRepository,
|
||||
TrivyJavaDBRepository: cfg.TrivyJavaDBRepository,
|
||||
KanikoImage: cfg.KanikoImage,
|
||||
TrivyImage: cfg.TrivyImage,
|
||||
Deadline: cfg.Deadline,
|
||||
CPULimit: cfg.CPULimit,
|
||||
MemLimit: cfg.MemLimit,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,11 +82,16 @@ type JobParams struct {
|
||||
// --db-repository flag). Empty keeps Trivy's own default; see
|
||||
// build.Config.TrivyDBRepository for why an in-cluster install sets it.
|
||||
TrivyDBRepository string
|
||||
KanikoImage string
|
||||
TrivyImage string
|
||||
Deadline time.Duration
|
||||
CPULimit string
|
||||
MemLimit string
|
||||
// TrivyJavaDBRepository overrides Trivy's Java-DB source (the
|
||||
// --java-db-repository flag), fetched lazily when the image contains Java
|
||||
// artifacts; empty keeps Trivy's own default, which the build egress lock
|
||||
// denies — a jar-bearing image then fails the scan.
|
||||
TrivyJavaDBRepository string
|
||||
KanikoImage string
|
||||
TrivyImage string
|
||||
Deadline time.Duration
|
||||
CPULimit string
|
||||
MemLimit string
|
||||
}
|
||||
|
||||
// BuildJobName is the deterministic Job name for a build id.
|
||||
@@ -257,6 +262,9 @@ func BuildJob(p JobParams) (*batchv1.Job, error) {
|
||||
if p.TrivyDBRepository != "" {
|
||||
trivyArgs = append(trivyArgs, "--db-repository", p.TrivyDBRepository)
|
||||
}
|
||||
if p.TrivyJavaDBRepository != "" {
|
||||
trivyArgs = append(trivyArgs, "--java-db-repository", p.TrivyJavaDBRepository)
|
||||
}
|
||||
trivyArgs = append(trivyArgs, p.ImageRef)
|
||||
trivy := corev1.Container{
|
||||
Name: ContainerTrivy,
|
||||
|
||||
@@ -204,9 +204,9 @@ func TestBuildJobKanikoPushesAndTrivyGates(t *testing.T) {
|
||||
if !hasArg(trivy.Args, p.ImageRef) {
|
||||
t.Errorf("trivy must scan the pushed ref %q, args=%v", p.ImageRef, trivy.Args)
|
||||
}
|
||||
// No DB repository configured: Trivy keeps its own default.
|
||||
if hasArg(trivy.Args, "--db-repository") {
|
||||
t.Errorf("unset TrivyDBRepository must not render --db-repository, args=%v", trivy.Args)
|
||||
// No DB repositories configured: Trivy keeps its own defaults.
|
||||
if hasArg(trivy.Args, "--db-repository") || hasArg(trivy.Args, "--java-db-repository") {
|
||||
t.Errorf("unset DB repositories must not render --db-repository/--java-db-repository, args=%v", trivy.Args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,12 +262,14 @@ func TestBuildJobKanikoGetsOnlyUnpackCapabilities(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A configured DB repository (the internal mirror) must reach Trivy as
|
||||
// --db-repository: without it the scan tries the internet, which the build egress
|
||||
// lock denies, and every build fails closed at the scan gate.
|
||||
// Configured DB repositories (the internal mirrors) must reach Trivy as
|
||||
// --db-repository / --java-db-repository: without them the scan tries the
|
||||
// internet, which the build egress lock denies, and every build fails closed at
|
||||
// the scan gate — the Java DB the moment the image contains a jar.
|
||||
func TestBuildJobTrivyDBRepositoryOverride(t *testing.T) {
|
||||
p := sampleJobParams()
|
||||
p.TrivyDBRepository = "registry.felis.svc:5000/mirror/trivy-db:2"
|
||||
p.TrivyJavaDBRepository = "registry.felis.svc:5000/mirror/trivy-java-db:1"
|
||||
job, err := BuildJob(p)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildJob: %v", err)
|
||||
@@ -276,6 +278,9 @@ func TestBuildJobTrivyDBRepositoryOverride(t *testing.T) {
|
||||
if !argPairPresent(trivy.Args, "--db-repository", p.TrivyDBRepository) {
|
||||
t.Errorf("trivy args = %v, want --db-repository %s", trivy.Args, p.TrivyDBRepository)
|
||||
}
|
||||
if !argPairPresent(trivy.Args, "--java-db-repository", p.TrivyJavaDBRepository) {
|
||||
t.Errorf("trivy args = %v, want --java-db-repository %s", trivy.Args, p.TrivyJavaDBRepository)
|
||||
}
|
||||
// The scanned image ref must stay the last argument.
|
||||
if last := trivy.Args[len(trivy.Args)-1]; last != p.ImageRef {
|
||||
t.Errorf("image ref must remain the last argument, args=%v", trivy.Args)
|
||||
|
||||
@@ -145,6 +145,15 @@ type RegistryConfig struct {
|
||||
// default (only usable on an install that deliberately opens internet
|
||||
// egress to the DB hosts).
|
||||
TrivyDBRepository string `toml:"trivy_db_repository"`
|
||||
// TrivyJavaDBRepository points Trivy at an OCI repository holding the Java
|
||||
// DB (--java-db-repository). Trivy fetches it lazily whenever the scanned
|
||||
// image contains Java artifacts — every real modpack image does — so on an
|
||||
// egress-locked box the scan fails closed without this mirror exactly like
|
||||
// the vulnerability DB. The supported shape is an internal mirror: copy
|
||||
// mirror.gcr.io/aquasec/trivy-java-db:1 into this cluster's registry and
|
||||
// set this to registry.<ns>.svc:5000/mirror/trivy-java-db:1 (recipe in
|
||||
// docs/troubleshooting.md §8e). Empty keeps Trivy's own default.
|
||||
TrivyJavaDBRepository string `toml:"trivy_java_db_repository"`
|
||||
// UserUploadsContext is the object-store base under which a user-submitted
|
||||
// modpack's Kaniko build context is pinned. It belongs to the §16 build
|
||||
// subsystem's input domain (the build-context store), introduced by the
|
||||
|
||||
Reference in new issue
Block a user