Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions services/aliyun__sas-vulnerability-management/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# aliyun-sas-vulnerability-management

Alibaba Cloud Security Center (SAS) Vulnerability Management service package.

## 支持版本

- **产品**: 阿里云安全中心 (Security Center / SAS)
- **API 版本**: `2018-12-03`
- **接入方式**: Alibaba Cloud OpenAPI (RPC, HMAC-SHA1 签名 V1)
- **API 端点**: `tds.{regionId}.aliyuncs.com`(中国区默认 `cn-shanghai`)

## 配置示例

```json
{
"regionId": "cn-shanghai",
"timeoutMs": 10000
}
```

```json
{
"accessKeyId": "<your-access-key-id>",
"accessKeySecret": "<your-access-key-secret>"
}
```

## 导入

```bash
octobus service import --id aliyun-sas ./services/aliyun__sas-vulnerability-management
```

## 方法说明

### 漏洞查询(4 个)

| RPC Method | CLI Command | 描述 |
|------------|-------------|------|
| `DescribeVulList` | `describe-vul-list` | 分页查询漏洞列表,支持按类型/等级/处理状态过滤 |
| `DescribeVulDetails` | `describe-vul-details` | 查询指定漏洞的详细信息(CVE、修复建议) |
| `DescribeUuidsByVulNames` | `describe-uuids-by-vul-names` | 根据漏洞名称查询受影响服务器 UUID |
| `DescribeCanFixVulList` | `describe-can-fix-vul-list` | 查询可修复的漏洞列表 |

### 漏洞操作(2 个)

| RPC Method | CLI Command | 描述 | 幂等 |
|------------|-------------|------|:--:|
| `ModifyOperateVul` | `modify-operate-vul` | 处理漏洞(修复/验证/忽略/取消忽略),oeprateType=`vul_fix\|verify\|ignore\|cancel_ignore` | ✅ |
| `OperateVuls` | `operate-vuls` | 批量修复 Linux 软件漏洞 | ✅ |

### 统计(2 个)

| RPC Method | CLI Command | 描述 |
|------------|-------------|------|
| `DescribeVulNumStatistics` | `describe-vul-num-statistics` | 漏洞数量统计(按严重等级和类型) |
| `DescribeVulFixStatistics` | `describe-vul-fix-statistics` | 漏洞修复统计 |

### 白名单(3 个)

| RPC Method | CLI Command | 描述 | 幂等 |
|------------|-------------|------|:--:|
| `DescribeVulWhitelist` | `describe-vul-whitelist` | 分页查询漏洞白名单 | — |
| `ModifyCreateVulWhitelist` | `modify-create-vul-whitelist` | 添加漏洞到白名单(不再告警) | ❌ 重复添加会创建多条 |
| `DeleteVulWhitelist` | `delete-vul-whitelist` | 按 ID 删除白名单条目 | ✅ |

### 应急漏洞(1 个)

| RPC Method | CLI Command | 描述 |
|------------|-------------|------|
| `DescribeEmgVulItem` | `describe-emg-vul-item` | 查询应急漏洞详情 |

## Config

| 字段 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `regionId` | string | `cn-shanghai` | SAS API 区域(中国区均映射到 cn-shanghai) |
| `timeoutMs` | integer | `10000` | HTTP 请求超时(毫秒) |

## Secret

| 字段 | 类型 | 必填 | 描述 |
|------|------|:--:|------|
| `accessKeyId` | string | ✅ | 阿里云 AccessKey ID |
| `accessKeySecret` | string | ✅ | 阿里云 AccessKey Secret |

## 错误映射

| 阿里云错误码 | gRPC 状态 |
|-------------|-----------|
| `InvalidAccessKeyId.*`, `SignatureDoesNotMatch` | `UNAUTHENTICATED` |
| `Forbidden.*` | `PERMISSION_DENIED` |
| `Invalid*`, `Missing*` | `INVALID_ARGUMENT` |
| `*NotFound*`, `*NotExist*` | `NOT_FOUND` |
| `Throttling*`, `LimitExceeded*` | `UNAVAILABLE` |
| HTTP 401/403 | `PERMISSION_DENIED` |
| HTTP 4xx | `FAILED_PRECONDITION` |
| HTTP 5xx | `UNAVAILABLE` |

## 写操作说明

### ModifyOperateVul
- **描述**: 对单条或多条漏洞执行操作
- **必填参数**: `type`(漏洞类型)、`operateType`(操作类型)、`info`(JSON 字符串,包含漏洞 ID 列表)
- **幂等性**: ✅ 重复修复同一漏洞不会重复消耗配额
- **回滚说明**: `ignore` 操作可通过 `cancel_ignore` 回滚;`vul_fix` 无法回滚
- **审计字段**: RequestId(请求追踪)、operateType(操作类型)、info(操作对象)

### OperateVuls
- **描述**: 批量修复 Linux 软件漏洞(cve 类型)
- **必填参数**: `type`、`operateType`、`uuids`(服务器 ID 列表)、`vulNames`(漏洞名称列表)
- **幂等性**: ✅ 重复修复已修复的漏洞为 no-op
- **回滚说明**: 修复操作不可回滚,建议先在测试环境验证
- **审计字段**: RequestId、type、vulNames(漏洞范围)、uuids(目标服务器)

### ModifyCreateVulWhitelist
- **描述**: 添加漏洞到白名单,Security Center 不再告警
- **必填参数**: `whitelist`(漏洞名称)、`reason`(加白原因)
- **可选参数**: `targetInfo`(仅对特定服务器生效,JSON 格式)
- **幂等性**: ❌ 重复调用会创建多条白名单记录
- **回滚说明**: 使用 `DeleteVulWhitelist` 按 ID 删除对应条目
- **审计字段**: RequestId、whitelist、reason

### DeleteVulWhitelist
- **描述**: 按 ID 列表删除白名单条目
- **必填参数**: `idList`(白名单 ID 数组,可通过 DescribeVulWhitelist 获取)
- **幂等性**: ✅ 删除已删除的条目无副作用
- **回滚说明**: 删除后需重新调用 ModifyCreateVulWhitelist 添加

## 风险说明

**读取操作(低风险)**:
- `Describe*` 方法仅查询数据,不会修改任何安全配置
- API 调用频率受阿里云默认限流控制(通常 100次/秒)

**写入操作(中风险)**:
- `ModifyOperateVul` / `OperateVuls`: 修复操作会触发服务器上的补丁安装,可能导致服务重启
- `ModifyCreateVulWhitelist`: 加白的漏洞不再告警,存在遗漏风险
- `DeleteVulWhitelist`: 删除后对应漏洞恢复告警,可能造成告警噪音
- 建议: 写入操作前先在控制台确认操作范围,批量操作建议分批次执行

**认证凭据风险**:
- AccessKey 需具备 SAS 权限(建议 `AliyunYundunSASReadOnlyAccess` 用于只读,`AliyunYundunSASFullAccess` 用于写入)
- 生产环境建议使用 RAM 子账号,遵循最小权限原则

## 建议 Capset

### `read` — 只读查询
```
DescribeVulList, DescribeVulDetails, DescribeUuidsByVulNames, DescribeCanFixVulList,
DescribeVulNumStatistics, DescribeVulFixStatistics, DescribeVulWhitelist, DescribeEmgVulItem
```
适用场景: SOC 分析、漏洞报表、态势感知

### `write` — 漏洞处置
```
ModifyOperateVul, OperateVuls, ModifyCreateVulWhitelist, DeleteVulWhitelist
```
适用场景: 漏洞修复工单、白名单管理

### `admin` — 完整权限
```
read + write 全部方法
```

## 测试

```bash
# 单元测试
node --test test/

# 真实 API 测试(需要 AKSK)
ACCESS_KEY_ID=xxx ACCESS_KEY_SECRET=yyy SAS_REGION=cn-shanghai node test/test-live.js
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env node
import { runServiceMain } from '@chaitin-ai/octobus-sdk';
import { service } from '../src/service.js';
runServiceMain(service);
17 changes: 17 additions & 0 deletions services/aliyun__sas-vulnerability-management/config.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "object",
"additionalProperties": true,
"properties": {
"regionId": {
"type": "string",
"default": "cn-shanghai",
"description": "Alibaba Cloud region ID. SAS API uses tds.{regionId}.aliyuncs.com. Note: most China regions map to tds.cn-shanghai.aliyuncs.com."
},
"timeoutMs": {
"type": "integer",
"minimum": 1,
"default": 10000,
"description": "HTTP request timeout in milliseconds"
}
}
}
12 changes: 12 additions & 0 deletions services/aliyun__sas-vulnerability-management/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "aliyun-sas-vulnerability-management",
"version": "0.0.0",
"private": true,
"type": "module",
"bin": {
"aliyun-sas-vulnerability-management": "bin/aliyun-sas-vulnerability-management.js"
},
"dependencies": {
"@chaitin-ai/octobus-sdk": "^0.5.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
syntax = "proto3";
package Aliyun_SAS_Vulnerability_Management;
option go_package = "miner/grpc-service/Aliyun_SAS_Vulnerability_Management";

import "google/protobuf/struct.proto";

service SASService {
rpc DescribeVulList(DescribeVulListRequest) returns (DescribeVulListResponse) {}
rpc DescribeVulDetails(DescribeVulDetailsRequest) returns (DescribeVulDetailsResponse) {}
rpc DescribeUuidsByVulNames(DescribeUuidsByVulNamesRequest) returns (DescribeUuidsByVulNamesResponse) {}
rpc DescribeCanFixVulList(DescribeCanFixVulListRequest) returns (DescribeCanFixVulListResponse) {}
rpc ModifyOperateVul(ModifyOperateVulRequest) returns (ModifyOperateVulResponse) {}
rpc OperateVuls(OperateVulsRequest) returns (OperateVulsResponse) {}
rpc DescribeVulNumStatistics(DescribeVulNumStatisticsRequest) returns (DescribeVulNumStatisticsResponse) {}
rpc DescribeVulFixStatistics(DescribeVulFixStatisticsRequest) returns (DescribeVulFixStatisticsResponse) {}
rpc DescribeVulWhitelist(DescribeVulWhitelistRequest) returns (DescribeVulWhitelistResponse) {}
rpc ModifyCreateVulWhitelist(ModifyCreateVulWhitelistRequest) returns (ModifyCreateVulWhitelistResponse) {}
rpc DeleteVulWhitelist(DeleteVulWhitelistRequest) returns (DeleteVulWhitelistResponse) {}
rpc DescribeEmgVulItem(DescribeEmgVulItemRequest) returns (DescribeEmgVulItemResponse) {}
}

// ---- DescribeVulList ----
message DescribeVulListRequest {
string type = 1;
repeated string uuids = 2;
string alias_name = 3 [json_name = "aliasName"];
string dealed = 4;
string severity = 5;
string group_id = 6 [json_name = "groupId"];
int32 current_page = 7 [json_name = "currentPage"];
int32 page_size = 8 [json_name = "pageSize"];
string lang = 9;
string attach_types = 10 [json_name = "attachTypes"];
string ids = 11;
int64 create_ts_start = 12 [json_name = "createTsStart"];
int64 create_ts_end = 13 [json_name = "createTsEnd"];
}
message DescribeVulListResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DescribeVulDetails ----
message DescribeVulDetailsRequest {
string type = 1;
string name = 2;
string alias_name = 3 [json_name = "aliasName"];
string lang = 4;
}
message DescribeVulDetailsResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DescribeUuidsByVulNames ----
message DescribeUuidsByVulNamesRequest {
string type = 1;
repeated string vul_names = 2 [json_name = "vulNames"];
string lang = 3;
}
message DescribeUuidsByVulNamesResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DescribeCanFixVulList ----
message DescribeCanFixVulListRequest {
string type = 1;
repeated string uuids = 2;
string alias_name = 3 [json_name = "aliasName"];
string dealed = 4;
repeated string status_list = 5 [json_name = "statusList"];
int32 current_page = 6 [json_name = "currentPage"];
int32 page_size = 7 [json_name = "pageSize"];
string lang = 8;
}
message DescribeCanFixVulListResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- ModifyOperateVul ----
message ModifyOperateVulRequest {
string type = 1;
string operate_type = 2 [json_name = "operateType"];
string info = 3;
}
message ModifyOperateVulResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- OperateVuls ----
message OperateVulsRequest {
repeated string uuids = 1;
string type = 2;
string operate_type = 3 [json_name = "operateType"];
repeated string vul_names = 4 [json_name = "vulNames"];
}
message OperateVulsResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DescribeVulNumStatistics ----
message DescribeVulNumStatisticsRequest {
string type = 1;
string resource_directory_account_id = 2 [json_name = "resourceDirectoryAccountId"];
}
message DescribeVulNumStatisticsResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DescribeVulFixStatistics ----
message DescribeVulFixStatisticsRequest {
}
message DescribeVulFixStatisticsResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DescribeVulWhitelist ----
message DescribeVulWhitelistRequest {
int32 current_page = 1 [json_name = "currentPage"];
int32 page_size = 2 [json_name = "pageSize"];
}
message DescribeVulWhitelistResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- ModifyCreateVulWhitelist ----
message ModifyCreateVulWhitelistRequest {
string whitelist = 1;
string reason = 2;
string target_info = 3 [json_name = "targetInfo"];
}
message ModifyCreateVulWhitelistResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DeleteVulWhitelist ----
message DeleteVulWhitelistRequest {
repeated string id_list = 1 [json_name = "idList"];
}
message DeleteVulWhitelistResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}

// ---- DescribeEmgVulItem ----
message DescribeEmgVulItemRequest {
string scan_type = 1 [json_name = "scanType"];
string lang = 2;
int32 current_page = 3 [json_name = "currentPage"];
int32 page_size = 4 [json_name = "pageSize"];
}
message DescribeEmgVulItemResponse {
int32 http_status = 1 [json_name = "httpStatus"];
string raw_body = 2 [json_name = "rawBody"];
google.protobuf.Value raw_json = 3 [json_name = "rawJson"];
}
Loading