- 网络安全
- 应用安全
- 云原生
- 漏洞扫描
【免费下载链接】ThreatMapper
Open Source Cloud Native Application Protection Platform (CNAPP)
ThreatMapper(Deepfence ThreatMapper)是开源云原生应用保护平台(CNAPP)。在 AWS Fargate 这类 Serverless 容器运行环境中,无法像传统 ECS EC2 或 Kubernetes 那样直接以特权容器方式部署传感器(Sensor Agent),因此 ThreatMapper 采用Sidecar 容器 + Task Definition的方式,让传感器与业务容器共享存储卷、共用启动入口,实现对 Serverless 容器的漏洞扫描、恶意软件扫描与密钥泄露扫描。读完本文,你将掌握在 AWS Fargate 上完整创建 Task Definition、配置 IAM 角色与密钥、注入环境变量、挂载卷并正确编排启动顺序的每一步,并能理解-fargate专用镜像背后的启动链路源码。
背景:为什么 Fargate 需要 Sidecar 部署
ThreatMapper 传感器以轻量级特权容器形式运行在目标主机上,负责发现工作负载、采集遥测数据并与 Management Console 通过 TLS 通信(参见 架构:Sensor Agent 与 安装传感器)。但 Fargate 与 ECS EC2 提供方有本质差异:
- 在 ECS EC2 提供方中,传感器以 DAEMON 服务部署,直接挂载宿主机的
/、/var/run/docker.sock、/sys/kernel/debug等路径,且以privileged: true运行; - 在 Fargate 中,用户无法访问底层宿主机,没有 Docker Socket、没有宿主目录挂载,传感器只能作为Sidecar 容器,通过
volumesFrom与业务容器共享 Agent 的/deepfence卷,并在业务容器内执行 Agent 入口脚本。
ThreatMapper 为此提供了专用镜像quay.io/deepfenceio/deepfence_agent_ce:THREATMAPPER_VERSION-fargate,它与 Docker / Kubernetes / ECS EC2 等其他部署方式使用的镜像 tag 不同,请勿混用。
当前 Fargate 传感器容器支持的基础操作系统为:Amazon Linux、Ubuntu、Debian、CentOS 和 RHEL。
Management Console(管理控制台)则独立安装在 Fargate 之外,安装流程与常规部署一致,不在此重复。
安装前准备
开始之前,请先确认具备以下信息(下文以<MGMT_CONSOLE_URL>、<DEEPFENCE_KEY>指代):
| 信息 | 说明 |
|---|---|
<MGMT_CONSOLE_URL> | Management Console 的 IP 或域名 |
<DEEPFENCE_KEY> | Deepfence API Key,可在管理控制台Settings > User > API Key中获取 |
随后按 AWS 官方文档《Set up to use AWS ECS》完成 ECS 环境初始化(创建账号、VPC、集群等)。之后你需要依次完成三件事:
- 创建AWS ECS task execution IAM role(任务执行角色);
- 创建 Secret 存储 Deepfence Key;
- 创建策略(托管策略或内联策略)允许访问所存储的 Secret,并将策略附加到任务 IAM 角色;同时需要把
AmazonECSTaskExecutionRolePolicy附加到该角色,以便 ECS 任务正常运行。
前置条件:创建 Secret 与 IAM 角色
1. 创建 Deepfence API Key 的 Secret
- 在 AWS Console 进入 Secrets Manager 控制台;
- 选择Store a new secret;
- 选择Other type of secret;
- 选择Plaintext,粘贴以下 JSON:
{ "deepfence_api_key": "<DEEPFENCE_KEY>" }创建完成后保存 Secret 的 ARN,下文以<API_KEY_SECRET_ARN>指代。
⚠️ 注意:务必小心双引号。AWS UI 有时会把普通双引号转成特殊字符,导致内容不再是合法 JSON。
2. 创建任务角色(如deepfence-agent-role)
- 在 AWS Console 进入 IAM 控制台;
- 进入Access management > roles;
- 选择Create Role;
- 选择Custom trust policy,粘贴:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }继续后续步骤:
- 在Permissions policies中搜索 "Task",选择
AmazonECSTaskExecutionRolePolicy; - 再次搜索 "Task",选择
CloudWatchLogsFullAccess; - 点击Next,将角色命名为
deepfence-agent-role,然后Create role; - 保存角色 ARN,下文以
<AGENT_TASK_ROLE_ARN>指代; - 搜索并进入刚创建的角色(如
deepfence-agent-role); - 选择Add permissions > Create inline policy,添加:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": [ "<API_KEY_SECRET_ARN>" ] } ] }- 如果你为 Secret 使用了自定义 KMS 密钥(而非默认密钥),还需要在内联策略中追加 KMS 权限:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "kms:Decrypt", "secretsmanager:GetSecretValue" ], "Resource": [ "<API_KEY_SECRET_ARN>", "<custom_kms_key_arn>" ] } ] }最后创建该策略即可。
在 Fargate 中创建新的 Task Definition
创建任务定义
在 ECS 控制台侧边栏点击Task definitions,选择Create new Task Definition,Launch type 选择AWS Fargate:
| 新建 Fargate 任务 |
设置任务参数
编辑Task Definition Name、Task Role、Task Execution Role等字段。Task Role与Task Execution Role必须使用前面在 IAM 步骤中创建的角色(如deepfence-agent-role)。根据实际负载需求指定Task memory与Task CPU:
| 更新任务定义并创建 Agent 容器 |
添加 Deepfence Agent Sidecar 容器
点击Add Container创建 ThreatMapper 传感器的标准容器:
- Image设置为
quay.io/deepfenceio/deepfence_agent_ce:THREATMAPPER_VERSION-fargate; - 在 Environment 部分,千万不要勾选 "Essential"(即不作为必备容器,避免 Agent 失败导致业务容器被回收);
- 记下 Agent 容器的名称(示例中为
deepfence-agent),稍后在应用容器的Volumes From中需要引用它。
最后点击Add完成 Agent 容器的创建:
| 在任务定义内创建 Sidecar Agent 容器 |
添加应用主容器
点击Add Container为你的应用创建容器。如果有多个应用容器,需要对每个容器重复以下步骤。
为 Fargate 应用容器配置环境变量
ThreatMapper 传感器要求以下环境变量:
| 环境变量 | 说明 |
|---|---|
DEEPFENCE_KEY | Management Console UI 中获取的 API Key(可存储为 Secret,随后通过valuesFrom在 environment 中引用) |
MGMT_CONSOLE_URL | Management Console 的 IP 地址 |
DF_SERVERLESS | Serverless 实例必须设置为true |
MGMT_CONSOLE_URL_SCHEMA | 根据 Management Console 使用的协议设置为http或https |
MGMT_CONSOLE_PORT | 根据 Management Console 使用的端口设置为80或443 |
| 为 Fargate 应用容器配置环境变量 |
如果使用 JSON 方式配置任务定义,可在对应容器段中填入以下内容(将 IP 与 API Key 替换为实际值):
"environment": [ { "name": "DEEPFENCE_KEY", "value": "<deepfence-key>" }, { "name": "MGMT_CONSOLE_URL", "value": "<MGMT_CONSOLE_URL>" }, { "name": "DF_SERVERLESS", "value": "true" }, { "name": "DF_LOG_LEVEL", "value": "info" }, { "name": "CUSTOM_TAGS", "value": "" }, { "name": "DF_INSTALL_DIR", "value": "/deepfence" }, { "name": "MGMT_CONSOLE_URL_SCHEMA", "value": "https" }, { "name": "MGMT_CONSOLE_PORT", "value": "443" } ]其中DF_LOG_LEVEL(debug/info/error,默认info)、CUSTOM_TAGS(以逗号分隔的标签)与DF_INSTALL_DIR(Agent 安装目录)是文档示例中给出的补充变量;从 start-df-services-fargate.sh 的源码可以看出,DF_SERVERLESS默认值即true,DF_INSTALL_DIR默认值为/opt/deepfence。若安全要求更高,DEEPFENCE_KEY可以不放在明文environment中,而是通过secrets段引用(见下文完整示例)。
配置存储(Volumes From)
滚动到Storage区域,点击Add Volume from:在Container下拉框选择你的应用容器,在Source container下拉框选择 Agent 容器,以允许应用容器对 Deepfence Agent 卷进行读写。不要勾选Read only,如下图所示:
| 配置 VolumesFrom 设置 |
使用 JSON 时,将以下内容复制到对应容器段(修改 Container 名称):
"volumesFrom": [ { "sourceContainer": "deepfence-agent", "readOnly": false } ],最后点击Create完成任务定义的创建。
配置正确的启动顺序
Agent 卷就绪后,还必须同时调用 Agent 入口与应用入口,才能以 Deepfence 监控模式启动应用。有两种方式:
方式一:修改 Entry point(入口点)
把 ThreatMapper 入口点与应用入口点及其参数,以逗号分隔列表的形式填入Entry point字段:
| 方式 (1a):通过修改 Entrypoint 启动 Agent |
JSON 方式如下(注意引号转义):
"entryPoint": [ "/deepfence/usr/local/bin/deepfence-entry-point-scratch.sh", "customer-entry-point.sh", "param1", "param2" ]方式二:分别修改 Entry point 和 Command
把 ThreatMapper 入口点填入Entry point字段,把应用入口点与参数填入Command字段:
| 方式 (1b):通过修改 Entrypoint 和 Command 启动 Agent |
JSON 方式如下:
"entryPoint": [ "/deepfence/usr/local/bin/deepfence-entry-point-scratch.sh" ], "command": [ "customer-entry-point.sh", "param1", "param2" ]完整示例:带 Deepfence Agent Sidecar 的 Fargate 任务定义
以下是文档提供的完整 JSON 示例(以 Pythonhttp.server为例)。其中应用容器通过dependsOn声明依赖 Agent 容器(condition: COMPLETE),通过secrets从 Secrets Manager 注入DEEPFENCE_KEY,通过volumesFrom共享 Agent 卷,并将日志输出到 CloudWatch:
{ "requiresCompatibilities": ["FARGATE"], "inferenceAccelerators": [], "containerDefinitions": [ { "name": "python", "image": "python:latest", "cpu": 0, "portMappings": [ { "name": "python-8000-tcp", "containerPort": 8000, "hostPort": 8000, "protocol": "tcp", "appProtocol": "http" } ], "essential": true, "entryPoint": [ "/deepfence/usr/local/bin/deepfence-entry-point-scratch.sh" ], "command": ["python3", "-m", "http.server"], "environment": [ { "name": "MGMT_CONSOLE_URL", "value": "<MGMT_CONSOLE_URL>" }, { "name": "DF_SERVERLESS", "value": "true" }, { "name": "DF_LOG_LEVEL", "value": "info" }, { "name": "CUSTOM_TAGS", "value": "" }, { "name": "DF_INSTALL_DIR", "value": "/deepfence" }, { "name": "MGMT_CONSOLE_URL_SCHEMA", "value": "https" }, { "name": "MGMT_CONSOLE_PORT", "value": "443" } ], "mountPoints": [], "volumesFrom": [ { "sourceContainer": "deepfence-agent", "readOnly": false } ], "secrets": [ { "name": "DEEPFENCE_KEY", "valueFrom": "<API_KEY_SECRET_ARN>:deepfence_api_key::" } ], "dependsOn": [ { "containerName": "deepfence-agent", "condition": "COMPLETE" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-create-group": "true", "awslogs-group": "/ecs/test-doc-python", "awslogs-region": "us-west-2", "awslogs-stream-prefix": "ecs", "mode": "non-blocking", "max-buffer-size": "25m" } } }, { "name": "deepfence-agent", "image": "quay.io/deepfenceio/deepfence_agent_ce:THREATMAPPER_VERSION-fargate", "repositoryCredentials": {}, "cpu": 0, "portMappings": [], "essential": false, "environment": [], "mountPoints": [], "volumesFrom": [], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-create-group": "true", "awslogs-group": "/ecs/test-doc-python", "awslogs-region": "us-west-2", "awslogs-stream-prefix": "ecs", "mode": "non-blocking", "max-buffer-size": "25m" } } } ], "volumes": [], "networkMode": "awsvpc", "memory": "4096", "cpu": "2048", "family": "test-doc-python", "executionRoleArn": "<AGENT_TASK_ROLE_ARN>", "taskRoleArn": "<AGENT_TASK_ROLE_ARN>", "runtimePlatform": { "cpuArchitecture": "X86_64", "operatingSystemFamily": "LINUX" }, "tags": [], "placementConstraints": [] }将该 JSON 中的<MGMT_CONSOLE_URL>、<API_KEY_SECRET_ARN>、<AGENT_TASK_ROLE_ARN>替换为实际值后即可直接使用。创建任务定义后,把应用部署到集群,即可在管理控制台中看到 Agent 出现。
源码视角:Fargate 传感器的启动链路
理解了配置后,可以从源码看清-fargate镜像的运作机制。
镜像构成:scratch 基础镜像 +/deepfence卷
Dockerfile.fargate 基于scratch构建,将 Agent 二进制、busybox 工具集、入口脚本等全部放入/deepfence目录,并声明VOLUME ["/deepfence"]。这就是 Fargate 任务中volumesFrom能共享的卷来源:应用容器挂载 Agent 容器的/deepfence卷后,即可调用其中的入口脚本与工具链。
入口脚本:先启动 Agent,再启动应用
deepfence-entry-point-scratch.sh 的逻辑非常清晰:
- 后台启动
/deepfence/usr/local/bin/start-df-services.sh(即 Agent 服务); sleep 20等待 Agent 完成初始化;- 若入口脚本携带参数(来自
entryPoint/command配置),则通过envsubst展开环境变量后执行应用自身的入口点,例如示例中的python3 -m http.server。
这正是文档要求"必须同时提供 ThreatMapper 入口点与应用入口点"的原因——由同一入口脚本串联 Agent 与应用的启动顺序。
服务启动脚本:Fargate 专属默认值
start-df-services-fargate.sh 会强制设置DF_SERVERLESS=true(默认值)、DF_INSTALL_DIR=/opt/deepfence(默认值),并把MGMT_CONSOLE_PORT强制设为443、开启DF_TLS_ON。脚本随后把/deepfence下的bin、etc、home、usr、opt拷贝到安装目录,用envsubst渲染 Fluent Bit 配置,最后启动deepfenced主进程。
探测模式:Serverless 分支
run_discovery.sh 中,当DF_SERVERLESS == "true"时,discovery 探针会以--probe.docker=false --probe.podman=false --probe.cri=false --probe.conntrack=false启动:Fargate 下没有 Docker Socket / CRI 可用,因此关闭容器运行时探测与连接跟踪,仅做进程与应用级探测。
扫描路径:Serverless 分支
Deepfence bootstrapper 是 Agent 内执行扫描任务的控制面。generate_sbom.go 的init()中,当DF_SERVERLESS == "true"时扫描根路径从dir:/fenced/mnt/host/(主机挂载模式)切换为dir:/(Fargate 模式,直接扫描容器文件系统);malware_scanner.go 与 secret_scanner.go 也有同样的分支。main.go 则通过binaryOnly = os.Getenv("DF_SERVERLESS") != ""进入纯二进制运行模式。这解释了为什么DF_SERVERLESS必须设为true:它决定了 Agent 的探测方式与扫描根目录。
网络出口配置
deepfence_shipper/config.go 表明MGMT_CONSOLE_URL_SCHEMA与MGMT_CONSOLE_PORT的默认值分别为https与443,与文档中推荐的配置一致;若 Console 使用 HTTP(端口80),则需显式设置MGMT_CONSOLE_URL_SCHEMA=http、MGMT_CONSOLE_PORT=80。
补充:EKS Fargate 场景的 Helm 参考实现
若你在 Amazon EKS 上使用 Fargate 配置(EKS Fargate 也是 Serverless 场景),仓库提供了参考 Helm Chart:deployment-scripts/helm-charts/eks-fargate/flask-echo-server。它的做法与 ECS Task Definition 本质相同:用 initContainer 把 Agent 镜像的/deepfence内容复制到共享emptyDir卷,业务容器以deepfence-entry-point-scratch.sh作为 command,并注入MGMT_CONSOLE_URL、MGMT_CONSOLE_PORT、DF_INSTALL_DIR=/deepfence、DF_SERVERLESS=true等环境变量(见 deployment.yaml),可作为理解"卷共享 + 入口编排"机制的补充样例。
验证与常见问题
部署完成后,可在管理控制台的传感器列表中看到对应 Fargate 节点上线。若未出现,请按以下顺序排查:
essential标记:Agent Sidecar 容器必须为essential: false,否则 Agent 启动失败会拖垮整个任务;- 启动依赖:应用容器应通过
dependsOn(condition: COMPLETE)等待 Agent 容器先完成,入口脚本中的sleep 20是为了等 Agent 服务就绪; - 网络与端口:Fargate 使用
awsvpc网络模式,需确保应用容器所在安全组能访问 Management Console 的443(或自定义端口),并正确设置MGMT_CONSOLE_URL_SCHEMA与MGMT_CONSOLE_PORT; - Secret 读取权限:确认任务执行角色已附加
AmazonECSTaskExecutionRolePolicy以及访问<API_KEY_SECRET_ARN>的secretsmanager:GetSecretValue权限(自定义 KMS 密钥还需kms:Decrypt); - JSON 格式:粘贴 Secret 内容时注意双引号是否被 AWS UI 转成特殊字符,导致 JSON 解析失败;
- 日志:通过 CloudWatch Logs 查看应用容器与 Agent 容器的
stdout(入口脚本会打印 "Deepfence agent started..." 等状态信息),快速定位启动链路中的失败点。
- 网络安全
- 应用安全
- 云原生
- 漏洞扫描
【免费下载链接】ThreatMapper
Open Source Cloud Native Application Protection Platform (CNAPP)
相关推荐
ThreatMapper 传感器部署指南:在 AWS ECS(EC2 Provider)上以 Task Definition + Daemon Service 方式安装 Agent
ThreatMapper 传感器部署指南:在 AWS ECS(EC2 Provider)上以 Task Definition + Daemon Service
网络安全应用安全云原生漏洞扫描ThreatMapper传感器部署指南:Docker、K8s和Fargate全攻略
ThreatMapper传感器部署指南:Docker、K8s和Fargate全攻略 ThreatMapper是开源云原生安全可观测性平台,为Linux、Kube
网络安全应用安全云原生漏洞扫描ThreatMapper 传感器(Sensor Agent)部署实战:从 Docker、Kubernetes 到 AWS 的完整安装指南
ThreatMapper 传感器(Sensor Agent)部署实战:从 Docker、Kubernetes 到 AWS 的完整安装指南 ThreatMappe
网络安全应用安全云原生漏洞扫描
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考