Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
55fa917
fix: Update golangci-lint config to v2 format and Go version to 1.23
ashnamehrotra Nov 20, 2025
3bf4801
update manager vulns and handle api migrations
ashnamehrotra Nov 20, 2025
115c155
remover image vulns
ashnamehrotra Nov 20, 2025
bd92d2f
update k8s
ashnamehrotra Nov 20, 2025
53c6cc5
update trivy binary
ashnamehrotra Nov 20, 2025
eac2ac4
change base img
ashnamehrotra Nov 20, 2025
7b47784
Merge branch 'main' of github.com:Azure/eraser into fix-vulns
ashnamehrotra Nov 21, 2025
114fd1a
final cve changes
ashnamehrotra Nov 26, 2025
81fb459
more lint
ashnamehrotra Nov 26, 2025
3e59077
unit test fix
ashnamehrotra Nov 26, 2025
aa34ec4
ignore revive
ashnamehrotra Nov 26, 2025
12e2be3
trivy binary update
ashnamehrotra Nov 26, 2025
b2e73a5
try increase timeout
ashnamehrotra Nov 26, 2025
d374da9
test fix
ashnamehrotra Nov 26, 2025
46fd36e
use grcp new client
ashnamehrotra Nov 26, 2025
1f9b180
grpc fix
ashnamehrotra Nov 26, 2025
4977f2b
grpc fix
ashnamehrotra Nov 26, 2025
67c84e8
getConn test
ashnamehrotra Nov 26, 2025
7507e05
update go version in CI
ashnamehrotra Nov 26, 2025
946f21c
revert grpc
ashnamehrotra Nov 26, 2025
8da8978
revert Dockerfile
ashnamehrotra Nov 26, 2025
e929a4c
Merge branch 'main' of github.com:Azure/eraser into fix-vulns
ashnamehrotra Nov 26, 2025
bb54194
trivy fs vulns upgrade
ashnamehrotra Nov 26, 2025
e6549b0
govulncheck fixes
ashnamehrotra Nov 26, 2025
b0dcdc6
docs changes
ashnamehrotra Nov 26, 2025
6cb2b32
update to go 1.25 and trivy binary to 0.67.2
ashnamehrotra Nov 26, 2025
7739e3d
change golang:1.25.3-bookworm to golang:1.25-bookworm
ashnamehrotra Nov 26, 2025
0ee866c
go version to 1.25 in workflows
ashnamehrotra Nov 26, 2025
70ddf0d
remove checkNodeFitness
ashnamehrotra Dec 1, 2025
b859a49
Merge branch 'main' of github.com:Azure/eraser into fix-vulns
ashnamehrotra Dec 1, 2025
f352eaf
Update .golangci.yaml
ashnamehrotra Dec 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/e2e-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.24.9"
check-latest: true
- name: Setup buildx instance
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.24.9"
check-latest: true
- name: Setup buildx instance
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
Expand Down Expand Up @@ -105,7 +105,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.24.9"
check-latest: true
- name: Setup buildx instance
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
Expand Down Expand Up @@ -147,7 +147,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.24.9"
check-latest: true
- name: Setup buildx instance
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.24.9"
check-latest: true
- name: Set env
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.24.9"
check-latest: true

- name: Set release version and target branch for vNext
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.25"
check-latest: true
- name: lint manager
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.25"
check-latest: true
- uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
Expand Down Expand Up @@ -128,7 +128,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.21"
go-version: "1.25"
check-latest: true
- name: Check go.mod and manifests
run: |
Expand Down
52 changes: 27 additions & 25 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
run:
timeout: 5m

linters-settings:
gocritic:
enabled-tags:
- performance
gosec:
excludes:
- G108
lll:
line-length: 200
version: "2"

misspell:
locale: US
staticcheck:
go: "1.21"
run:
go: "1.23"

linters:
disable-all: true
default: none
enable:
- errcheck
- exportloopref
- copyloopvar # replacement for exportloopref
- forcetypeassert
- gocritic
- goconst
- godot
- gofmt
- gofumpt
- goimports
- gosec
- gosimple
- govet
- ineffassign
- misspell
- revive # replacement for golint
- staticcheck
- typecheck
# - revive # replacement for golint
- staticcheck # includes gosimple and staticcheck
- unused
- whitespace
settings:
gocritic:
enabled-tags:
- performance
gosec:
excludes:
- G108
lll:
line-length: 200
misspell:
locale: US
exclusions:
paths:
- "docs/build/assets/files/.*\\.go"

formatters:
enable:
- gofmt
- gofumpt
- goimports
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# syntax=docker/dockerfile:1.6

# Default Trivy binary image, overwritten by Makefile
ARG TRIVY_BINARY_IMG="ghcr.io/aquasecurity/trivy:0.50.0"
ARG TRIVY_BINARY_IMG="ghcr.io/aquasecurity/trivy:0.58.1"
ARG BUILDKIT_SBOM_SCAN_STAGE=builder,manager-build,collector-build,remover-build,trivy-scanner-build

FROM --platform=$TARGETPLATFORM $TRIVY_BINARY_IMG AS trivy-binary

# Build the manager binary
FROM --platform=$BUILDPLATFORM golang:1.25-bookworm AS builder
FROM --platform=$BUILDPLATFORM golang:1.25.3-bookworm AS builder
WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
Expand Down Expand Up @@ -70,5 +70,5 @@ COPY --from=trivy-binary /usr/local/bin/trivy /
WORKDIR /var/lib/trivy
ENTRYPOINT ["/trivy-scanner"]

FROM gcr.io/distroless/static:nonroot as non-vulnerable
FROM gcr.io/distroless/static-debian12:nonroot AS non-vulnerable
COPY --from=builder /tmp /tmp
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ REMOVER_TAG ?= ${VERSION}
TRIVY_SCANNER_REPO ?= ghcr.io/eraser-dev/eraser-trivy-scanner
TRIVY_SCANNER_IMG ?= ${TRIVY_SCANNER_REPO}:${TRIVY_SCANNER_TAG}
TRIVY_BINARY_REPO ?= ghcr.io/aquasecurity/trivy
TRIVY_BINARY_TAG ?= 0.48.3
TRIVY_BINARY_TAG ?= 0.67.2
TRIVY_BINARY_IMG ?= ${TRIVY_BINARY_REPO}:${TRIVY_BINARY_TAG}
MANAGER_REPO ?= ghcr.io/eraser-dev/eraser-manager
MANAGER_IMG ?= ${MANAGER_REPO}:${MANAGER_TAG}
Expand Down Expand Up @@ -293,7 +293,7 @@ ENVTEST = $(shell pwd)/bin/setup-envtest
envtest: __tooling-image bin/setup-envtest

bin/setup-envtest:
docker run --rm -v $(shell pwd)/bin:/go/bin -e GO111MODULE=on eraser-tooling go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
docker run --rm -v $(shell pwd)/bin:/go/bin -e GO111MODULE=on eraser-tooling go install sigs.k8s.io/controller-runtime/tools/setup-envtest@v0.0.0-20240320141353-395cfc7486e6

__controller-gen: __tooling-image
CONTROLLER_GEN=docker run --rm -v $(shell pwd):/eraser eraser-tooling controller-gen
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// Package v1alpha1 contains API Schema definitions for the eraser v1alpha1 API version.
// +k8s:conversion-gen=github.com/eraser-dev/eraser/api/unversioned
package v1alpha1
1 change: 1 addition & 0 deletions api/v1alpha2/doc.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// Package v1alpha2 contains API Schema definitions for the eraser v1alpha2 API version.
// +k8s:conversion-gen=github.com/eraser-dev/eraser/api/unversioned
package v1alpha2
2 changes: 1 addition & 1 deletion controllers/configmap/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func Add(mgr manager.Manager, cfg *config.Manager) error {
}

err = c.Watch(
&source.Kind{Type: &corev1.ConfigMap{}},
source.Kind(mgr.GetCache(), &corev1.ConfigMap{}),
&handler.EnqueueRequestForObject{},
predicate.ResourceVersionChangedPredicate{},
predicate.Funcs{
Expand Down
1 change: 1 addition & 0 deletions controllers/controller.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package controllers implements Kubernetes controllers for eraser resources.
package controllers

import (
Expand Down
4 changes: 2 additions & 2 deletions controllers/imagecollector/imagecollector_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,15 @@ func add(mgr manager.Manager, r *Reconciler) error {
}

err = c.Watch(
&source.Kind{Type: &eraserv1.ImageJob{}},
source.Kind(mgr.GetCache(), &eraserv1.ImageJob{}),
&handler.EnqueueRequestForObject{}, predicate.Funcs{
// Do nothing on Create, Delete, or Generic events
CreateFunc: util.NeverOnCreate,
DeleteFunc: util.NeverOnDelete,
GenericFunc: util.NeverOnGeneric,
UpdateFunc: func(e event.UpdateEvent) bool {
if job, ok := e.ObjectNew.(*eraserv1.ImageJob); ok && util.IsCompletedOrFailed(job.Status.Phase) {
return ownerLabel.Matches(labels.Set(job.ObjectMeta.Labels))
return ownerLabel.Matches(labels.Set(job.Labels))
}

return false
Expand Down
77 changes: 48 additions & 29 deletions controllers/imagejob/imagejob_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ import (

"golang.org/x/exp/slices"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/pkg/scheduler/framework"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"

"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -102,7 +101,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
}

// Watch for changes to ImageJob
err = c.Watch(&source.Kind{Type: &eraserv1.ImageJob{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
err = c.Watch(source.Kind(mgr.GetCache(), &eraserv1.ImageJob{}), &handler.EnqueueRequestForObject{}, predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
if job, ok := e.ObjectNew.(*eraserv1.ImageJob); ok && controllerUtils.IsCompletedOrFailed(job.Status.Phase) {
return false // handled by Owning controller
Expand All @@ -120,13 +119,8 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {

// Watch for changes to pods created by ImageJob (eraser pods)
err = c.Watch(
&source.Kind{
Type: &corev1.Pod{},
},
&handler.EnqueueRequestForOwner{
OwnerType: &corev1.PodTemplate{},
IsController: true,
},
source.Kind(mgr.GetCache(), &corev1.Pod{}),
handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &corev1.PodTemplate{}),
predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return e.Object.GetNamespace() == eraserUtils.GetNamespace()
Expand All @@ -145,13 +139,8 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {

// watch for changes to imagejob podTemplate (owned by controller manager pod)
err = c.Watch(
&source.Kind{
Type: &corev1.PodTemplate{},
},
&handler.EnqueueRequestForOwner{
OwnerType: &corev1.Pod{},
IsController: true,
},
source.Kind(mgr.GetCache(), &corev1.PodTemplate{}),
handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &corev1.Pod{}),
predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
ownerLabels, ok := e.Object.GetLabels()[managerLabelKey]
Expand All @@ -175,14 +164,43 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
}

func checkNodeFitness(pod *corev1.Pod, node *corev1.Node) bool {
nodeInfo := framework.NewNodeInfo()
nodeInfo.SetNode(node)
// Check if node has sufficient resources for the pod
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did we reimplement this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The framework package it was using introduces k8s.io/kubernetes vulnerabilities which is what this was trying to resolve. In order to upgrade this to latest version, it would require major controller runtime api changes. By removing the dependency on this we can eliminate both the dependency and vulns.

nodeAllocatable := node.Status.Allocatable
if nodeAllocatable == nil {
log.Error(fmt.Errorf("node %v has no allocatable resources", node.Name), "node resource check")
return false
}

insufficientResource := noderesources.Fits(pod, nodeInfo)
// Calculate total resource requests from all containers in the pod
totalCPU := resource.NewQuantity(0, resource.DecimalSI)
totalMemory := resource.NewQuantity(0, resource.BinarySI)

if len(insufficientResource) != 0 {
log.Error(fmt.Errorf("pod %v in namespace %v does not fit in node %v", pod.Name, pod.Namespace, node.Name), "insufficient resource")
return false
for i := range pod.Spec.Containers {
container := &pod.Spec.Containers[i]
if container.Resources.Requests != nil {
if cpu, exists := container.Resources.Requests[corev1.ResourceCPU]; exists {
totalCPU.Add(cpu)
}
if memory, exists := container.Resources.Requests[corev1.ResourceMemory]; exists {
totalMemory.Add(memory)
}
}
}

// Check if node has sufficient CPU
if allocatableCPU, exists := nodeAllocatable[corev1.ResourceCPU]; exists {
if totalCPU.Cmp(allocatableCPU) > 0 {
log.Error(fmt.Errorf("pod %v in namespace %v requires more CPU than available on node %v", pod.Name, pod.Namespace, node.Name), "insufficient CPU")
return false
}
}

// Check if node has sufficient memory
if allocatableMemory, exists := nodeAllocatable[corev1.ResourceMemory]; exists {
if totalMemory.Cmp(allocatableMemory) > 0 {
log.Error(fmt.Errorf("pod %v in namespace %v requires more memory than available on node %v", pod.Name, pod.Namespace, node.Name), "insufficient memory")
return false
}
}

return true
Expand Down Expand Up @@ -437,6 +455,7 @@ func (r *Reconciler) handleNewJob(ctx context.Context, imageJob *eraserv1.ImageJ
}

for _, namespacedName := range namespacedNames {
//nolint:staticcheck // SA1019: TODO: Replace with PollUntilContextTimeout in future refactor
if err := wait.PollImmediate(time.Nanosecond, time.Minute*5, r.isPodReady(ctx, namespacedName)); err != nil {
log.Error(err, "timed out waiting for pod to leave pending state", "pod NamespacedName", namespacedName)
}
Expand Down Expand Up @@ -509,11 +528,11 @@ nodes:
}

log.V(1).Info("includedLabels", "includedLabels", includedLabels)
log.V(1).Info("nodeLabels", "nodeLabels", nodes.Items[i].ObjectMeta.Labels)
if includedLabels.Matches(labels.Set(nodes.Items[i].ObjectMeta.Labels)) {
log.V(1).Info("nodeLabels", "nodeLabels", nodes.Items[i].Labels)
if includedLabels.Matches(labels.Set(nodes.Items[i].Labels)) {
log.Info("node is included because it matched the specified labels",
"nodeName", nodeName,
"labels", nodes.Items[i].ObjectMeta.Labels,
"labels", nodes.Items[i].Labels,
"specifiedSelectors", includeNodesSelectors,
)

Expand Down Expand Up @@ -543,11 +562,11 @@ nodes:
}

log.V(1).Info("skipLabels", "skipLabels", skipLabels)
log.V(1).Info("nodeLabels", "nodeLabels", nodes.Items[i].ObjectMeta.Labels)
if skipLabels.Matches(labels.Set(nodes.Items[i].ObjectMeta.Labels)) {
log.V(1).Info("nodeLabels", "nodeLabels", nodes.Items[i].Labels)
if skipLabels.Matches(labels.Set(nodes.Items[i].Labels)) {
log.Info("node will be skipped because it matched the specified labels",
"nodeName", nodeName,
"labels", nodes.Items[i].ObjectMeta.Labels,
"labels", nodes.Items[i].Labels,
"specifiedSelectors", skipNodesSelectors,
)

Expand Down
Loading
Loading