Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 16 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ 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

.PHONY: build test lint tidy clean cluster-up cluster-down e2e smoke image sample-image kind-load node-e2e
.PHONY: build test lint tidy clean cluster-up cluster-down e2e smoke image sample-image kind-load node-e2e inventory-e2e

build: ## Build the agent binary into bin/
go build -ldflags '$(LDFLAGS)' -o bin/agent ./cmd/agent
Expand Down Expand Up @@ -63,5 +66,17 @@ node-e2e: kind-load ## Deploy the node DaemonSet in kind and assert Go-binary de
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 15m -v ./test/e2e/ -run TestGoInventoryEndToEnd 2>&1 \
| tee test/e2e/logs/inventory-e2e-$$(date +%Y%m%d-%H%M%S).log

clean:
rm -rf bin
147 changes: 147 additions & 0 deletions deploy/controller.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Controller — raw manifest for the node-intake receiver (ADR 0010). No Helm
# chart lives in this repo yet; this file is what the e2e deploys and a reference
# for the eventual chart. It is deliberately scoped to what the node→controller
# inventory path needs: the read RBAC the collectors use (security.md §4), the
# read-only JWKS discovery grant for local token validation (no TokenReview, no
# write verb), the receiver Service, and a spool volume. It does NOT include the
# backend enrollment/identity machinery (ADR 0005/0008) — that is a later slice.
---
apiVersion: v1
kind: Namespace
metadata:
name: runtime-agent
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: runtime-agent-controller
namespace: runtime-agent
---
# The controller's access is read-only (security.md §4). The two nonResourceURL
# GETs are OIDC discovery + JWKS, used to validate node tokens locally — a read,
# never a write, and specifically NOT `create tokenreviews`.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: runtime-agent-controller
rules:
- apiGroups: [""]
resources: [pods, namespaces, nodes]
verbs: [get, list, watch]
- apiGroups: [""]
resources: [nodes/proxy]
verbs: [get]
- apiGroups: [apps]
resources: [replicasets, deployments, statefulsets, daemonsets]
verbs: [get, list, watch]
- apiGroups: [batch]
resources: [jobs, cronjobs]
verbs: [get, list, watch]
- nonResourceURLs: ["/openid/v1/jwks", "/.well-known/openid-configuration"]
verbs: [get]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: runtime-agent-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: runtime-agent-controller
subjects:
- kind: ServiceAccount
name: runtime-agent-controller
namespace: runtime-agent
---
apiVersion: v1
kind: ConfigMap
metadata:
name: runtime-agent-controller
namespace: runtime-agent
data:
config.yaml: |
spool:
dir: /var/spool/runtime-agent
nodeIntake:
enabled: true
listenAddress: ":8080"
# Must match the audience the node DaemonSet's projected token requests.
audience: rebuildstack-controller
# Pin the accepted caller to the node role's ServiceAccount.
expectedSubject: "system:serviceaccount:runtime-agent:runtime-agent-node"
---
apiVersion: v1
kind: Service
metadata:
name: runtime-agent-controller
namespace: runtime-agent
labels:
app.kubernetes.io/name: runtime-agent
app.kubernetes.io/component: controller
spec:
selector:
app.kubernetes.io/name: runtime-agent
app.kubernetes.io/component: controller
ports:
- name: node-intake
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: runtime-agent-controller
namespace: runtime-agent
labels:
app.kubernetes.io/name: runtime-agent
app.kubernetes.io/component: controller
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: runtime-agent
app.kubernetes.io/component: controller
template:
metadata:
labels:
app.kubernetes.io/name: runtime-agent
app.kubernetes.io/component: controller
spec:
serviceAccountName: runtime-agent-controller
containers:
- name: controller
image: runtime-agent:latest
args:
- -config
- /etc/runtime-agent/config.yaml
ports:
- name: node-intake
containerPort: 8080
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
volumeMounts:
- name: config
mountPath: /etc/runtime-agent
readOnly: true
- name: spool
mountPath: /var/spool/runtime-agent
volumes:
- name: config
configMap:
name: runtime-agent-controller
# emptyDir by default (ADR 0007): unshipped payloads are loss-harmless.
- name: spool
emptyDir: {}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ require (
github.com/go-openapi/swag v0.23.0 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/moby/spdystream v0.5.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
Expand All @@ -55,6 +57,7 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.140.0 // indirect
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
k8s.io/streaming v0.36.3 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/kind v0.32.0 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXy
al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -35,6 +37,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
Expand All @@ -53,6 +57,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y=
github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down Expand Up @@ -136,6 +142,8 @@ k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hk
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0=
k8s.io/kubelet v0.36.3 h1:dRzEnhHk35Opy6wjWR4YBcN5RI9lB2npUY37TghFuPU=
k8s.io/kubelet v0.36.3/go.mod h1:4USFGr21Ioka+b964Beq0NvV5b5aca3RWJ1/kfq+RLw=
k8s.io/streaming v0.36.3 h1:9rAaqBk0C0Pc7+/fqGekj07NV+/Xrew58p647A0JT8w=
k8s.io/streaming v0.36.3/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
Expand Down
Loading