亚马逊AWS官方博客

利用 Lambda 和 Falco 为 Amazon EKS 提供安全保护

入侵和异常检测是重要的安全工具,可提高在 Amazon EKS 集群上的容器中部署的应用程序的运行时安全性。在本博文中,来自 Sysdig 公司的 Michael Ducy 将会介绍 Falco(CNCF 沙盒项目)如何在检测到异常应用程序行为时发出提醒。然后配置 AWS Lambda 函数,将提醒消息传送到 Slack。

您可通过多种方式为 Amazon Web Services (AWS) 上的 Amazon Elastic Container Service for Kubernetes (Amazon EKS) 集群提供安全保护。AWS 提供多种选项,其中包括 Virtual Private Cloud (VPC),该服务可对安全组和网络 ACL 进行传统网络控制。Amazon EKS 同样支持 IAM 身份验证,Kubernetes RBAC 系统中已直接绑定该功能。除了上述功能外,AWS 会将运行 EKS 集群的节点与其他客户隔离开。

即使拥有这些强大功能,额外的安全层仍然必不可少。Falco 是由 Sysdig 公司开发的开源 CNCF 沙盒项目,可检测 EKS 集群以及集群中部署的应用程序的异常行为,从而提供额外安全保护。

配合使用 Amazon Simple Notification Service (Amazon SNS) 和 AWS Lambda 等 AWS 服务,Falco 通过删除受损容器、受污染 EKS 节点以防止安排新工作负载,同时通过 Slack 等消息收发系统通知团队,来主动保护您的 EKS 集群。

Falco 运行时安全保护

Falco 可为容器化应用程序及其底层主机系统提供运行时安全保护。通过检测容器主机的 Linux 内核,Falco 能够根据容器和主机执行的系统调用创建事件流。然后可对此事件流应用规则,以检测异常行为。

例如,以下规则可在容器启动后检测试图读取密钥的任何流程(密钥只能在启动时读取):

- macro: proc_is_new
 condition: proc.duration <= 5000000000

- rule: Read secret file after startup
 desc: >
   an attempt to read any secret file (e.g. files containing user/password/authentication
   information) Processes might read these files at startup, but not afterwards.
 condition: fd.name startswith /etc/secrets and open_read and not proc_is_new
 output: >
   Sensitive file opened for reading after startup (user=%user.name
   command=%proc.cmdline file=%fd.name)
 priority: WARNING

Falco 还会从底层容器运行时及包括 Docker 和 Kubernetes 在内的协调器中提取元数据信息。系统可在 Falco 规则中实施这些元数据,从而根据容器映像、容器名称或特定 Kubernetes 资源(例如 pod、deployment、service 或 namespace)来限制某些行为。

Falco 流程图
如果 Falco 检测到异常事件,会向目标发出提醒。目标可以是 stdout、日志文件、Syslog,或触发将提醒作为 stdin 传递的程序。利用 Kubernetes 中的伴生容器,您可以扩展目标以添加 AWS Simple Notification Service (SNS) 等消息收发服务。发布到 SNS 的警报可以触发订阅 Falco 警报的其他服务,例如 AWS Lambda 函数。

部署支持 SNS 的 Falco

要开始使用 Falco,最简单的方法就是利用 Falco 提供的 Helm 图表。Helm 是 Kubernetes 的包管理器,可提供丰富的应用程序库。您还可使用 Helm 为您独特环境专用的应用程序设置选项。要安装 Helm,工作站中需要有 Helm 二进制文件,同时需要在 EKS集群中安装 Helm。

$ brew install kubernetes-helm # For macOS users with Homebrew installed

$ kubectl -n kube-system create sa tiller
$ kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller
$ helm init --service-account tiller

Helm 安装完成后,即可轻松安装支持 SNS 的 Falco。

$ helm install --name sysdig-falco-1 \
--set integrations.snsOutput.enabled=true \
--set integrations.snsOutput.topic=SNS_TOPIC \
--set integrations.snsOutput.aws_access_key_id=AWS_ACCESS_KEY_ID \
--set integrations.snsOutput.aws_secret_access_key=AWS_SECRET_ACCESS_KEY \
--set integrations.snsOutput.aws_default_region=AWS_DEFAULT_REGION \
stable/falco

将 SNS_TOPIC、AWS_ACCESS_KEY_ID、AWS_SECRET_KEY 和 AWS DEFAULT_REGION 调整为适合 EKS 部署的设置,然后 Falco 将开始向您指定的 SNS 主题发布警报。

为 Lambda 函数创建角色

借助 EKS,即可通过 AWS IAM 对用户和服务账户进行身份验证。为了让 Lambda 函数与 EKS 交互,以根据 Falco 警报删除 pod 或执行其他操作,我们需要为服务账户创建 IAM 角色。Kubernetes 将会验证 IAM 服务账户是否为有效用户,然后利用 Kubernetes RBAC 内部功能限制服务账户可在集群内执行的操作。

IAM for Lambda 摘要屏幕

我们已为 Lambda 函数创建了 IAM 角色。然后,我们需要在 IAM 角色和拥有集群身份验证权限的用户之间构建信任关系。在此环境中,我们将创建一个名为 kubernetes-response-engine 的 IAM 用户。我们将此用户的权限留空,让其作为有效用户通过 Kubernetes 身份验证,但不会在 AWS 账户中创建或修改对象。然后可将该用户映射到 IAM 角色,如下所示。

IAM for Lambda 摘要屏幕

我们还需要在 Kubernetes 中为 aws-iam-authenticator 创建(或更新)configmap,从而将 IAM 角色映射到 Kubernetes 用户。如果遵循启动工作程序节点的 AWS 指南操作,则该 configmap 可能已经存在。您可以运行 kubectl desc configmap aws-auth 获取现有 configmap。如果 configmap 已存在,您需要合并现有 configmap 和以下 configmap 的 data 部分。

apiVersion: v1
kind: ConfigMap
metadata:
 name: aws-auth
 namespace: kube-system
data:
 mapRoles: |
    - rolearn: arn:aws:iam::<ARN From IAM>:role/iam_for_lambda
      username: kubernetes-response-engine
      groups:
        - system:masters

最后,我们还需要为 Kubernetes RBAC 系统添加角色,以便 Lambda 函数在 Kubernetes 集群中执行操作。我们已经为 Falco Github 存储库中的集群角色和集群角色绑定添加了所需的 yaml。

$ git clone https://github.com/falcosecurity/falco.git
$ cd integrations/kubernetes-response-engine/deployment/aws
$ kubectl apply -f cluster-role.yaml cluster-role-binding.yaml

部署 Lambda 函数以处理 Falco 警报

现在,我们要将 Falco 警报发布到 SNS 主题,我们可以部署 Lambda 函数以处理这些警报。首先请查看 Falco GitHub 存储库中的示例。

克隆存储库后,请导航至 integrations/kubernetes-response-engine/playbooks 目录。为了向 Lambda 部署函数,我们需要将函数和所有依赖项打包为 zip 文件。由于函数采用 Python 编写,因此您需要基本 Python 环境、pip 和 pipenv

首先,生成一个 requirements.txt 文件,其中包含运行 Lambda 函数所需的 Python 库列表。此操作可通过 pipenv 完成:

$ pipenv lock --requirements | sed '/^-/ d' > requirements.txt

现在已定义依赖项,pip 可将这些依赖项下拉至本地目录。由于我们希望使用 Lambda 向 Slack 推送消息,因此还需复制 slack.py 函数,当 Falco 发送警报时会触发该函数。

$ mkdir -p lambda
$ pip install -t lambda -r requirements.txt
$ pip install -t lambda  .
$ cp functions/slack.py lambda/

现在,依赖项和函数位于相同目录中,接下来只需创建 zip 文件以部署到 AWS Lambda 即可:

$ cd lambda
$ zip ../slack.zip  -r *
$ cd ..

代码已打包,我们可以使用 AWS CLI 创建 Lambda 函数。您需要将 --role 值替换为之前创建角色的相应 ID,并且将 Slack webhook URL 替换为您希望在其中发布 Falco 消息的通道的 URL。

$ aws lambda create-function \
 --function-name falco-slack \
 --runtime python2.7 \
 --role <arn:aws:iam::XXXxxXXX:role/iam_for_lambda> \
 --environment Variables=”SLACK_WEBHOOK_URL=https://<custom_slack_app_url>” \
 --handler slack.handler \
 --zip-file fileb://./slack.zip

部署函数以在 EKS 中执行操作

除了向 Slack 发送消息外,还可利用 AWS Lambda 在 EKS 集群中执行操作。您可在 integrations/kubernetes-response-engine/playbooks/functions 目录中找到这些函数。

按照上述说明提取函数的依赖项,将 functions/slack.py 替换为您要部署的函数。为了允许这些 Lambda 函数与 EKS 通信,我们需要生成一个包含集群信息的 kubeconfig 文件。

$ aws eks update-kubeconfig --name <cluster-name> --kubeconfig lambda/kubeconfig

$ sed -i "s/command: aws-iam-authenticator/command: .\/aws-iam-authenticator/g" lambda/kubeconfig

我们还需复制 aws-iam-authenticator,从而允许 Lambda 函数验证回 IAM 以在 EKS 集群中运行。然后,我们就可如前所述创建 zip 文件:

$ cp extra/aws-iam-authenticator lambda/
$ cd lambda
$ zip ../delete.zip  -r *
$ cd ..

要部署函数,我们最后需要指定 kubeconfig 文件的位置,以及是否需要在函数中加载此文件。

$ aws lambda create-function \
 --function-name falco-delete \
 --runtime python2.7 \
 --role <arn:aws:iam::XXXxxXXX:role/iam_for_lambda> \
 --environment Variables=”KUBECONFIG=kubeconfig,KUBERNETES_LOAD_KUBE_CONFIG=1” \
 --handler delete.handler \
 --zip-file fileb://./delete.zip

捆绑 SNS 和 Lambda

我们已经将 Falco 发布到 SNS,并且已部署 Lambda 函数来处理警报,现在需要整合 SNS 主题和函数。此操作可以通过 AWS 控制台轻松完成。

导航至 Lambda 服务并选择 falco-slack 函数。您可在设计器中添加触发器,只需从左侧窗格中选择即可。向下滚动并单击 SNS 以添加触发器。在配置触发器下方,搜索之前创建的 SNS 主题,确保已选中启用触发器,然后保存函数。

设置 Falco-Slack

触发 Falco 警报会向 SNS 发布警报,触发 Lambda 函数并将警报发布到 Slack。

Slack 警报
更新函数订阅

可能无需为每个发布到 SNS 的事件启用 Lambda 函数。例如,如果函数删除 pod,我们只希望在发出严重警报时触发函数。如需控制触发警报的函数,我们可以更新函数订阅。

在 AWS SNS 控制台中,选择订阅,然后编辑函数的订阅筛选策略。

编辑订阅筛选策略

创建 JSON 对象并设置筛选策略。现在,只有当系统收到“错误”或“警告”警报时才会触发 Lambda 函数。

了解 Falco

我们希望本文有助于集成 Falco 运行时安全与 Amazon Web Services,从而构建符合需求的安全堆栈。

如果您认为本文有用,而且希望为 Falco 项目做出贡献,可以通过以下途径提供帮助:

Michael Ducy

Michael Ducy

作为 Sysdig 的社区和宣教管理者,Michael Ducy 负责推广 Sysdig 开源解决方案。他也是 Falco 负责人,Falco 是由 Sysdig 开发的行为活动监控工具,现已迅速成为热门的开源容器运行时安全选择,适用于通过 Kubernetes、Cloud Foundry 和 OpenShift 构建的原生云平台。

加入 Sysdig 之前,Michael 曾在 Chef 负责社区和宣教工作,并且在领先的技术公司从事过系统架构、系统工程和性能工程方面的工作。

Michael 拥有芝加哥大学的计算机科学硕士学位和俄亥俄州立大学的 MBA 学位。

本博文中的内容和意见属于第三方作者,AWS 不对本博文的内容或准确性负责。