使用 Sysdig Falco 和 Kubernetes 设置运行时容器安全监控
Falco 是一个云原生运行时安全系统,可与容器和原始 Linux 主机一起使用。它由 Sysdig 开发,是 Cloud Native Computing Foundation(云原生计算基金会)的一个 沙箱 项目。Falco 的工作方式是查看文件更改、网络活动、进程表和其他数据是否存在可疑行为,然后通过可插拔后端发送警报。通过内核模块或扩展的 BPF 探测器在主机的系统调用级别检查事件。Falco 包含一组丰富的规则,您可以编辑这些规则以标记特定的异常行为,并为正常的计算机操作创建允许列表。
在本教程中,您将学习如何在 IBM Cloud 上的 Kubernetes 集群上安装和设置 Falco、如何创建合成安全事件以及如何在 Falco 中查看事件。最后,将 Falco 连接起来,在运行时向 Slack 发送安全警报。本教程适用于标准 Kubernetes 和 Red Hat OpenShift on IBM Cloud 。
前提条件
免费试用 IBM Cloud
利用 IBM Cloud Lite 快速轻松地构建您的下一个应用程序。您的免费帐户从不过期,而且您会获得 256 MB 的 Cloud Foundry 运行时内存和包含 Kubernetes 集群的 2 GB 存储空间。了解所有细节并确定如何开始。
在开始之前,您需要准备以下软件:
您需要获取此处的源代码:
$ git clone https://gitlab.com/nibalizer/falco-iks $ cd falco-iks
验证您是否已设置并配置了 IBM Cloud Kubernetes Service 集群:
$ ibmcloud ks cluster get nibz-nightly-2019-03-29 Retrieving cluster nibz-nightly-2019-03-29... OK Name: nibz-nightly-2019-03-29 ID: 0bddeb0c936d4b5a831849a399022389 State: normal Created: 2019-03-29T08:01:08+0000 Location: wdc06 Master URL: https://c1.us-east.containers.cloud.ibm.com:30611 Master Location: Washington D.C. Master Status: Ready (12 hours ago) Ingress Subdomain: nibz-nightly-2019-03-29.us-east.containers.appdomain.cloud Ingress Secret: nibz-nightly-2019-03-29 Workers: 3 Worker Zones: wdc06 Version: 1.12.6_1546 Owner: skrum@us.ibm.com Monitoring Dashboard: - Resource Group ID: 2a926a9173174d94a6eb13284e089f88 Resource Group Name: default
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME 10.188.103.223 Ready 12h v1.12.6+IKS 10.188.103.223 169.63.131.195 Ubuntu 16.04.6 LTS 4.4.0-143-generic containerd://1.1.6 10.188.103.242 Ready 12h v1.12.6+IKS 10.188.103.242 169.63.131.201 Ubuntu 16.04.6 LTS 4.4.0-143-generic containerd://1.1.6 10.188.103.248 Ready 12h v1.12.6+IKS 10.188.103.248 169.63.131.248 Ubuntu 16.04.6 LTS 4.4.0-143-generic containerd://1.1.6
容器运行时环境为 containerd
。
预估时间
完成本教程大约需要 20 分钟。
使用 Kubernetes 为您所需的任务配置 Falco
由于 Kubernetes 1.12 环境,本教程使用 k8s-with-rbac
文件。Falco 需要设置几个文件:用于运行 Falco daemonset 的 Kubernetes 配置与针对 daemonset 本身的配置的组合。
1:查看 Falco 文件
Falco 使用 Kubernetes 中的服务帐户来访问 Kubernetes API。 falco-account.yaml
规范设置了一种基于角色的通用访问控制三重方法: ServiceAccount
、 ClusterRole
和 ClusterRoleBinding
。 ClusterRole
包含关于所授予的访问权限的信息。如果您在这些文件中没有进行任何更改,那么 Falco 守护进程只能读取和列示,而不能修改 Kubernetes API 中的任何对象。
$ ls -l total 20 -rw-r--r-- 1 nibz nibz 931 Mar 29 15:46 falco-account.yaml drwxr-xr-x 2 nibz nibz 4096 Mar 29 15:51 falco-config/ -rw-r--r-- 1 nibz nibz 2138 Mar 29 15:48 falco-daemonset-configmap.yaml -rw-r--r-- 1 nibz nibz 196 Mar 29 15:45 falco-service.yaml -rw-r--r-- 1 nibz nibz 13 Mar 29 15:27 Readme.md
2:配置基于角色的访问控制 (RBAC)
运行以下命令:
$ kubectl apply -f falco-account.yaml serviceaccount/falco-account created clusterrole.rbac.authorization.k8s.io/falco-cluster-role created clusterrolebinding.rbac.authorization.k8s.io/falco-cluster-role-binding created
如果您使用的是 OpenShift,请为刚创建的帐户设置 OpenShift 安全上下文约束。
$ oc adm policy add-scc-to-user privileged -z falco-account
3:应用 Falco 服务对象
Falco 的 Web 前端还需要 Kubernetes 服务:
$ kubectl apply -f falco-service.yaml service/falco-service created
4:创建 falco-config ConfigMap
Falco 的配置被分成几个文件。 falco.yaml
是指守护进程配置的细节:输出类型、端口等。其他 *_rules.yaml
文件包含 Falco 会针对其进行触发的检查(正在打开的 shell、正在修改的文件等)。通过将 --from-file
自变量与目录一起使用,将所有这些文件组合到单个 ConfigMap 中:
$ kubectl create configmap falco-config --from-file=falco-config configmap/falco-config created
稍后,在 daemonset 的部署中,该 configmap
将安装在 /etc/falco
下。
5:启动 Falco DaemonSet
最后,运行 Falco 应用程序。它作为 DaemonSet 运行,使您可以在每个节点上运行一个:
$ kubectl apply -f falco-daemonset-configmap.yaml daemonset.extensions/falco-daemonset created
在首次运行安装期间,它将使用动态内核模块支持 (DKMS) 来编译和安装内核模块,这就是 Falco 选取系统调用的方式。
6:检查 pod 是否正确启动
运行以下命令以查看 pod 及其状态:
nibz@shockley:~/projects/falco/install-falco-iks/git-repo$ kubectl get pod NAME READY STATUS RESTARTS AGE falco-daemonset-99p8j 1/1 Running 0 26s falco-daemonset-wf2lf 1/1 Running 0 26s falco-daemonset-wqrwm 1/1 Running 0 26s
7:检查日志并读取 DKMS 消息
检查日志并记下来自 DKMS 的消息。您会看到 Sysdig 是一个内核模块:
nibz@shockley:~/projects/falco/install-falco-iks/git-repo$ kubectl logs falco-daemonset-wf2lf * Setting up /usr/src links from host * Unloading falco-probe, if present * Running dkms install for falco Kernel preparation unnecessary for this kernel. Skipping... Building module: cleaning build area... make -j2 KERNELRELEASE=4.4.0-148-generic -C /lib/modules/4.4.0-148-generic/build M=/var/lib/dkms/falco/0.1.2780dev/build.... cleaning build area... DKMS: build completed. falco-probe.ko: Running module version sanity check. - Original module - No original module exists within this kernel - Installation - Installing to /lib/modules/4.4.0-148-generic/kernel/extra/ mkdir: cannot create directory '/lib/modules/4.4.0-148-generic/kernel/extra': Read-only file system cp: cannot create regular file '/lib/modules/4.4.0-148-generic/kernel/extra/falco-probe.ko': No such file or directory depmod... DKMS: install completed. * Trying to load a dkms falco-probe, if present falco-probe found and loaded in dkms Wed May 29 14:55:40 2019: Falco initialized with configuration file /etc/falco/falco.yaml Wed May 29 14:55:40 2019: Loading rules from file /etc/falco/falco_rules.yaml: Wed May 29 14:55:40 2019: Loading rules from file /etc/falco/falco_rules.local.yaml: Wed May 29 14:55:40 2019: Loading rules from file /etc/falco/k8s_audit_rules.yaml: Wed May 29 14:55:41 2019: Starting internal webserver, listening on port 8765 {"output":"00:00:00.048356736: Informational Container with sensitive mount started (user=root command=container:7c5302fccfcb k8s.ns= k8s.pod= container=7c5302fccfcb image=registry.ng.bluemix.net/armada-master/ibm-kube-fluentd-collector:c16fe1602ab65db4af0a6ac008f99ca2a526e6f6 mounts=/etc/kubernetes/:/etc/kubernetes::false:private,/:/host::false:private,/var/log/:/var/log::false:private,/var/lib/docker:/var/lib/docker::false:private,/var/run/docker.sock:/var/run/docker.sock::false:private,/mnt/ibm-kube-fluentd-persist:/mnt/ibm-kube-fluentd-persist::true:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/logmet-secrets-volume:/mnt/logmet/secrets::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/fluentd-config:/fluentd/etc/config.d/logmet/::false:private,/var/data:/var/data::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/at-fluentd-config:/fluentd/etc/config.d/at/::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/activity-tracker-secrets-volume:/mnt/activity-tracker/secrets/::false:private,/var/log/at:/var/log/at::false:private,/var/log/at-no-rotate:/var/log/at-no-rotate::false:private,/run/containerd:/run/containerd::false:private,/run/containerd/containerd.sock:/run/containerd/containerd.sock::true:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/ibm-kube-fluentd-token-v2q5s:/var/run/secrets/kubernetes.io/serviceaccount::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/etc-hosts:/etc/hosts::true:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/containers/fluentd/35f64419:/dev/termination-log::true:private) k8s.ns= k8s.pod= container=7c5302fccfcb","priority":"Informational","rule":"Launch Sensitive Mount Container","time":"1970-01-01T00:00:00.048356736Z", "output_fields": {"container.id":"7c5302fccfcb","container.image.repository":"registry.ng.bluemix.net/armada-master/ibm-kube-fluentd-collector","container.image.tag":"c16fe1602ab65db4af0a6ac008f99ca2a526e6f6","container.mounts":"/etc/kubernetes/:/etc/kubernetes::false:private,/:/host::false:private,/var/log/:/var/log::false:private,/var/lib/docker:/var/lib/docker::false:private,/var/run/docker.sock:/var/run/docker.sock::false:private,/mnt/ibm-kube-fluentd-persist:/mnt/ibm-kube-fluentd-persist::true:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/logmet-secrets-volume:/mnt/logmet/secrets::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/fluentd-config:/fluentd/etc/config.d/logmet/::false:private,/var/data:/var/data::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/at-fluentd-config:/fluentd/etc/config.d/at/::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/activity-tracker-secrets-volume:/mnt/activity-tracker/secrets/::false:private,/var/log/at:/var/log/at::false:private,/var/log/at-no-rotate:/var/log/at-no-rotate::false:private,/run/containerd:/run/containerd::false:private,/run/containerd/containerd.sock:/run/containerd/containerd.sock::true:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/ibm-kube-fluentd-token-v2q5s:/var/run/secrets/kubernetes.io/serviceaccount::false:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/etc-hosts:/etc/hosts::true:private,/var/data/kubelet/pods/8bf0a002-81eb-11e9-b9cf-c68b81a15994/containers/fluentd/35f64419:/dev/termination-log::true:private","evt.time":48356736,"k8s.ns.name":null,"k8s.pod.name":null,"proc.cmdline":"container:7c5302fccfcb","user.name":"root"}} {"output":"00:00:00.048356736: Informational Container with sensitive mount started (user= command=container:721ef5130945 k8s.ns= k8s.pod= container=721ef5130945 image=docker.io/falcosecurity/falco:dev mounts=/run/containerd/containerd.sock:/host/run/containerd/containerd.sock::true:private,/dev:/host/dev::true:private,/proc:/host/proc::false:private,/boot:/host/boot::false:private,/lib/modules:/host/lib/modules::false:private,/usr:/host/usr::false:private,/etc:/host/etc/::false:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/falco-config:/etc/falco::false:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/falco-account-token-jlddc:/var/run/secrets/kubernetes.io/serviceaccount::false:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/etc-hosts:/etc/hosts::true:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/containers/falco/aa75ae83:/dev/termination-log::true:private) k8s.ns= k8s.pod= container=721ef5130945","priority":"Informational","rule":"Launch Sensitive Mount Container","time":"1970-01-01T00:00:00.048356736Z", "output_fields": {"container.id":"721ef5130945","container.image.repository":"docker.io/falcosecurity/falco","container.image.tag":"dev","container.mounts":"/run/containerd/containerd.sock:/host/run/containerd/containerd.sock::true:private,/dev:/host/dev::true:private,/proc:/host/proc::false:private,/boot:/host/boot::false:private,/lib/modules:/host/lib/modules::false:private,/usr:/host/usr::false:private,/etc:/host/etc/::false:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/falco-config:/etc/falco::false:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/falco-account-token-jlddc:/var/run/secrets/kubernetes.io/serviceaccount::false:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/etc-hosts:/etc/hosts::true:private,/var/data/kubelet/pods/c09f7a8d-8221-11e9-b9cf-c68b81a15994/containers/falco/aa75ae83:/dev/termination-log::true:private","evt.time":48356736,"k8s.ns.name":null,"k8s.pod.name":null,"proc.cmdline":"container:721ef5130945","user.name":null}}
Falco 正在运行并且正在记录事件。
查看 Falco 的配置
现在,查看一下您为 Falco 设置的配置。
1:检查 DaemonSet 配置
运行以下命令,以告知 DaemonSet 使用您先前设置的服务帐户和权限来运行:
$ cat falco-daemonset-configmap.yaml | grep serviceAcc serviceAccount: falco-account
查看 falco-account.yaml
以获取详细信息。此配置提供对 Kubernetes API 服务器中几乎所有内容的读取访问权限。
您将许多重要的目录从 Kubernetes 主机安装到 Falco pod 中:
$ cat falco-daemonset-configmap.yaml | grep -A 11 volumes: volumes: - name: containerd-socket hostPath: path: /run/containerd/containerd.sock - name: dev-fs hostPath: path: /dev - name: proc-fs hostPath: path: /proc - name: boot-fs hostPath:
此步骤使 Falco 可以与容器运行时环境进行交互,以提取容器元数据(例如,容器名称和底层镜像名称),查询主机的进程表以发现进程名称。另需注意,此示例将映射 containerd-socket
,而不是 docker-socket
。
2:检查 Falco 配置文件
Falco 由我们通过 ConfigMap 设置的多个 YAML 文件进行配置。 Falco.yaml
将配置服务器设置, falco_rules.yaml
包含有关警报对象和警报级别的规则。
$ ls falco-config/ falco_rules.local.yaml falco_rules.yaml falco.yaml k8s_audit_rules.yaml
3:查看 Falco 值
该规则监视可能有害的 Netcat 命令,并在发现其处于 WARNING
级别时发出警报。
$ cat falco-config/falco_rules.yaml | grep -A 12 'Netcat Remote' - rule: Netcat Remote Code Execution in Container desc: Netcat Program runs inside container that allows remote code execution condition: > spawned_process and container and ((proc.name = "nc" and (proc.args contains "-e" or proc.args contains "-c")) or (proc.name = "ncat" and (proc.args contains "--sh-exec" or proc.args contains "--exec")) ) output: > Netcat runs inside container that allows remote code execution (user=%user.name command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) priority: WARNING tags: [network, process]
观察 Falco 的实际应用
现在让我们看看 Falco 的实际应用。您将跟踪一个终端中的日志,然后在另一终端中综合创建一些事件,并观察事件是否记录到日志。
1:跟踪第一个终端中的日志
运行以下命令:
$ kubectl get pod NAME READY STATUS RESTARTS AGE falco-daemonset-99p8j 1/1 Running 0 112m falco-daemonset-wf2lf 1/1 Running 0 112m falco-daemonset-wqrwm 1/1 Running 0 112m $ kubectl logs -f falco-daemonset-99p8j * Setting up /usr/src links from host * Unloading falco-probe, if present * Running dkms install for falco Kernel preparation unnecessary for this kernel. Skipping... Building module: cleaning build area... make -j2 KERNELRELEASE=4.4.0-148-generic -C /lib/modules/4.4.0-148-generic/build M=/var/lib/dkms/falco/0.1.2780dev/build.... cleaning build area... DKMS: build completed. falco-probe.ko: Running module version sanity check. - Original module - No original module exists within this kernel - Installation - Installing to /lib/modules/4.4.0-148-generic/kernel/extra/ mkdir: cannot create directory '/lib/modules/4.4.0-148-generic/kernel/extra': Read-only file system cp: cannot create regular file '/lib/modules/4.4.0-148-generic/kernel/extra/falco-probe.ko': No such file or directory depmod... DKMS: install completed. * Trying to load a dkms falco-probe, if present falco-probe found and loaded in dkms Wed May 29 14:55:36 2019: Falco initialized with configuration file /etc/falco/falco.yaml Wed May 29 14:55:36 2019: Loading rules from file /etc/falco/falco_rules.yaml: Wed May 29 14:55:37 2019: Loading rules from file /etc/falco/falco_rules.local.yaml: Wed May 29 14:55:37 2019: Loading rules from file /etc/falco/k8s_audit_rules.yaml: Wed May 29 14:55:38 2019: Starting internal webserver, listening on port 8765 {"output":"00:00:00.020155776: Informational Container with sensitive mount started (user= command=container:9d56002def78 k8s.ns= k8s.pod= container=9d56002def78 image=docker.io/falcosecurity/falco:dev mounts=/run/containerd/containerd.sock:/host/run/containerd/containerd.sock::true:private,/dev:/host/dev::true:private,/proc:/host/proc::false:private,/boot:/host/boot::false:private,/lib/modules:/host/lib/modules::false:private,/usr:/host/usr::false:private,/etc:/host/etc/::false:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/falco-config:/etc/falco::false:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/falco-account-token-jlddc:/var/run/secrets/kubernetes.io/serviceaccount::false:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/etc-hosts:/etc/hosts::true:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/containers/falco/cb0bed6e:/dev/termination-log::true:private) k8s.ns= k8s.pod= container=9d56002def78","priority":"Informational","rule":"Launch Sensitive Mount Container","time":"1970-01-01T00:00:00.020155776Z", "output_fields": {"container.id":"9d56002def78","container.image.repository":"docker.io/falcosecurity/falco","container.image.tag":"dev","container.mounts":"/run/containerd/containerd.sock:/host/run/containerd/containerd.sock::true:private,/dev:/host/dev::true:private,/proc:/host/proc::false:private,/boot:/host/boot::false:private,/lib/modules:/host/lib/modules::false:private,/usr:/host/usr::false:private,/etc:/host/etc/::false:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~configmap/falco-config:/etc/falco::false:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/volumes/kubernetes.io~secret/falco-account-token-jlddc:/var/run/secrets/kubernetes.io/serviceaccount::false:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/etc-hosts:/etc/hosts::true:private,/var/data/kubelet/pods/c0a1a131-8221-11e9-b9cf-c68b81a15994/containers/falco/cb0bed6e:/dev/termination-log::true:private","evt.time":20155776,"k8s.ns.name":null,"k8s.pod.name":null,"proc.cmdline":"container:9d56002def78","user.name":null}} ...
2:在第二个终端中创建安全事件
谨记重新导出 KUBECONFIG
:
$ export KUBECONFIG=/home/nibz/.bluemix/plugins/container-service/clusters/yourcluster.yml $ kubectl get pod NAME READY STATUS RESTARTS AGE falco-daemonset-99p8j 1/1 Running 0 3h2m falco-daemonset-wf2lf 1/1 Running 0 3h2m falco-daemonset-wqrwm 1/1 Running 0 3h2m nibz@shockley:~/projects/falco/install-falco-iks/git-repo$ kubectl exec -it falco-daemonset-99p8j /bin/bash root@falco-daemonset-99p8j:/# echo "I'm in!" I'm in! root@falco-daemonset-99p8j:/#
在第一个终端中,您可以看到事件:
{"output":"17:58:28.064781208: Notice A shell was spawned in a container with an attached terminal (user=root k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78 shell=bash parent= cmdline=bash terminal=34816) k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78","priority":"Notice","rule":"Terminal shell in container","time":"2019-05-29T17:58:28.064781208Z", "output_fields": {"container.id":"9d56002def78","evt.time":1559152708064781208,"k8s.ns.name":"default","k8s.pod.name":"falco-daemonset-99p8j","proc.cmdline":"bash","proc.name":"bash","proc.pname":null,"proc.tty":34816,"user.name":"root"}}
3:使用 jq 处理事件
当您使用 jq 处理事件时,Falco 会提供有关安全事件以及事件的完整 Kubernetes 上下文的有用信息,例如 pod 名称和名称空间:
$ echo '{"output":"17:58:28.064781208: Notice A shell was spawned in a container with an attached terminal (user=root k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78 shell=bash parent= cmdline=bash terminal=34816) k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78","priority":"Notice","rule":"Terminal shell in container","time":"2019-05-29T17:58:28.064781208Z", "output_fields": {"container.id":"9d56002def78","evt.time":1559152708064781208,"k8s.ns.name":"default","k8s.pod.name":"falco-daemonset-99p8j","proc.cmdline":"bash","proc.name":"bash","proc.pname":null,"proc.tty":34816,"user.name":"root"}} > ' | jq '.' { "output": "17:58:28.064781208: Notice A shell was spawned in a container with an attached terminal (user=root k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78 shell=bash parent= cmdline=bash terminal=34816) k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78", "priority": "Notice", "rule": "Terminal shell in container", "time": "2019-05-29T17:58:28.064781208Z", "output_fields": { "container.id": "9d56002def78", "evt.time": 1559152708064781300, "k8s.ns.name": "default", "k8s.pod.name": "falco-daemonset-99p8j", "proc.cmdline": "bash", "proc.name": "bash", "proc.pname": null, "proc.tty": 34816, "user.name": "root" } }
现在您可以触发早前显示的 Netcat 规则:
root@falco-daemonset-99p8j:/# nc -l 4444 ^C
kubectl logs falco-daemonset-99p8j ... {"output":"18:00:41.530249297: Notice Network tool launched in container (user=root command=nc -l 4444 container_id=9d56002def78 container_name=falco image=docker.io/falcosecurity/falco:dev) k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78 k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78","priority":"Notice","rule":"Lauch Suspicious Network Tool in Container","time":"2019-05-29T18:00:41.530249297Z", "output_fields": {"container.id":"9d56002def78","container.image.repository":"docker.io/falcosecurity/falco","container.image.tag":"dev","container.name":"falco","evt.time":1559152841530249297,"k8s.ns.name":"default","k8s.pod.name":"falco-daemonset-99p8j","proc.cmdline":"nc -l 4444","user.name":"root"}} ... $ echo '{"output":"18:00:41.530249297: Notice Network tool launched in container (user=root command=nc -l 4444 contain er_id=9d56002def78 container_name=falco image=docker.io/falcosecurity/falco:dev) k8s.ns=default k8s.pod=falco- daemonset-99p8j container=9d56002def78 k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78","priority":"Notice","rule":"Lauch Suspicious Network Tool in Container","time":"2019-05-29T18:00:41.530249297Z", "output_fields": {"container.id":"9d56002def78","container.image.repository":"docker.io/falcosecurity/falco", "container.image.tag":"dev","container.name":"falco","evt.time":1559152841530249297,"k8s.ns.name":"default","k 8s.pod.name":"falco-daemonset-99p8j","proc.cmdline":"nc -l 4444","user.name":"root"}}' | jq '.' { "output": "18:00:41.530249297: Notice Network tool launched in container (user=root command=nc -l 4444 contain er_id=9d56002def78 container_name=falco image=docker.io/falcosecurity/falco:dev) k8s.ns=default k8s.pod=falco- daemonset-99p8j container=9d56002def78 k8s.ns=default k8s.pod=falco-daemonset-99p8j container=9d56002def78", "priority": "Notice", "rule": "Lauch Suspicious Network Tool in Container", "time": "2019-05-29T18:00:41.530249297Z", "output_fields": { "container.id": "9d56002def78", "container.image.repository": "docker.io/falcosecurity/falco", "container.image.tag": "dev", "container.name": "falco", "evt.time": 1559152841530249200, "k8s.ns.name": "default", "k8s.pod.name": "falco-daemonset-99p8j", "proc.cmdline": "nc -l 4444", "user.name": "root" } }
您已看到 Falco 可以发现什么样的事件以及如何进行配置。
将警报发送到 Slack 通道
现在,您不仅可以将警报转储到标准输出中,还可以对警报进行更有趣的操作。 Falco 可以对警报执行一些其他操作 ,但是本教程展示了如何将警报发送到 Slack 通道。
- 更改
falco-config/falco.yaml
以包含您的 slack webhook,并将enabled
更改为true
。在 api.slack.com/incoming-webhooks 查看如何在 Slack 中创建传入 webhook。
$ cat falco-config/falco.yaml | grep -A1 -B3 hooks.slack -- program_output: enabled: false keep_alive: false program: "jq '{text: .output}' | curl -d @- -X POST https://hooks.slack.com/services/XXX"
vim falco-config/falco.yaml
$ cat falco-config/falco.yaml | grep -A1 -B3 hooks.slack program_output: enabled: true keep_alive: false program: "jq '{text: .output}' | curl -d @- -X POST https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/xxxxxxxxxxxxxxxxxxxxxxxx"
- 重做
ConfigMap
和DaemonSet
:$ kubectl delete configmap falco-config $ kubectl create configmap falco-config --from-file=falco-config $ kubectl delete -f falco-daemonset-configmap.yaml $ kubectl apply -f falco-daemonset-configmap.yaml
- 使用
spawn
命令启动 shell,然后您会看到安全警报发布至 Slack:
结束语
您可以使用 Falco 做更多事情,包括将 Falco 事件关联到无服务器计算平台,例如 OpenWhisk 和Knative。希望本介绍为您提供了一些基本信息,帮助您开始下一个项目。
致谢
我非常感谢 Michael Ducy 帮助我完成了本教程。
参考资源
- 相关文章: Linux 基础知识:学习容器之前的必备知识
- Code Pattern:汽车拍卖网络
本文翻译自: Set up runtime container security monitoring with Sysdig Falco and Kubernetes (2019-07-02)