diff --git a/Makefile b/Makefile index 0090809e..8a9cdaec 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,9 @@ build_m1: ## build docker-slim build_dev: ## build docker-slim for development (quickly), in bin/ '$(CURDIR)/scripts/src.build.quick.sh' +build-sensor: ## build mint-sensor + '$(CURDIR)/scripts/src.build.sensor.sh' + fmt: ## format all golang files '$(CURDIR)/scripts/src.fmt.sh' @@ -34,6 +37,9 @@ test: export GO_TEST_FLAGS ?= test: '$(CURDIR)/scripts/src.test.sh' +test-e2e-exclude: build-sensor + sudo DSLIM_SENSOR_PATH=$(CURDIR)/bin/mint-sensor go test -v -tags e2e -count 1 -timeout 30m -run TestExcludePattern ./pkg/app/sensor + clean: ## clean up '$(CURDIR)/scripts/src.cleanup.sh' diff --git a/build/mint-sensor b/build/mint-sensor new file mode 100755 index 00000000..e6fac760 Binary files /dev/null and b/build/mint-sensor differ diff --git a/pkg/app/master/inspectors/sensor/sensor.go b/pkg/app/master/inspectors/sensor/sensor.go index 1dec5ee6..c061fc44 100644 --- a/pkg/app/master/inspectors/sensor/sensor.go +++ b/pkg/app/master/inspectors/sensor/sensor.go @@ -20,7 +20,10 @@ const ( ) func EnsureLocalBinary(xc *app.ExecutionContext, logger *log.Entry, statePath string, printState bool) string { - sensorPath := filepath.Join(fsutil.ExeDir(), LocalBinFile) + sensorPath := os.Getenv("DSLIM_SENSOR_PATH") + if sensorPath == "" { + sensorPath = filepath.Join(fsutil.ExeDir(), LocalBinFile) + } if runtime.GOOS == "darwin" { stateSensorPath := filepath.Join(statePath, LocalBinFile) diff --git a/pkg/app/sensor/artifact/artifact.go b/pkg/app/sensor/artifact/artifact.go index 72553aea..e6896069 100644 --- a/pkg/app/sensor/artifact/artifact.go +++ b/pkg/app/sensor/artifact/artifact.go @@ -1985,7 +1985,7 @@ func (p *store) saveArtifacts() { syscall.Umask(0) - excludePatterns := p.cmd.Excludes + excludePatterns := addImplicitExcludes(p.cmd.Excludes) excludePatterns = append(excludePatterns, "/opt/_mint") excludePatterns = append(excludePatterns, "/opt/_mint/**") if p.cmd.ExcludeVarLockFiles { @@ -3973,3 +3973,21 @@ func getFileDevice(fullName string) (uint64, error) { return uint64(info.Dev), nil } + +func addImplicitExcludes(patterns []string) []string { + var newExcludes []string + for _, pattern := range patterns { + if strings.HasSuffix(pattern, "/**") { + base := strings.TrimSuffix(pattern, "/**") + if base != "" { + newExcludes = append(newExcludes, base) + } + } + } + + if len(newExcludes) > 0 { + return append(patterns, newExcludes...) + } + + return patterns +} diff --git a/pkg/app/sensor/exclude_test.go b/pkg/app/sensor/exclude_test.go new file mode 100644 index 00000000..b16c08d5 --- /dev/null +++ b/pkg/app/sensor/exclude_test.go @@ -0,0 +1,71 @@ +//go:build e2e +// +build e2e + +package sensor_test + +import ( + "context" + "os" + "path/filepath" + "testing" + "time" + + "github.com/mintoolkit/mint/pkg/ipc/event" + testsensor "github.com/mintoolkit/mint/pkg/test/e2e/sensor" +) + +func TestExcludePattern(t *testing.T) { + // Create a temporary directory for the sensor executable + sensorBinDir := t.TempDir() + t.Setenv("DSLIM_SENSOR_PATH", filepath.Join(sensorBinDir, testsensor.LocalBinFile)) + if err := os.WriteFile(filepath.Join(sensorBinDir, testsensor.LocalBinFile), []byte(""), 0755); err != nil { + t.Fatalf("Failed to create dummy sensor executable: %v", err) + } + + runID := newTestRun(t) + ctx := context.Background() + + // Setup a temporary directory with a file to be excluded + tmpDir := t.TempDir() + excludeDir := filepath.Join(tmpDir, "exclude_me") + err := os.Mkdir(excludeDir, 0755) + if err != nil { + t.Fatalf("Failed to create exclude directory: %v", err) + } + + excludeFile := filepath.Join(excludeDir, "file.txt") + err = os.WriteFile(excludeFile, []byte("some data"), 0644) + if err != nil { + t.Fatalf("Failed to create exclude file: %v", err) + } + + sensor := testsensor.NewSensorOrFail(t, ctx, tmpDir, runID, imageSimpleCLI) + defer sensor.Cleanup(t, ctx) + + sensor.StartControlledOrFail(t, ctx) + + sensor.SendStartCommandOrFail(t, ctx, + testsensor.NewMonitorStartCommand( + testsensor.WithSaneDefaults(), + testsensor.WithAppNameArgs("sh", "-c", "ls -R /"), + testsensor.WithExcludes("/tmp/exclude_me/**"), + ), + ) + sensor.ExpectEvent(t, event.StartMonitorDone) + + time.Sleep(5 * time.Second) + + sensor.SendStopCommandOrFail(t, ctx) + sensor.ExpectEvent(t, event.StopMonitorDone) + + sensor.ShutdownOrFail(t, ctx) + sensor.WaitOrFail(t, ctx) + + sensor.DownloadArtifactsOrFail(t, ctx) + + // Assert that the directory and file are not included in the report. + sensor.AssertReportNotIncludesFiles(t, + "/tmp/exclude_me", + "/tmp/exclude_me/file.txt", + ) +} diff --git a/pkg/app/sensor/mint-sensor b/pkg/app/sensor/mint-sensor new file mode 100755 index 00000000..0acbf5e3 Binary files /dev/null and b/pkg/app/sensor/mint-sensor differ diff --git a/pkg/test/e2e/sensor/monitor.go b/pkg/test/e2e/sensor/monitor.go index c8828213..f0070101 100644 --- a/pkg/test/e2e/sensor/monitor.go +++ b/pkg/test/e2e/sensor/monitor.go @@ -52,6 +52,12 @@ func WithPreserves(path ...string) StartMonitorOpt { } } +func WithExcludes(path ...string) StartMonitorOpt { + return func(cmd *command.StartMonitor) { + cmd.Excludes = path + } +} + func NewMonitorStartCommand(opts ...StartMonitorOpt) command.StartMonitor { cmd := command.StartMonitor{} diff --git a/pkg/test/e2e/sensor/sensor.go b/pkg/test/e2e/sensor/sensor.go index dd04c153..2eaa95b3 100644 --- a/pkg/test/e2e/sensor/sensor.go +++ b/pkg/test/e2e/sensor/sensor.go @@ -31,6 +31,7 @@ import ( ) const ( + LocalBinFile = "mint-sensor" // Intentionally duplicating values here since to make sure a refactoing // of the paths on the sensor side won't be unnoticed. CommandsFileName = "commands.json" @@ -129,9 +130,13 @@ func NewSensor( imageName string, opts ...sensorOpt, ) (*Sensor, error) { - sensorExePath, err := exec.LookPath(sensor.LocalBinFile) - if err != nil { - return nil, fmt.Errorf("cannot locate %s executable on the host system", sensor.LocalBinFile) + sensorExePath := os.Getenv("DSLIM_SENSOR_PATH") + if sensorExePath == "" { + var err error + sensorExePath, err = exec.LookPath(sensor.LocalBinFile) + if err != nil { + return nil, fmt.Errorf("cannot locate %s executable on the host system", sensor.LocalBinFile) + } } if err := imagePull(ctx, imageName); err != nil { diff --git a/scripts/src.build.sensor.sh b/scripts/src.build.sensor.sh new file mode 100755 index 00000000..fb0ac788 --- /dev/null +++ b/scripts/src.build.sensor.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -e + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +BDIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" + +BUILD_TIME="$(date -u '+%Y-%m-%d_%I:%M:%S%p')" +TAG="current" +REVISION="current" +if hash git 2>/dev/null && [ -e $BDIR/.git ]; then + TAG="$(git describe --tags --always)" + REVISION="$(git rev-parse HEAD)" +fi + +LD_FLAGS="-s -w -X github.com/mintoolkit/mint/pkg/version.appVersionTag=${TAG} -X github.com/mintoolkit/mint/pkg/version.appVersionRev=${REVISION} -X github.com/mintoolkit/mint/pkg/version.appVersionTime=${BUILD_TIME}" + +go generate github.com/mintoolkit/mint/pkg/appbom + +BINDIR="${BDIR}/bin" +mkdir -p "$BINDIR" +rm -f "${BINDIR}/mint-sensor" + +CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="${LD_FLAGS}" -mod=vendor -o "${BINDIR}/mint-sensor" "${BDIR}/cmd/mint-sensor/main.go"