Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
223 lines (191 loc) · 11.8 KB
/
Copy pathMakefile
File metadata and controls
223 lines (191 loc) · 11.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
SHELL := /bin/bash
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
LDFLAGS := -X main.version=$(VERSION)
E2E_CLUSTER ?= runtime-agent-e2e
SMOKE_SECONDS ?= 5
IMAGE ?= runtime-agent
IMAGE_TAG ?= $(VERSION)
SAMPLE_IMAGE ?= rebuildstack-e2e-goworkload:latest
# A shell-bearing image loaded into kind as a sidecar so the inventory e2e can
# read the controller's spool (the agent image is distroless — no shell).
SPOOL_READER_IMAGE ?= busybox:1.37
# The scanners, pinned like everything else this repository builds with
# (ADR 0085). CI runs these exact versions.
SYFT_IMAGE ?= anchore/syft:v1.52.0
GRYPE_IMAGE ?= anchore/grype:v0.119.0
.PHONY: build test lint chart-lint proto proto-lint vulncheck tidy clean cluster-up cluster-down e2e smoke image sample-image kind-load node-e2e inventory-e2e restart-e2e restarts-e2e lifecycle-e2e policy-e2e watch-e2e profile-gate-e2e profile-capture-e2e identity-e2e
build: ## Build the agent binary into bin/
go build -ldflags '$(LDFLAGS)' -o bin/agent ./cmd/agent
test: ## Run all tests with the race detector, and type-check the e2e-tagged ones
go test -race ./...
# The e2e tests are behind a build tag, so `go test ./...` never compiles
# them and a changed signature can rot there unnoticed. Type-check them on
# every run; they still only execute against a kind cluster.
go vet -tags e2e ./...
lint: ## Run golangci-lint
golangci-lint run
vulncheck: ## Scan for known vulnerabilities reachable from this code, standard library included
# Fails only on vulnerabilities the code actually calls. A finding in a
# module we require but never reach is reported and does not fail — which is
# the right line: `golang.org/x/crypto/openpgp` arrives through helm, is
# declared unmaintained with no fixed version, and is not linked into the
# agent binary at all.
#
# This exists because Dependabot answers a different question. It walks the
# module graph, so it found one transitive dependency that is not in the
# shipped image, and could not see sixteen standard-library vulnerabilities
# that were (ADR 0038).
go tool govulncheck ./...
proto: ## Regenerate the Go types from the payload schema (needs buf on PATH)
buf generate
proto-lint: ## Lint the payload schema and check it against main for breaking changes
buf lint
# Field numbers are never reused and removed ones are reserved; this is what
# enforces it, and with it the N-2 window in backend-requirements.md §6.
@if git ls-tree -r --name-only origin/main -- proto | grep -q .; then \
buf breaking --against '.git#ref=origin/main'; \
else \
echo "main carries no schema: this change is the one introducing it."; \
fi
chart-lint: ## Lint the Helm chart with the helm CLI, once per install profile
go tool helm lint charts/runtime-agent --set profile=metrics-only
go tool helm lint charts/runtime-agent --set profile=inventory
go tool helm lint charts/runtime-agent \
--set profile=ebpf --set profiling.allowedModulePrefixes={example.com/app}
tidy: ## Sync go.mod/go.sum
go mod tidy
cluster-up: ## Create the disposable kind cluster for e2e
go tool kind create cluster --name $(E2E_CLUSTER) --wait 120s
cluster-down: ## Delete the e2e kind cluster
go tool kind delete cluster --name $(E2E_CLUSTER)
e2e: ## Run e2e tests against the kind cluster (see cluster-up); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
set -o pipefail; E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) go test -tags e2e -count=1 -timeout 30m -v ./test/e2e/ 2>&1 \
| tee test/e2e/logs/e2e-$$(date +%Y%m%d-%H%M%S).log
restart-e2e: ## Run the usage pipeline in kind, stop it mid-window, start it again over the same spool (ADR 0072); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
set -o pipefail; E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
go test -tags e2e -count=1 -timeout 15m -v ./test/e2e/ -run TestARestartResumesTheOpenWindowFromTheSpool 2>&1 \
| tee test/e2e/logs/restart-e2e-$$(date +%Y%m%d-%H%M%S).log
smoke: build ## Run the agent for SMOKE_SECONDS against the kind cluster (see cluster-up); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
@kubeconfig=$$(mktemp); \
trap 'rm -f "$$kubeconfig"' EXIT; \
go tool kind export kubeconfig --name $(E2E_CLUSTER) --kubeconfig "$$kubeconfig" || exit 1; \
log=test/e2e/logs/smoke-$$(date +%Y%m%d-%H%M%S).log; \
KUBECONFIG=$$kubeconfig ./bin/agent >/dev/null 2>"$$log" & pid=$$!; \
sleep $(SMOKE_SECONDS); kill -TERM $$pid; wait $$pid; \
echo "smoke log: $$log"
image: ## Build the agent container image (controller + node roles, one binary)
docker build -t $(IMAGE):$(IMAGE_TAG) --build-arg VERSION=$(VERSION) .
image-scan: image ## Catalogue the agent image and scan it, the way CI does (ADR 0085)
@mkdir -p bin
docker save $(IMAGE):$(IMAGE_TAG) -o bin/image.tar
docker run --rm -v "$(PWD)/bin:/w" $(SYFT_IMAGE) docker-archive:/w/image.tar -o json > bin/sbom.json
docker run --rm -v "$(PWD):/w" -w /w $(GRYPE_IMAGE) sbom:/w/bin/sbom.json -o table --show-suppressed
docker run --rm -v "$(PWD):/w" -w /w $(GRYPE_IMAGE) sbom:/w/bin/sbom.json --fail-on high --only-fixed
sample-image: ## Build the e2e "known Go process" workload image
docker build -t $(SAMPLE_IMAGE) test/e2e/sample
kind-load: image sample-image ## Load the agent and sample images into the kind cluster
go tool kind load docker-image $(IMAGE):$(IMAGE_TAG) $(SAMPLE_IMAGE) --name $(E2E_CLUSTER)
node-e2e: kind-load ## Deploy the node DaemonSet in kind and assert Go-binary detection; log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SAMPLE_IMAGE=$(SAMPLE_IMAGE) \
go test -tags e2e -count=1 -timeout 15m -v ./test/e2e/ -run TestNodeScanner 2>&1 \
| tee test/e2e/logs/node-e2e-$$(date +%Y%m%d-%H%M%S).log
inventory-e2e: kind-load ## Deploy controller + node DaemonSet + sample in kind and assert the go_inventory payload in the controller spool; log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SAMPLE_IMAGE=$(SAMPLE_IMAGE) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 20m -v ./test/e2e/ -run TestGoInventoryEndToEnd 2>&1 \
| tee test/e2e/logs/inventory-e2e-$$(date +%Y%m%d-%H%M%S).log
collection-e2e: kind-load ## Deploy the controller in kind and assert the loopback listing names what the filters excluded, and that no other pod can read it (ADR 0084); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 15m -v ./test/e2e/ -run TestTheCollectionListingNamesWhatWasExcluded 2>&1 \
| tee test/e2e/logs/collection-e2e-$$(date +%Y%m%d-%H%M%S).log
policy-e2e: kind-load ## Deploy the controller in kind and assert job_runs, deployment_revisions, workload_policy and cluster_policy in the spool — including that the widened ClusterRole grants what ADR 0032 says; log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 20m -v ./test/e2e/ -run TestPolicyAndJournalsEndToEnd 2>&1 \
| tee test/e2e/logs/policy-e2e-$$(date +%Y%m%d-%H%M%S).log
profile-gate-e2e: kind-load ## Deploy the ebpf node variant in kind and assert the eBPF gate refuses gracefully while the scanner keeps running; log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
go test -tags e2e -count=1 -timeout 15m -v ./test/e2e/ -run TestEBPFGateRefusesGracefully 2>&1 \
| tee test/e2e/logs/profile-gate-e2e-$$(date +%Y%m%d-%H%M%S).log
identity-e2e: kind-load ## Deploy controller + node DaemonSet in kind and assert a real node token cannot speak for another node, and that a token not projected into a pod is refused (ADR 0040); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 20m -v ./test/e2e/ -run 'TestANodeCannotSpeakForAnotherNode|TestATokenThatWasNotProjectedIntoAPodIsRefused' 2>&1 \
| tee test/e2e/logs/identity-e2e-$$(date +%Y%m%d-%H%M%S).log
profile-capture-e2e: kind-load ## Deploy controller + ebpf node + CPU-hot sample in kind and assert the full eBPF capture→filter→ship→spool path (ADR 0011); skips where the host cannot run eBPF (no BTF / no CAP_BPF, e.g. Docker Desktop); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SAMPLE_IMAGE=$(SAMPLE_IMAGE) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 20m -v ./test/e2e/ -run TestEBPFCaptureEndToEnd 2>&1 \
| tee test/e2e/logs/profile-capture-e2e-$$(date +%Y%m%d-%H%M%S).log
restarts-e2e: kind-load ## Deploy the controller in kind next to a crash-looping workload and assert both the container_restarts windows (ADR 0020) and the restart_counters reading a late-arriving agent recovers (ADR 0034); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 25m -v ./test/e2e/ \
-run 'TestContainerRestartsEndToEnd|TestRestartCountersCarryTheHistoryTheAgentDidNotWatch' 2>&1 \
| tee test/e2e/logs/restarts-e2e-$$(date +%Y%m%d-%H%M%S).log
watch-e2e: kind-load ## Deny the pods grant, then revoke a policy grant from a running agent, and assert the first stops the agent while the second only degrades its payload (ADR 0035); slow by nature — an established watch is re-authorized only when client-go re-establishes it, every 5–10 minutes; log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 45m -v ./test/e2e/ \
-run 'TestAnAgentDeniedAGatingPermissionStopsInsteadOfWaitingForever|TestAPermissionRevokedFromTheRunningAgentReachesThePayload' 2>&1 \
| tee test/e2e/logs/watch-e2e-$$(date +%Y%m%d-%H%M%S).log
lifecycle-e2e: kind-load ## Deploy the controller in kind, stage an unschedulable pod and a scheduler preemption, and assert both reach the payloads (ADR 0021); log goes to test/e2e/logs/
@mkdir -p test/e2e/logs
docker pull $(SPOOL_READER_IMAGE)
go tool kind load docker-image $(SPOOL_READER_IMAGE) --name $(E2E_CLUSTER)
set -o pipefail; \
E2E_KUBE_CONTEXT=kind-$(E2E_CLUSTER) \
E2E_AGENT_IMAGE=$(IMAGE):$(IMAGE_TAG) \
E2E_SPOOL_READER_IMAGE=$(SPOOL_READER_IMAGE) \
go test -tags e2e -count=1 -timeout 20m -v ./test/e2e/ -run TestPodLifecycleEndToEnd 2>&1 \
| tee test/e2e/logs/lifecycle-e2e-$$(date +%Y%m%d-%H%M%S).log
clean:
rm -rf bin