Runtime security with Tetragon
Tetragon is Cilium’s open-source eBPF runtime security agent. It watches the kernel on each node and reports what processes do: every process start, and every match of a TracingPolicy you apply (a file read, a privilege change, a network connection). Shield360 reads those events from each node, shows them with your logs, and raises detections from them.
What you get:
- Every process start in your pods and on your nodes: the binary, its arguments, its parent, and the pod, container, image and workload it ran in.
- Policy matches from Shield360’s baseline policies (below), or your own.
- Detections, ready to turn on: Sensitive file read on a node, Privilege escalation on a node, Shell started in a container and Burst of outbound connections from a node.
Set it up
Section titled “Set it up”-
Install Tetragon with its Helm chart, as the Tetragon docs describe:
Terminal window helm repo add cilium https://helm.cilium.iohelm install tetragon cilium/tetragon -n kube-systemIt writes its events to
/var/run/cilium/tetragon/tetragon.logon each node. -
Apply Shield360’s baseline policies. Your Shield360 server serves all three as one YAML file (replace
https://app.shield360.aiwith your own address if you self-host):Terminal window kubectl apply -f https://app.shield360.ai/api/downloads/tetragon-policiesTo apply only some, name them with
policy(comma-separated):Terminal window kubectl apply -f "https://app.shield360.ai/api/downloads/tetragon-policies?policy=shield360-sensitive-files,shield360-privilege-escalation"Policy Reports shield360-sensitive-filesReads of /etc/shadow,/etc/gshadow,/etc/sudoersand root’s SSH, AWS, Kubernetes and gcloud credentials, except by sshd, sudo, su, passwd and the PAM password checkershield360-privilege-escalationsetuid(0)andsetgid(0), except by sudo, su, login, sshd, cron and systemdshield360-outbound-connectionsTCP connections to public addresses, and to the cloud metadata address. Private, loopback and link-local ranges are left out Review a policy before you apply it, or save it and apply your own copy:
shield360-sensitive-files
# SHIELD: runtime security — reads of protected files on the node or in any pod.# Reported as process_kprobe events with policy_name shield360-sensitive-files;# Shield360's "Sensitive file read on a node" detection fires on any match.# The tools that read these files as part of their job (sshd, sudo, su,# passwd, the PAM password checker) are left out. Service-account tokens are# not watched by default: every app that talks to the Kubernetes API reads# its own at start; add the path if you want those reads reported too.apiVersion: cilium.io/v1alpha1kind: TracingPolicymetadata:name: shield360-sensitive-filesspec:kprobes:- call: security_file_permissionsyscall: falsereturn: trueargs:- index: 0type: file- index: 1type: intreturnArg:index: 0type: intreturnArgAction: Postselectors:- matchArgs:- index: 0operator: Prefixvalues:- /etc/shadow- /etc/gshadow- /etc/sudoers- /root/.ssh- /root/.aws- /root/.kube- /root/.config/gcloud- index: 1operator: Maskvalues:- "4" # MAY_READmatchBinaries:- operator: NotInvalues:- /usr/sbin/sshd- /usr/bin/sudo- /usr/bin/su- /bin/su- /usr/bin/passwd- /usr/sbin/unix_chkpwdshield360-privilege-escalation
# SHIELD: runtime security — a process becoming root. Reported as# process_kprobe events with policy_name shield360-privilege-escalation;# Shield360's "Privilege escalation on a node" detection fires on any match.# setuid(0) and setgid(0) by the tools whose job that is (sudo, su, login,# sshd, cron, systemd) are left out.apiVersion: cilium.io/v1alpha1kind: TracingPolicymetadata:name: shield360-privilege-escalationspec:kprobes:- call: sys_setuidsyscall: trueargs:- index: 0type: intselectors:- matchArgs:- index: 0operator: Equalvalues:- "0"matchBinaries: &trusted- operator: NotInvalues:- /usr/bin/sudo- /usr/bin/su- /bin/su- /usr/bin/login- /bin/login- /usr/sbin/sshd- /usr/sbin/cron- /usr/sbin/crond- /usr/lib/systemd/systemd- /lib/systemd/systemd- call: sys_setgidsyscall: trueargs:- index: 0type: intselectors:- matchArgs:- index: 0operator: Equalvalues:- "0"matchBinaries: *trustedshield360-outbound-connections
# SHIELD: runtime security — TCP connections to public addresses. Reported as# process_kprobe events with policy_name shield360-outbound-connections, with# the process, pod and destination; Shield360's "Burst of outbound connections# from a node" detection fires at 50 in 15 minutes. Private, loopback and# link-local ranges are left out except the cloud metadata address# (169.254.169.254), which a workload reading credentials from is worth seeing.# A busy cluster sends many: start with it, then narrow it to the namespaces# that should not talk to the internet (selectors: matchNamespaces).apiVersion: cilium.io/v1alpha1kind: TracingPolicymetadata:name: shield360-outbound-connectionsspec:kprobes:- call: tcp_connectsyscall: falseargs:- index: 0type: sockselectors:- matchArgs:- index: 0operator: NotDAddrvalues:- 127.0.0.0/8- 10.0.0.0/8- 172.16.0.0/12- 192.168.0.0/16- 100.64.0.0/10- ::1/128- fc00::/7- fe80::/10 -
Turn it on in the Shield360 operator chart, with system logs on:
Terminal window helm upgrade --install shield360 oci://ghcr.io/thinkfleetai/charts/shield360-operator \--version 0.3.0 -n shield360-system \--reuse-values --set systemLogs.enabled=true --set systemLogs.node.tetragon.enabled=trueThe node agent mounts Tetragon’s export directory read-only and reads
tetragon.log. If your Tetragon chart uses anotherexportDirectory, setsystemLogs.node.tetragon.exportDirectoryto match. -
Turn on the detections in Detections: the four Tetragon templates are off until you enable them.
Where the events show
Section titled “Where the events show”- Logs: pick Source: Tetragon (runtime security). Process starts are
INFOand read as the command line (/usr/bin/curl -s https://example.com/x.sh); policy matches areWARNand read as the policy, the hook, the file and the binary (shield360-sensitive-files security_file_permission /etc/shadow /usr/bin/cat). Each record carriestetragon.event,tetragon.policy,process.executable.path,process.command_args,process.parent.executable.path,k8s.namespace.name,k8s.pod.name,k8s.container.name,container.image.nameandfile.pathas fields, so the facets and search work on them. - Detections: the templates read the same records, grouped by node or by workload.
- Monitor → Detections → Runtime events (source Tetragon) and All detections: every policy match, with its policy, hook, action (reported, killed, call refused), file, binary, parent, pod, container, image, workload and node, filtered by policy, action, namespace, pod, binary or node, and counted over time by action. Process starts stay in Logs. The command line is not shown there; Open in Logs finds the event, masked like every log. Reading them needs Data protection access.
Process exits are left out (about half of Tetragon’s volume, and nothing to act on). Command lines go through the same masking as every log, so a password on a command line is masked before it is stored.
Volume
Section titled “Volume”Every process start is an event. A cluster that starts many short-lived processes (shell scripts in a loop, say) sends many. The outbound connections policy is the noisiest: once you know your normal traffic, narrow it to the namespaces that should not reach the internet with a matchNamespaces selector, or remove it.