tetragon - Tetragon 是一种实时安全和可观察性工具。这意味着 Tetragon 直接在 eBPF 中应用策略和过滤。

Created at: 2022-03-23 18:25:36
Language: C
License: Apache-2.0

许可证


Cilium的新型Tetragon组件可实现强大的实时,基于eBPF的安全可观察性和运行时实施。

Tetragon 检测并能够实时响应安全重大事件,例如

  • 流程执行事件
  • 对权限和功能的更改
  • I/O 活动,包括网络和文件访问

当在 Kubernetes 环境中使用时,Tetragon 是 Kubernetes 感知的 - 也就是说,它理解 Kubernetes 身份,如命名空间、pod 等 - 以便可以针对单个工作负载配置安全事件检测。

功能概述

eBPF 实时

Tetragon是一种实时安全性和可观察性工具。这意味着Tetragon直接在eBPF中应用策略和过滤。在安全上下文中,这可以阻止操作的发生,而不是在事后观察操作并对其做出 React (例如,检测到的恶意行为)。在 React 情况下,攻击者可能已经操纵了关键数据,窃取了机密,或以其他方式破坏了计算机。通过在 eBPF 中内联应用策略,恶意操作在发生之前就被阻止。

对于可观察性用例,直接在内核中应用筛选器可显著降低观察开销。通过避免代价高昂的上下文切换和唤醒,特别是对于高频事件,如发送、读取或写入操作,eBPF 减少了所需的资源。相反,Tetragon在eBPF中提供了丰富的过滤器(文件,套接字,二进制名称,命名空间/功能等),允许用户在其特定上下文中指定重要和相关的事件,并仅将这些事件传递给用户空间代理。

eBPF 灵活性

Tetragon可以挂接到Linux内核中的任何函数,并过滤其参数,返回值,Tetragon收集的有关进程的相关元数据(例如,可执行文件名称),文件和其他属性。通过编写跟踪策略,用户可以解决各种安全性和可观察性用例。我们在存储库中提供了许多示例,并在下面的“入门指南”中突出显示了一些示例,但鼓励用户创建与其用例匹配的新策略。这些例子就是这样,跳出一些点,然后用户可以使用这些点来创建新的和特定的策略部署,甚至可能跟踪我们没有考虑的内核功能。有关跟踪哪些函数以及应用了哪些筛选器的任何细节都没有在引擎本身中进行硬编码。

至关重要的是,Tetragon允许在内核深处进行钩子,其中数据结构无法被用户空间应用程序操纵,从而避免了系统调用跟踪的常见问题,即数据被错误读取,被攻击者恶意更改或由于页面错误和其他用户/内核边界错误而丢失。

许多Tetragon开发人员也是内核开发人员。通过利用此知识库,Tetragon 创建了一组跟踪策略,可以解决许多常见的可观察性和安全性用例。

eBPF 内核感知

Tetragon通过eBPF可以访问Linux内核状态。然后,Tetragon 可以将此内核状态与 Kubernetes 感知或用户策略相结合,以创建由内核实时执行的规则。这允许批注和强制实施进程命名空间和功能、进程套接字、文件名的进程文件描述符等。例如,当应用程序更改其权限时,我们可以创建一个策略来触发警报,甚至在它有机会完成系统调用并可能运行其他系统调用之前终止进程。

本地发展

有关本地开发的入门,请参阅开发指南

快速入门指南

本快速入门指南使用 Kind 群集和基于 helm 的安装来提供一种简单的方法来获取 Tetragon 和生成的事件的实践经验。这些事件包括监视进程执行、网络套接字和文件访问,以查看哪些二进制文件正在执行、建立网络连接或写入敏感文件。

在这种情况下,我们将安装一个演示应用程序,

  • 观察 Kubernetes 工作负载内发生的所有流程执行
  • 检测文件访问和写入
  • 观察 Kubernetes 工作负载正在建立的网络连接
  • 检测 Kubernetes 工作负载中的特权进程

虽然,我们在本指南中使用了 Kubernetes Kind 集群,但用户也可以在其他 Kubernetes 平台、裸机或 VM 环境中应用相同的概念。

要求

基本内核应该支持 BTF,或者 BTF 文件应该放在 Tetragon 可以读取它的地方。

作为参考,下面的示例使用此 Vagrantfile,我们使用默认值选项创建了 Kind 群集。

创建集群

使用 Kind 或 GKE 创建 Kubernetes 集群。

运行以下命令创建 Kubernetes 集群:

kind create cluster

断续器

执行以下命令创建GKE集群:

export NAME="$(whoami)-$RANDOM"
gcloud container clusters create "${NAME}" \
  --zone us-west2-a \
  --release-channel rapid \
  --num-nodes 1 \

部署 Tetragon

要安装和部署 Tetragon,请从 git 存储库运行以下命令。请注意,如果运行上面的 Vagrant 文件,存储库将与 VM 同步。

helm install tetragon -n kube-system ./install/kubernetes/
kubectl rollout status -n kube-system ds/tetragon -w

默认情况下,kube-system pod 被过滤为下面的示例,我们使用来自 Cilium 的演示部署来生成事件。

部署演示应用程序

安装 Tetragon 后,你可以使用我们的演示应用程序来探索安全性可观察性事件:

kubectl create -f https://raw.githubusercontent.com/cilium/cilium/v1.11/examples/minikube/http-sw-app.yaml

在继续之前,请验证所有 Pod 是否都已启动并运行 - 某些 Pod 可能需要几秒钟才能满足所有依赖项:

kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
deathstar-6c94dcc57b-7pr8c   1/1     Running   0          10s
deathstar-6c94dcc57b-px2vw   1/1     Running   0          10s
tiefighter                   1/1     Running   0          10s
xwing                        1/1     Running   0          10s

探索安全可观察性事件

在 Tetragon 和演示应用程序启动并运行后,你可以以不同的方式检查 Tetragon 生成的安全性和可观察性事件。

原始 JSON 事件

第一种方法是观察 stdout 容器日志中的原始 json 输出:

kubectl logs -n kube-system ds/tetragon -c export-stdout -f

注意:如果你正在运行多个 Pod,则上面的命令将仅打印其中一个 Pod 的日志。要打印出所有 Pod 上的日志,你需要使用过滤器/选择器,例如:

tetragon
tetragon
-l app.kubernetes.io/name=tetragon

kubectl logs -n kube-system -l app.kubernetes.io/name=tetragon -c export-stdout -f 

原始 JSON 事件提供 Kubernetes API、身份元数据和操作系统级别进程可见性,以了解已执行的二进制文件、其父级和执行时间。

四边形 CLI

第二种方法是使用 Tetragon CLI 漂亮地打印事件。该工具还允许按进程、pod 和其他字段进行筛选。

你可以通过以下命令下载并安装它

wget https://github.com/cilium/tetragon/releases/download/tetragon-cli/tetragon-linux-386.tar.gz
tar -zxvf tetragon-linux-386.tar.gz -C /usr/local/bin/

要开始打印事件,请运行:

kubectl logs -n kube-system ds/tetragon -c export-stdout -f | tetragon observe

Tetragon能够观察到几个事件,在这里我们提供了一些可以用作起点的小样本:

流程执行

第一个用例是监视进程执行,这可以通过 Tetragon 和 JSON 事件来观察。这些事件包含流程的整个生命周期,从分叉/执行到退出,包括元数据,例如:

process_exec
process_exit

  • 二进制名称:定义可执行文件的名称
  • 父进程:帮助识别进程执行异常(例如,如果 nodejs 应用程序分叉了一个 shell,这是可疑的)
  • 命令行参数:定义程序运行时行为
  • 当前工作目录:帮助识别临时文件夹中隐藏的恶意软件执行,这是恶意软件中使用的常见模式
  • Kubernetes 元数据:包含 pod、标签和 Kubernetes 命名空间,这对于识别服务所有者至关重要,尤其是在多租户环境中
  • exec_id:唯一的流程标识符,用于关联流程的所有记录活动

作为第一步,让我们开始监视 Pod 中的事件:

xwing

kubectl logs -n kube-system ds/tetragon -c export-stdout -f | tetragon observe --namespace default --pod xwing

然后在另一个终端中,让我们进入 pod 并执行一些示例命令:

kubectl exec
xwing

kubectl exec -it xwing -- /bin/bash
whoami

如果观察,第一个终端中的输出应为:

🚀 process default/xwing /bin/bash
🚀 process default/xwing /usr/bin/whoami
💥 exit    default/xwing /usr/bin/whoami 0

在这里,你可以看到二进制名称及其参数,pod信息和返回代码。用于事件的紧凑单线视图。

有关更多详细信息,请使用原始 JSON 事件获取详细信息,你可以通过执行以下命令来停止 Tetragon CLI 并解析文件:

Crl-C
tetragon.log

kubectl logs -n kube-system ds/tetragon -c export-stdout -f | jq 'select(.process_exec.process.pod.name=="xwing" or .process_exit.process.pod.name=="xwing")'

示例和事件可以是:

process_exec
process_exit

处理执行事件

{
  "process_exec": {
    "process": {
      "exec_id": "a2luZC1jb250cm9sLXBsYW5lOjExNDI4NjE1NjM2OTAxOjUxNTgz",
      "pid": 51583,
      "uid": 0,
      "cwd": "/",
      "binary": "/usr/bin/whoami",
      "arguments": "--version",
      "flags": "execve rootcwd clone",
      "start_time": "2022-05-11T12:54:45.615Z",
      "auid": 4294967295,
      "pod": {
        "namespace": "default",
        "name": "xwing",
        "container": {
          "id": "containerd://1fb931d2f6e5e4cfdbaf30fdb8e2fdd81320bdb3047ded50120a4f82838209ce",
          "name": "spaceship",
          "image": {
            "id": "docker.io/tgraf/netperf@sha256:8e86f744bfea165fd4ce68caa05abc96500f40130b857773186401926af7e9e6",
            "name": "docker.io/tgraf/netperf:latest"
          },
          "start_time": "2022-05-11T10:07:33Z",
          "pid": 50
        }
      },
      "docker": "1fb931d2f6e5e4cfdbaf30fdb8e2fdd",
      "parent_exec_id": "a2luZC1jb250cm9sLXBsYW5lOjkwNzkyMjU2MjMyNjk6NDM4NzI=",
      "refcnt": 1
    },
    "parent": {
      "exec_id": "a2luZC1jb250cm9sLXBsYW5lOjkwNzkyMjU2MjMyNjk6NDM4NzI=",
      "pid": 43872,
      "uid": 0,
      "cwd": "/",
      "binary": "/bin/bash",
      "flags": "execve rootcwd clone",
      "start_time": "2022-05-11T12:15:36.225Z",
      "auid": 4294967295,
      "pod": {
        "namespace": "default",
        "name": "xwing",
        "container": {
          "id": "containerd://1fb931d2f6e5e4cfdbaf30fdb8e2fdd81320bdb3047ded50120a4f82838209ce",
          "name": "spaceship",
          "image": {
            "id": "docker.io/tgraf/netperf@sha256:8e86f744bfea165fd4ce68caa05abc96500f40130b857773186401926af7e9e6",
            "name": "docker.io/tgraf/netperf:latest"
          },
          "start_time": "2022-05-11T10:07:33Z",
          "pid": 43
        }
      },
      "docker": "1fb931d2f6e5e4cfdbaf30fdb8e2fdd",
      "parent_exec_id": "a2luZC1jb250cm9sLXBsYW5lOjkwNzkxODU5NTMzOTk6NDM4NjE=",
      "refcnt": 1
    }
  },
  "node_name": "kind-control-plane",
  "time": "2022-05-11T12:54:45.615Z"
}
进程退出事件

{
  "process_exit": {
    "process": {
      "exec_id": "a2luZC1jb250cm9sLXBsYW5lOjExNDI4NjE1NjM2OTAxOjUxNTgz",
      "pid": 51583,
      "uid": 0,
      "cwd": "/",
      "binary": "/usr/bin/whoami",
      "arguments": "--version",
      "flags": "execve rootcwd clone",
      "start_time": "2022-05-11T12:54:45.615Z",
      "auid": 4294967295,
      "pod": {
        "namespace": "default",
        "name": "xwing",
        "container": {
          "id": "containerd://1fb931d2f6e5e4cfdbaf30fdb8e2fdd81320bdb3047ded50120a4f82838209ce",
          "name": "spaceship",
          "image": {
            "id": "docker.io/tgraf/netperf@sha256:8e86f744bfea165fd4ce68caa05abc96500f40130b857773186401926af7e9e6",
            "name": "docker.io/tgraf/netperf:latest"
          },
          "start_time": "2022-05-11T10:07:33Z",
          "pid": 50
        }
      },
      "docker": "1fb931d2f6e5e4cfdbaf30fdb8e2fdd",
      "parent_exec_id": "a2luZC1jb250cm9sLXBsYW5lOjkwNzkyMjU2MjMyNjk6NDM4NzI="
    },
    "parent": {
      "exec_id": "a2luZC1jb250cm9sLXBsYW5lOjkwNzkyMjU2MjMyNjk6NDM4NzI=",
      "pid": 43872,
      "uid": 0,
      "cwd": "/",
      "binary": "/bin/bash",
      "flags": "execve rootcwd clone",
      "start_time": "2022-05-11T12:15:36.225Z",
      "auid": 4294967295,
      "pod": {
        "namespace": "default",
        "name": "xwing",
        "container": {
          "id": "containerd://1fb931d2f6e5e4cfdbaf30fdb8e2fdd81320bdb3047ded50120a4f82838209ce",
          "name": "spaceship",
          "image": {
            "id": "docker.io/tgraf/netperf@sha256:8e86f744bfea165fd4ce68caa05abc96500f40130b857773186401926af7e9e6",
            "name": "docker.io/tgraf/netperf:latest"
          },
          "start_time": "2022-05-11T10:07:33Z",
          "pid": 43
        }
      },
      "docker": "1fb931d2f6e5e4cfdbaf30fdb8e2fdd",
      "parent_exec_id": "a2luZC1jb250cm9sLXBsYW5lOjkwNzkxODU5NTMzOTk6NDM4NjE="
    }
  },
  "node_name": "kind-control-plane",
  "time": "2022-05-11T12:54:45.616Z"
}

对于其余的用例,我们将使用 Tetragon CLI 来提供输出。

文件访问

第二个用例是文件访问,这可以通过 Tetragon JSON 事件来观察。通过使用 kprobe 挂接点,这些事件能够观察 Linux 内核中的任意内核调用和文件描述符,使你能够监视进程在其整个生命周期中打开、读取、写入和关闭的每个文件。为了能够观察任意内核调用,Tetragon 可以使用 TracingPolicies 进行扩展。

process_kprobe

TracingPolicy 是一个用户可配置的 Kubernetes 自定义资源定义 (CRD),它允许用户跟踪内核中的任意事件并定义要对匹配执行的操作。对于没有 Kubernetes 的裸机或 VM 用例,可以使用 YAML 配置文件。

在这个例子中,我们可以监控 Kubernetes 工作负载中的进程是否在目录中执行打开、关闭、读取或写入。如果需要,该策略可以进一步指定其他 dirs 或特定文件。

/etc/

作为第一步,让我们应用以下跟踪策略:

kubectl apply -f ./crds/examples/sys_write_follow_fd_prefix.yaml

作为第二步,让我们开始监视 Pod 中的事件:

xwing

kubectl logs -n kube-system ds/tetragon -c export-stdout -f | tetragon observe --namespace default --pod xwing

在另一个终端中,进入 pod:

kubectl exec
xwing

kubectl exec -it xwing -- /bin/bash

并编辑文件:

/etc/passwd

vi /etc/passwd

如果观察,第一个终端中的输出应为:

🚀 process default/xwing /usr/bin/vi /etc/passwd
📬 open    default/xwing /usr/bin/vi /etc/passwd
📚 read    default/xwing /usr/bin/vi /etc/passwd 1269 bytes
📪 close   default/xwing /usr/bin/vi /etc/passwd
📬 open    default/xwing /usr/bin/vi /etc/passwd
📝 write   default/xwing /usr/bin/vi /etc/passwd 1277 bytes
💥 exit    default/xwing /usr/bin/vi /etc/passwd 0

请注意,由于内核过滤中的 eBPF,仅为 '/etc/' 文件生成打开和关闭。默认 CRD 还会过滤与 pod init 进程关联的事件,以过滤 Pod 启动时的 init 噪音。

与前面的示例类似,查看 JSON 事件可提供有关该事件的其他数据。除了来自 exec 事件的 Kubernetes 标识和进程元数据之外,事件还包含观察到的系统调用的参数。在上述情况下,它们是

process_kprobe

  • path
    :观察到的文件路径
  • bytes_arg
    :以 base64 编码的观察到文件的内容
  • size_arg
    :观察到文件的大小(以字节为单位)

禁用跟踪策略运行:

kubectl delete -f ./crds/examples/sys_write_follow_fd_prefix.yaml

Network Observability

To view TCP connect events apply the example TCP connect tracing policy.

kubectl apply -f ./crds/examples/tcp-connect.yaml

To start monitoring events in the xwing pod run the observer,

kubectl logs -n kube-system ds/tetragon -c export-stdout -f | tetragon observe --namespace default --pod xwing

In another terminal, start generate a TCP connection. Here we use curl.

kubectl exec -it xwing -- curl http://cilium.io

The output in the first terminal will capture the new connect and write,

🚀 process default/xwing /usr/bin/curl http://cilium.io
🔌 connect default/xwing /usr/bin/curl tcp 10.244.0.6:34965 -> 104.198.14.52:80
📤 sendmsg default/xwing /usr/bin/curl tcp 10.244.0.6:34965 -> 104.198.14.52:80 bytes 73
🧹 close   default/xwing /usr/bin/curl tcp 10.244.0.6:34965 -> 104.198.14.52:80
💥 exit    default/xwing /usr/bin/curl http://cilium.io 0

To disable the TracingPolicy run:

kubectl delete -f ./crds/examples/tcp-connect.yaml

Privileged Execution

Tetragon also provides the ability to check process capabilities and kernel namespaces.

As a first step let's enable visibility to capability and namespace changes via the configmap by setting and from to

enable-process-cred
enable-process-ns
false
true

kubectl edit cm -n kube-system tetragon-config
# change "enable-process-cred" from "false" to "true"
# change "enable-process-ns" from "false" to "true"
# then save and exit

Restart the Tetragon daemonset:

kubectl rollout restart -n kube-system ds/tetragon

As a second step, let's start monitoring the Security Observability events from the privileged workload:

test-pod

kubectl logs -n kube-system ds/tetragon -c export-stdout -f | tetragon observe --namespace default --pod test-pod

在另一个终端中,让我们应用特权 PodSpec:

kubectl apply -f ./testdata/specs/testpod.yaml

如果在第一个终端中观察输出,可以看到容器以 以下列开头:

CAP_SYS_ADMIN

🚀 process default/test-pod /bin/sleep 365d                🛑 CAP_SYS_ADMIN
🚀 process default/test-pod /usr/bin/jq -r .bundle         🛑 CAP_SYS_ADMIN
🚀 process default/test-pod /usr/bin/cp /kind/product_name /kind/product_uuid /run/containerd/io.containerd.runtime.v2.task/k8s.io/7c7e513cd4d506417bc9d97dd9af670d94d9e84161c8c8 fdc9fa3a678289a59/rootfs/ 🛑 CAP_SYS_ADMIN

BTF 要求

Tetragon存储库提供了一个Vagrantfile,可用于安装一个Vagrant盒子,用于运行具有BTF要求的Tetragon。其他VM解决方案也可以工作,许多常见的Linux发行版现在都附带BTF,不需要任何额外的工作。要检查是否在 Linux 系统上启用了 BTF,请检查标准位置中的 BTF 文件,

$ ls /sys/kernel/btf/

要与流浪汉一起运行,我们提供了一个启用了所需组件的标准流浪汉文件。只需运行,

 $ vagrant up
 $ vagrant ssh

这应该足以创建 Kind 集群并运行 Tetragon。

社区

松弛

加入 Tetragon Slack 频道,与开发人员、维护人员和其他用户聊天。这是提出问题和分享经验的良好第一站。