threatgrid/ctia
GitHub: threatgrid/ctia
这是一个由思科开源的、务实且可运营化的威胁情报服务,旨在提供简单易用的 REST/GraphQL API 以存储、检索及共享可行动的威胁数据。
Stars: 73 | Forks: 26
[](https://travis-ci.org/threatgrid/ctia)
# Cisco Threat Intel API
一个务实、可运营化的威胁情报服务和数据模型
完整文档请参阅 [文档](resources/ctia/public/doc/)
我们也认为 [用例](resources/ctia/public/doc/use_cases.md) 文档是一个很好的
起点。
一旦运行,API 的交互式 Swagger 文档即可通过以下地址访问:
```
http://localhost:3000/index.html
```
## 目标
* 共享可操作的威胁情报
* 简单、务实的数据模型
* 易于集成和探索
* 极快的 Verdict(判定)查找
* 与其他服务的超文本集成
这不是一个完整的 STIX/TAXII 服务。其目的是帮助
分析师了解什么是重要的,并让检测和预防
工具知道要寻找什么。
除了 RESTful HTTP API 外,它还具有 GraphQL API 和许多事件处理程序。
数据模型在 [CTIM](https://github.com/threatgrid/ctim) 项目中定义,
尽管在运行后,使用内置的 [Swagger UI](http://localhost:3000/index.html)
很容易查看 API 及其处理的模型。
CTIA 使用 [Clojure](http://clojure.org) 实现
## 使用
### 数据存储和外部依赖
CTIA 使用 Leiningen 作为其“构建”工具,您可以按照此处的说明进行安装:http://leiningen.org/#install
默认情况下,CTIA 使用 Elasticsearch 5.x 作为其数据存储。假设您
在 127.0.0.1:9200 上运行它,您可以简单地启动
CTIA。
您可以跳转到 [开发](#Development) 部分查看有关
如何使用 Docker 运行 elasticsearch 和其他可选支持工具的说明。
CTIA 可能使用 Kafka、Redis 和 ES 来推送事件。
CTIA 支持 Java 21。
#### 清除 ES 存储
使用 uberjar 构建,您可以使用以下命令清除所有 ES 存储:
`java -cp ctia.jar:resources:. clojure.main -m ctia.task.purge-es-stores`
使用 lein 请使用此命令:
`lein run -m ctia.task.purge-es-stores`
### 在本地运行应用程序
从克隆的仓库运行:
`lein run -m ctia.main`
### 打包并作为独立 jar 运行
这是在生产环境中运行此程序的正确方式。
```
lein do clean, uberjar
java -Xmx4g -Djava.awt.headless=true -Dlog.console.threshold=INFO -jar target/ctia.jar
```
您可以根据需要调整 java 参数。
## 开发
最简单的启动方式是使用 `docker`。
在 Mac OS X 上,您应该使用
[Docker for Mac](https://docs.docker.com/docker-for-mac/),它
包含运行 Docker 容器所需的所有依赖项。
**由于 Kafka 和 Zookeeper 现已成为开发集群的一部分,您需要
增加分配给 Docker 的内存。您可以通过
Docker 偏好设置进行此操作。这已在 6GB 分配下
测试通过。**
我们提供了一个默认的 `containers/dev/docker-compose.yml`,它将
在容器中启动您所需的依赖项。
您可以启动开发环境:
```
# 仅适用于 M1 mac,仅需构建一次
docker compose -f containers/dev/docker-compose.yml -f containers/dev/m1-docker-compose.yml build
docker compose -f containers/dev/docker-compose.yml up
```
使用 Docker for Mac,这会将开发机器上的以下端口绑定到容器中运行的服务:
* Redis - 6379
* elasticsearch5 - 9205 和 9305
* elasticsearch7 - 9207 和 9307
* kibana - 5601
* zookeeper - 2181
* kafka - 9092
* riemann - 5555-5557
* riemann-dash - 4567
* aws - 4566
如果您需要重置整个开发环境,
只需终止 docker compose 进程并运行:
```
docker compose -f containers/dev/docker-compose.yml down
docker compose -f containers/dev/docker-compose.yml up --force-recreate --remove-orphans
```
特别是,这会重置 ElasticSearch 索引,因为它们无法
被多次创建。
### 本地工作流
要在本地启动 CTIA,首先通过取消注释 `resources/ctia-default.properties` 中以 `ctia.store.es.default.auth` 开头的行来配置本地开发的 ES 认证。然后对于 ES5 使用 `./scripts/run`,对于 ES7 使用 `./scripts/run7`。
要运行测试,对于所有非集成测试使用 `./scripts/test`,对于仅 ES7 的非集成测试使用 `./scripts/test7`。
对于 REPL 工作流,运行 `lein repl`。使用 `(start)` 启动 CTIA,
`(stop)` 停止它,使用 `(go)` 重启 ES5 --- 对于 ES7,请在每个名称后追加 `7`。
### 测试和 CI
所有 PR 必须通过 `lein test` 且无失败才能被接受。
任何新的代码功能/更改都应附带测试。
PR 使用 GitHub Actions 构建和部署。
要跳过 PR 提交的 CI,请在提交消息中使用 [[skip ci]](https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/)
。由于分支保护规则,一旦您准备好
合并您的 PR,必须完成完整的构建。当您为压缩的 PR 选择
最终提交消息时,请注意
Travis 也支持在某些提交消息上跳过 CI——换句话说,
某些提交消息可能会跳过部署。
要在 PR 上运行更严格的 cron 作业(多 JVM/Clojure 矩阵),请以 `{:test-suite :cron}` 开始提交消息。
### 测试平衡
持续集成测试运行使用 `dev-resources/ctia_test_timings.edn` 中的先前计时信息进行并行化。
对于 GitHub Actions Pull Requests,测试通过
访问先前构建的缓存自动平衡。
要在本地试验此功能,您需要本地仓库中的计时数据。
有两种生成它们的方法,在以下小节中描述:
1. 本地(慢)
2. 通过下载最近构建的 GitHub Actions artifact(快)。
#### 本地重新平衡测试(慢)
1. 运行 `./build/run-tests.sh` 获取最新的测试计时。
2. 运行 `./scripts/summarize-tests.clj` 收集计时
3. 运行 `cp target/test-results/all-test-timings.edn dev-resources/ctia_test_timings.edn`
以更新最新的计时。
4. 提交此更改并推送。
#### 通过 GitHub Actions 重新平衡测试(快)
您需要一个已完成的 GitHub Actions Pull Request 构建作为基础。
1. 访问您想用来重新平衡的 GitHub Actions Pull Request 构建
- 例如,https://github.com/threatgrid/ctia/actions/runs/342562872
2. 转到 `all-pr-checks` 作业(应该是最后一个作业)并下载 `all-test-timings` artifact
3. 解压下载的文件并找到解压后的 `all-test-timings.edn` 文件。
4. 将解压后的 `all-test-timings.edn` 文件复制到 `dev-resources/ctia_test_timings.edn`
5. 提交此更改并推送。
注意:不幸的是,即使是公共 artifacts 也需要 API 密钥才能通过 API 下载,
因此这并不容易自动化
([查看更多](https://github.com/actions/upload-artifact/issues/51))。
### 数据访问控制
文档访问控制在文档级别定义,规则默认使用 TLP 结合 max-record-visibility 属性(交通信号灯协议)定义:
#### 所有人 最大记录可见性
##### 绿色/白色 TLP
| 身份 | 读取 | 写入 |
|-----------|----------|----------|
| 所有者 | ✔ | ✔ |
| 组/组织 | ✔ | ✔ |
| 其他人 | ✔ | |
#### 琥珀色 TLP
| 身份 | 读取 | 写入 |
|-----------|----------|----------|
| 所有者 | ✔ | ✔ |
| 组/组织 | ✔ | ✔ |
| 其他人 | | |
#### 红色 TLP
| 身份 | 读取 | 写入 |
|-----------|----------|----------|
| 所有者 | ✔ | ✔ |
| 组/组织 | | |
| 其他人 | | |
#### 组 最大记录可见性
##### 绿色/白色 TLP
| 身份 | 读取 | 写入 |
|-----------|----------|----------|
| 所有者 | ✔ | ✔ |
| 组/组织 | ✔ | ✔ |
| 其他人 | | |
#### 琥珀色 TLP
| 身份 | 读取 | 写入 |
|-----------|----------|----------|
| 所有者 | ✔ | ✔ |
| 组/组织 | ✔ | ✔ |
| 其他人 | | |
#### 红色 TLP
| 身份 | 读取 | 写入 |
|-----------|----------|----------|
| 所有者 | ✔ | ✔ |
| 组/组织 | | |
| 其他人 | | |
#### 自定义访问规则
可以使用 `authorized_users` 或 `authorized_groups` 文档字段向任何用户/组授予额外访问权限,当一个身份被标记在这些字段中时,
它将获得对文档的完整读/写访问权限。
请注意,`authorized_groups` 属性可能仅在最大记录可见性设置为 `everyone` 时有效
示例:
以下 actor 实体被标记为 `Red`,因此仅允许其所有者进行读写访问,
因为 "foo" 和 "bar" 被标记为 `authorized_users`,这些身份的所有者也拥有读写访问权限。
```
{"id": "actor-5023697b-3857-4652-9b53-ccda297f9c3e",
"type": "actor",
"schema_version": "0.4.2",
"actor_type": "Hacker",
"confidence": "High",
"source": "a source",
"tlp": "red",
"valid_time": {},
"authorized_users": ["foo" "bar"]}
```
以下 actor 实体被标记为 `Amber`,因此仅允许其所有者或组进行读写访问,
因为 "foogroup" 和 "bargroup" 被标记为 `authorized_groups`,这些组中的身份也将获得完整的读写访问权限。
```
{"id": "actor-5023697b-3857-4652-9b53-ccda297f9c3e",
"type": "actor",
"schema_version": "0.4.2",
"actor_type": "Hacker",
"confidence": "High",
"source": "a source",
"tlp": "red",
"valid_time": {},
"authorized_groups": ["foogroup" "bargroup"]}
```
## Bulk 和 Bundle
CTIA 提供 Bulk 和 Bundle 路由以帮助处理多个实体。
请参阅 [Bulk 和 Bundle 文档](resources/ctia/public/doc/bulk-bundle.org)
### Bundle 导入
`/bundle` API 端点允许拥有正确权限的用户 POST 一个 CTIM [bundle object](https://github.com/threatgrid/ctim/blob/master/src/ctim/schemas/bundle.cljc)。
发布 bundle 的能力由 `import-bundle` 权限控制。
提交 bundle 时:
1. 搜索所有已使用前缀通过 `ctia.store.external-key-prefixes` 属性配置的外部 ID 导入的实体。
2. 如果它们通过瞬态 ID 标识,则会建立瞬态 ID 与存储 ID 之间的映射表。
3. 仅以与 `/bulk` API 端点相同的方式创建新实体,并进行瞬态 ID 解析。现有实体不会被修改。
如果多个实体引用同一个外部 ID,则选取检索到的第一个。
Bundle API 端点的响应:
```
{:results [{:id "http://example.com/ctia/entity-type/entity-type-991d8dfb-b54e-4435-ac58-2297b4d886c1"
:tempid "transient:1f48f48c-4130-47f1-92dc-a6df8ab110b6"
:action "create"
:external_id "indicator-abuse-ch-077d653844d95d8cd8e4e51cb1f9215feae50426"
:error "An error occurs"}]
```
| 字段 | 描述 |
|----------------|----------------------------------------------------------|
| `:id` | 真实 ID |
| `:original_id` | 如果与真实 ID 不同则提供的 ID(例如:瞬态 ID) |
| `:result` | `error`, `created` 或 `exists` |
| `:external_id` | 用于标识实体的外部 ID |
| `:error` | 错误消息 |
### Feeds
CTIA 允许生成 Feed 作为公共 URL,旨在通过跳过身份验证的视图轻松交换数据。您可以使用此功能生成可被简单系统轻松使用的阻止列表。
第一种 `Feed` 是 `Indicator` 类型,您可以通过发布一个指定 `indicator_id` 和 `output` 类型的 `Feed` 文档来创建它。
CTIA 随后将返回已实现的 `Feed` 文档,包含两个新字段:`feed_view_url` 和 `feed_view_url_csv`
- 这两个 URL 将无需认证即可公开访问,因此必须谨慎共享。
- 这两个 URL 都通过它们的关系返回与提供的 `indicator_id` 关联的 Judgements
- 根据选择的 `output`,它将仅提取并返回 observable 或完整的 Judgements
- CSV 视图输出根据 `output` 设置,要么输出完整的 `Judgement` CSV,要么仅输出 Observable 值。
### Elasticsearch 存储管理
请参阅 [CTIA Elasticsearch Stores: managing big Indices](resources/ctia/public/doc/es_stores.md)
请参阅 [Migration procedure](resources/ctia/public/doc/migration.md)
请参阅 [CTIA Elasticsearch CRUD details](resources/ctia/public/doc/es_stores.pdf)
### 存储检查
有一个专门的任务用于检查已配置 CTIA 实例的所有存储。
此任务将遍历所有已配置的存储并批量验证每个文档。
使用以下命令启动任务:
`java -cp ctia.jar:resources:. clojure.main -m ctia.task.check-es-stores `
或使用 leiningen 从源码运行:
`lein run -m ctia.task.check-es-stores `
#### 任务参数
| 参数 | 描述 | 示例 |
|------------|----------------------------------------|---------|
| batch-size | 一次验证多少文档 | 1000 |
#### API
##### 列表分页
提供列表的 HTTP 路由默认使用 100 条记录的限制。
API 客户端可以将此参数更改为最多 10 0000 条记录。
当响应应用限制时,将返回分页标头:
| 标头 | 描述 | 示例 |
|------------|--------------------------------------------------------------------------------|------------------------------------------------|
| X-TOTAL | 数据存储中的总数 | 5000 |
| X-OFFSET | 当前的分页偏移量 | 200 |
| X-NEXT | 用于获取下一页结果的现成参数 | limit=100&offset=100&search_after=foo |
| X-PREVIOUS | 用于获取上一页结果的现成参数 | limit=100&offset=0 |
| X-SORT | 与 `search_after` 一起使用的排序参数,最后一页结果的 ID | ["actor-77b01a42-6d2b-4081-8fd0-c887bf54140c"] |
| | | |
要轻松滚动浏览列表的所有结果,只需迭代并将 `X-Next` 附加到您的基础查询 URL。
如果不存在 `X-Next` 标头,则您已到达最后一页。
##### 偏移分页
用于简单情况,当结果窗口小于 10 000 (`offset` + `limit`) 时,
结合使用 `offset` 和 `limit` 参数对结果进行分页。
#### 无状态游标分页
用于结果窗口大于 `10 000` 的情况,允许轻松循环遍历查询响应的所有页面。
使用 `limit` 和 `offset` 以及用 `X-Sort` 响应标头的值填充的 `search_after` 来获取下一页。
#### 速率限制
可以通过使用 `ctia.http.rate-limit.enabled` 属性启用中间件来对请求进行速率限制。
它限制一个 CTIA 组在一小时内可以发出的 HTTP 请求数量。该组通过当前 Ring 请求的 :identity 属性进行标识。
在达到速率限制之前,响应中会返回标头 `X-Ratelimit-Group-Limit`:
```
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Date: Wed, 31 Oct 2018 14:05:30 GMT
Server: Jetty(9.4.z-SNAPSHOT)
Strict-Transport-Security: max-age=31536000; includeSubdomains
Vary: Accept-Encoding, User-Agent
X-Ctim-Version: 1.0.6
X-Ctia-Config: b9b3477528d9616ed85221f2827bf1da443e8f00
X-Ctia-Version: 70323eb3b72da558e7f056e418533402f65d335a
X-Ratelimit-Group-Limit: 8000
```
如果超过速率限制:
- 客户端收到带有 429 HTTP 状态、`retry-after` 标头和 JSON 消息 `{"error": "Too Many Requests"}` 的响应。retry-after 标头指示在发出新请求之前等待的秒数。
```
HTTP/1.1 429 Too Many Requests
Content-Length: 30
Content-Type: application/json
Date: Wed, 31 Oct 2018 14:05:30 GMT
Retry-After: 3557
Server: Jetty(9.4.z-SNAPSHOT)
Strict-Transport-Security: max-age=31536000; includeSubdomains
X-Ctim-Version: 1.0.6
X-Ctia-Config: b9b3477528d9616ed85221f2827bf1da443e8f00
X-Ctia-Version: 70323eb3b72da558e7f056e418533402f65d335a
```
- 记录一条 :info 级别的消息
### 更新索引状态任务
有一个专门的任务用于在启动时更新 ES 索引状态。它执行 CTIA 启动前所需的 ES 映射和设置的幂等
更改。
理论上,此任务可以在 CTIA 启动时自动执行,但在 CTIA 跨多个实例负载均衡的情况下,
这会导致性能问题,因为所有实例
将同时更新 ES。因此将其分离出来。
必须通过以下方式成功完成此任务才能启动 CTIA:
```
java -cp ctia.jar:resources:. clojure.main -m ctia.task.update-index-state
```
或使用 leiningen 从源码运行:
```
lein run -m ctia.task.update-index-state
```
# 常见问题 (FAQ)
问:在本地运行 CTIA 时,如何停止看到 `Unauthorized ES request`?
答:取消注释 `resources/ctia-default.properties` 中的以下行
```
ctia.store.es.default.auth.type=basic-auth
ctia.store.es.default.auth.params.user=elastic
ctia.store.es.default.auth.params.pwd=ductile
```
## 许可证
Copyright © 2015-2022 Cisco Systems
Eclipse Public License v1.0
## 数据模型
CTIA 的数据模型紧密基于
[STIX](http://stixproject.github.io/data-model/),并有一些
简化。详情请参阅 [Cisco Threat Intel Model](https://github.com/threatgrid/ctim/tree/master/doc/)。
标签:AMSI绕过, API, Cisco, Clojure, DNS解析, Docker, Elasticsearch, GraphQL, JS文件枚举, Kafka, Leiningen, Redis, RESTful, SonarQube插件, STIX, Swagger, Verdict Lookup, 威胁情报, 威胁检测, 安全防御评估, 开发者工具, 开源项目, 情报共享, 搜索引擎查询, 数据模型, 网络安全, 请求拦截, 隐私保护