Metadata-Version: 2.4
Name: salt-fga
Version: 0.1.4
Requires-Python: >=3.12
Requires-Dist: openfga-sdk>=0.9.9
Requires-Dist: requests>=2.32.5
Requires-Dist: rich>=14.3.3
Description-Content-Type: text/markdown

# Salt CLI

Salt CLI 是一个用于执行 SaltStack CherryPy REST API 的命令行工具，提供简洁的命令行接口和美化的输出，并集成了基于 OpenFGA 的权限控制系统。

**完全兼容原生 Salt 命令格式！**

## 安装

```bash
git clone <repository-url>
cd salt
uv sync
./.venv/bin/salt-fga <command>
```

## 快速开始

### 命令格式

```bash
salt-fga [全局选项] 'target' module.function [args...]
```

### 基本示例

```bash
# 测试连接
salt-fga 'minion-01' test.ping

# 执行命令
salt-fga 'minion-01' cmd.run 'uptime'

# 获取系统信息
salt-fga 'minion-01' grains.get os
salt-fga 'minion-01' grains.items

# 使用通配符
salt-fga 'web-*' test.ping
salt-fga '*' test.ping

# 指定集群
salt-fga -c prod 'minion-01' test.ping

# 状态管理
salt-fga 'web-*' state.apply webserver
salt-fga 'minion-01' state.sls nginx

# 包管理
salt-fga 'minion-01' pkg.install nginx
salt-fga 'minion-01' pkg.remove nginx

# 服务管理
salt-fga 'minion-01' service.start nginx
salt-fga 'minion-01' service.restart nginx
salt-fga 'minion-01' service.status nginx

# 文件操作
salt-fga 'minion-01' file.read /etc/hosts
salt-fga 'minion-01' file.write /tmp/test.txt 'hello world'

# 用户管理
salt-fga 'minion-01' user.list_users
salt-fga 'minion-01' user.info root
```

## 配置

### 集群配置：`~/.config/salt/credentials.json`

```json
[
  {
    "name": "prod",
    "description": "saltproject 生产环境",
    "base_url": "https://salt-api.example.com",
    "username": "saltadmin",
    "password": "your-password",
    "eauth": "file",
    "token_expire": "10h"
  }
]
```

字段说明：

- `name`: 环境名称，对应 `-c` 参数
- `base_url`: Salt CherryPy REST API 地址
- `eauth`: 认证方式（`file`、`pam`、`ldap`）
- `token_expire`: Token 过期时间（`10h`、`30m`、`60s`）

## 全局参数

| 参数            | 说明                               |
| --------------- | ---------------------------------- |
| `-c, --cluster` | 指定集群环境名称（默认使用第一个） |
| `--raw`         | 输出原始 JSON，不美化              |

## 支持的 Salt 模块

salt-fga 支持所有标准 Salt 模块，包括但不限于：

### 测试和诊断
- `test.ping` - 测试 minion 连接
- `test.version` - 查看 Salt 版本

### 命令执行
- `cmd.run` - 执行 shell 命令
- `cmd.script` - 执行脚本
- `cmd.exec_code` - 执行代码

### 系统信息
- `grains.get` - 获取指定 grain
- `grains.items` - 获取所有 grains
- `status.diskusage` - 磁盘使用情况
- `status.meminfo` - 内存信息

### 状态管理
- `state.apply` - 应用状态
- `state.sls` - 应用指定 SLS
- `state.highstate` - 执行 highstate

### 包管理
- `pkg.install` - 安装包
- `pkg.remove` - 删除包
- `pkg.upgrade` - 升级包
- `pkg.list_pkgs` - 列出已安装的包

### 服务管理
- `service.start` - 启动服务
- `service.stop` - 停止服务
- `service.restart` - 重启服务
- `service.status` - 查看服务状态
- `service.enable` - 启用服务
- `service.disable` - 禁用服务

### 文件操作
- `file.read` - 读取文件
- `file.write` - 写入文件
- `file.copy` - 复制文件
- `file.remove` - 删除文件

### 用户管理
- `user.list_users` - 列出用户
- `user.info` - 查看用户信息
- `user.add` - 添加用户
- `user.delete` - 删除用户



## 权限系统（OpenFGA）

Salt CLI 集成 OpenFGA 进行细粒度权限控制。**未配置 OpenFGA 时，所有命令自动放行。**

### 开发/测试环境设置

在开发和测试环境中，可以使用 Makefile 快速设置 OpenFGA：

```bash
# 1. 启动 OpenFGA 服务（Docker）
make openfga-up

# 2. 初始化 store 和 model（自动更新配置文件）
make openfga-init

# 3. 停止服务
make openfga-down
```

详细说明请参考 [scripts/README.md](scripts/README.md)。

### 生产环境配置

在生产环境中，OpenFGA 应该由运维团队独立部署和管理。Salt CLI 只需要配置文件：

**`~/.config/salt/openfga.json`**

```json
{
  "api_url": "http://localhost:8080",
  "store_id": "01KKG94CBB7430H0GZ2RBW6GMA",
  "authorization_model_id": "01KKG94CCVE0ZXBZZPSV6YB9S8"
}
```

### 权限管理

权限管理通过 OpenFGA CLI (`fga`) 或 OpenFGA API 直接操作，不通过 salt-fga 命令。

#### 添加用户到集群

```bash
# 使用 fga CLI 添加用户为集群成员
fga tuple write --store-id <store_id> \
  '[{"user":"user:alice","relation":"member","object":"cluster:prod"}]'

# 添加用户为集群管理员
fga tuple write --store-id <store_id> \
  '[{"user":"user:alice","relation":"admin","object":"cluster:prod"}]'
```

#### 授予主机访问权限

```bash
# 授予用户访问特定主机的权限（所有命令）
fga tuple write --store-id <store_id> \
  '[{"user":"user:alice","relation":"can_access","object":"target:prod/web-01"}]'

# 授予用户访问所有主机的权限
fga tuple write --store-id <store_id> \
  '[{"user":"user:alice","relation":"can_access","object":"target:prod/*"}]'
```

#### 授予命令执行权限

```bash
# 授予用户在特定主机执行特定命令的权限
fga tuple write --store-id <store_id> \
  '[{"user":"user:alice","relation":"can_execute","object":"target_cmd:prod/web-01/ping"}]'

# 授予用户在所有主机执行特定命令的权限
fga tuple write --store-id <store_id> \
  '[{"user":"user:alice","relation":"can_execute","object":"target_cmd:prod/*/cmd"}]'
```

#### 查看权限

```bash
# 查看用户的所有权限
fga tuple read --store-id <store_id> --user "user:alice"

# 查看特定对象的权限
fga tuple read --store-id <store_id> --object "cluster:prod"
```

#### 撤销权限

```bash
# 撤销权限
fga tuple delete --store-id <store_id> \
  '[{"user":"user:alice","relation":"can_access","object":"target:prod/web-01"}]'
```

### 权限模型说明

用户执行命令需同时满足：

1. 是目标集群的成员（`member of cluster:xxx`）
2. 有访问目标主机的权限（`can_access on target:xxx`）或有执行特定命令的权限（`can_execute on target_cmd:xxx`）

**权限检查逻辑：**
- 如果用户有 `can_access` 权限，可以在该主机上执行所有命令（非限制模式）
- 如果用户只有 `can_execute` 权限，只能执行特定命令（限制模式）
- 支持通配符 `*` 表示所有主机

**Object ID 格式：**
- 集群：`cluster:<name>`（如 `cluster:prod`）
- 主机：`target:<cluster>/<hostname>`（如 `target:prod/web-01`、`target:prod/*`）
- 命令：`target_cmd:<cluster>/<hostname>/<command>`（如 `target_cmd:prod/web-01/ping`、`target_cmd:prod/*/cmd`）

### 环境变量

| 变量               | 说明             | 默认值 |
| ------------------ | ---------------- | ------ |
| `COPAW_USER_ID`    | 当前用户 ID      | 无     |
| `COPAW_USERNAME`   | 当前用户名       | 无     |
| `COPAW_SESSION_ID` | 当前会话 ID      | 无     |
| `COPAW_CHANNEL`    | 当前渠道（如 wecom） | 无     |

使用 `salt-fga user info` 命令可以查看当前环境变量的设置状态。

## Token 管理

Token 自动缓存到 `~/.config/salt/tokens/<cluster_name>.json`，过期时自动刷新，遇到 401 自动重试。

## 开发

```bash
# 安装开发依赖
uv sync --group dev

# 单元测试（不依赖外部服务）
make test

# 集成测试（需要已配置的 Salt API 环境）
make test-integration

# OpenFGA 模型测试
make openfga-test

# 安装 Cursor Skill
make skill-install
```
make skill-install
```

## 架构说明

详细的架构说明请参考 [CLAUDE.md](./CLAUDE.md)。
