Skip to content

zhuxbo/sslctl

Repository files navigation

sslctl

SSL 证书部署工具,支持 Nginx、Apache,支持 Docker 容器。

安装

# 安装最新稳定版(参数传域名,脚本自动拼接 https://<host>/sslctl)
curl -fsSL https://release.example.com/sslctl/install.sh | sudo bash -s -- release.example.com

# 安装测试版
curl -fsSL https://release.example.com/sslctl/install.sh | sudo bash -s -- release.example.com --dev

# 安装指定版本
curl -fsSL https://release.example.com/sslctl/install.sh | sudo bash -s -- release.example.com --version 1.0.0

# 强制重新安装
curl -fsSL https://release.example.com/sslctl/install.sh | sudo bash -s -- release.example.com --force

Windows (PowerShell 管理员):

# 安装最新稳定版(一行命令)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object Net.WebClient).DownloadFile("https://release.example.com/sslctl/install.ps1", "$pwd\install.ps1"); powershell -ExecutionPolicy Bypass -File install.ps1

# 或者分步执行
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object Net.WebClient).DownloadFile("https://release.example.com/sslctl/install.ps1", "$pwd\install.ps1")
powershell -ExecutionPolicy Bypass -File install.ps1 -ReleaseHost release.example.com

# 更多参数
powershell -ExecutionPolicy Bypass -File install.ps1 -ReleaseHost release.example.com -Dev           # 安装测试版
powershell -ExecutionPolicy Bypass -File install.ps1 -ReleaseHost release.example.com -Version 1.0.0 # 安装指定版本
powershell -ExecutionPolicy Bypass -File install.ps1 -ReleaseHost release.example.com -Force         # 强制重新安装

注意

  • 第一行 SecurityProtocol 用于启用 TLS 1.2(PowerShell 5.1 默认未启用),Server 2019+ 可省略
  • 使用 WebClient.DownloadFile 而非 irm -OutFile,避免 PowerShell 5.1 编码转换导致中文乱码
  • -ExecutionPolicy Bypass 绕过脚本签名限制,仅影响当前执行
  • Windows Server 2012 R2 等老系统若 PowerShell 中看到空白或中文乱码:这是 PowerShell 默认 Raster Font(点阵字体)无法渲染 CJK 字符导致的,改字体即可修复——右键 PowerShell 窗口左上角图标 → 默认值 → 字体 → 选 Consolas 或 Lucida Console,关闭后重新打开窗口。cmd.exe 一般不受影响

手动安装: 从 Releases 下载解压,重命名为 sslctl

使用

一键部署(推荐)

sslctl setup --url https://api.example.com --token your-token --order 12345

自动完成:

  1. 检测 Web 服务器(Nginx/Apache)
  2. 获取证书信息并匹配站点
  3. 为未启用 SSL 的站点安装 HTTPS 配置(需确认,备份原配置,失败自动回滚)
  4. 部署证书到匹配的站点
  5. 安装守护服务(自动续签)

选项:

  • --local-key: 使用本机提交
  • --key <path>: 私钥文件路径(隐含 --local-key
  • --file-validation: 启用文件验证(隐含 --local-key
  • --webroot <path>: 文件验证的 Web 根目录(隐含 --file-validation
  • --yes: 跳过确认提示
  • --no-service: 不安装守护服务

扫描站点

sslctl scan              # 扫描所有站点
sslctl scan --ssl-only   # 仅扫描 SSL 站点

本地证书部署

# 部署本地证书文件到站点
sslctl deploy local --cert cert.pem --key key.pem --site example.com

# 带 CA 证书链部署(Apache 配置了 SSLCertificateChainFile 时需要)
sslctl deploy local --cert cert.pem --key key.pem --ca chain.pem --site apache-site.com

选项:

  • --cert: 证书文件路径(必需)
  • --key: 私钥文件路径(必需)
  • --ca: CA 证书链文件路径(Apache 配置了证书链路径时必需)
  • --site: 目标站点名称(必需,需先运行 sslctl scan

站点信息优先从 config.json 获取,回退到 scan-result.json

证书回滚

sslctl rollback --site example.com              # 回滚到最新备份
sslctl rollback --site example.com --list       # 查看备份列表
sslctl rollback --site example.com --version 20240101-120000  # 回滚到指定版本

回滚前会自动备份当前文件,包含符号链接防护。

其他命令:

sslctl deploy --cert example.com-12345                     # 部署指定证书
sslctl deploy --cert example.com-12345 --site example.com  # 绑定站点并部署
sslctl deploy --all                                  # 部署所有证书
sslctl status                                        # 查看服务状态(含证书过期详情)
sslctl upgrade                                       # 升级到最新版本
sslctl upgrade --check                               # 检查更新
sslctl service repair                                # 修复 systemd 服务
sslctl --debug scan                                  # 调试模式
sslctl uninstall                                     # 卸载(交互确认是否清理配置)

平台支持

平台 Nginx Apache 服务管理
Linux (systemd) systemd
Linux (OpenRC) OpenRC
Linux (SysVinit) SysVinit
Windows Windows Service

CI 覆盖 linux/amd64、linux/arm64、windows/amd64 三平台交叉编译验证。

支持 Docker 容器 Nginx(挂载卷/docker cp 双模式),自动检测本地或容器环境。

Debug 模式

# 启用调试模式
sslctl --debug deploy --site example.com
  • 详细日志输出(请求/响应、配置解析、文件操作)
  • 日志写入文件:/opt/sslctl/logs/debug/

工作目录

/opt/sslctl/
├── config.json     # 统一配置文件
├── certs/          # 证书存储
│   └── {server_name}/
│       ├── cert.pem
│       └── key.pem
├── pending-keys/   # 待确认私钥(本机提交)
├── logs/           # 日志文件
├── backup/         # 证书备份
└── scan-result.json  # 扫描结果缓存

安全特性

  • HTTPS 强制:远程 API 必须使用 HTTPS(仅 localhost 允许 HTTP)
  • SSRF 防护:阻止访问内网 IP(10/172.16/192.168)、未指定地址(0.0.0.0/::)和云元数据地址(169.254.169.254)
  • DNS Rebinding 防护:自定义 DialContext 在 TCP 连接时二次校验目标 IP
  • 命令白名单 + 超时:统一的 executor 包,只允许预定义命令,默认 30 秒超时,支持 Context 取消
  • 日志脱敏:自动过滤私钥、Bearer Token、Basic Auth、JSON 敏感字段、URL 参数;错误消息使用相对路径
  • 并发安全:配置读取返回深拷贝,mtime + SHA256 哈希检测外部修改自动重载,防止并发修改污染
  • 配置保存安全:拒绝写入符号链接目标,防止任意文件覆盖
  • 路径验证:Docker 容器路径参数严格验证,防止命令注入;挂载路径精确匹配防止误匹配
  • 备份 TOCTOU 保护:使用文件哈希校验检测并发修改,确保备份一致性;恢复时内部备份跳过清理,防止目标备份被删除;备份源文件符号链接检查,拒绝备份符号链接目标;siteName/timestamp 路径穿越防护
  • 扫描防护:Nginx/Apache/Docker 扫描器文件数量限制(1000)+ 深度限制(100)+ 文件大小限制(10MB),防止恶意配置耗尽资源
  • 升级安全:gzip 解压大小限制,防止 gzip 炸弹攻击;Ed25519 数字签名验证(按文件名索引签名,密钥环支持多公钥 + key ID,空密钥环拒绝验证,已配置公钥时拒绝未签名版本防止降级攻击),防止供应链攻击;先停服务再替换二进制,失败时恢复服务;Windows 上 rename 策略替换运行中 exe;安装时符号链接防护;临时文件保持 0600 仅在最终路径设置 0755;通道白名单防止路径遍历;密钥不匹配时提示用 install.sh 重装
  • 临时目录安全:临时目录权限设置为 0700
  • 日志目录安全:日志目录权限设置为 0700
  • 配置文件锁:文件锁在操作前获取,确保原子性和一致性
  • 部署回滚:部署失败自动回滚到备份(通过抽象层接口),回滚失败时提供手动恢复命令
  • 私钥保护:本机提交下,新私钥先保存到临时位置,签发成功后再替换;所有私钥写入统一使用 AtomicWrite
  • SELinux 兼容:部署后自动恢复文件安全上下文(restorecon),非 SELinux 环境静默跳过
  • IDN/Punycode 支持:域名匹配器自动转换国际化域名
  • 证书过期告警:守护进程周期检查证书过期时间,7 天/13 天阈值输出告警日志
  • 环境变量:支持通过环境变量配置敏感信息,避免明文存储

环境变量

变量 说明
SSLCTL_RELEASE_URL Release URL(安装脚本使用,完整 URL 含 https://)
SSLCTL_API_TOKEN API Token(覆盖所有证书的 API 配置)
SSLCTL_API_URL API URL(覆盖所有证书的 API 配置)
SSLCTL_LOG_FORMAT 日志格式:json 启用 JSON 输出

使用示例:

export SSLCTL_API_TOKEN="your-secret-token"
sslctl status

配置结构

config.json:

{
  "release_url": "https://release.example.com/sslctl",
  "schedule": {
    "renew_before_days": 13,
    "renew_mode": "pull"
  },
  "certificates": [
    {
      "cert_name": "example.com-12345",
      "order_id": 12345,
      "enabled": true,
      "domains": ["*.example.com", "example.com"],
      "api": {
        "url": "https://api.example.com",
        "token": "your-deploy-token"
      },
      "renew_mode": "pull",
      "bindings": [
        {
          "server_name": "www.example.com",
          "server_type": "nginx",
          "enabled": true,
          "paths": {
            "certificate": "/opt/sslctl/certs/www.example.com/cert.pem",
            "private_key": "/opt/sslctl/certs/www.example.com/key.pem"
          }
        }
      ]
    }
  ]
}

注意:API 配置在证书级别,每个证书可以使用不同的 API 来源。

schedule 字段说明

字段 类型 默认值 说明
renew_before_days int 13 提前续期天数,最大 13,0 使用默认值
renew_mode string pull 全局续签模式,证书级别可覆盖

config.json.lock

保存配置时自动创建的文件锁(flock),防止多个 sslctl 进程同时写入 config.json 导致数据损坏。无需手动管理。

续签模式

两种模式统一:renew_before_days 最大 13 天,默认 13 天。

模式 说明 默认值
local 本机提交,本地生成私钥和 CSR 13 天
pull 自动签发,从服务端拉取已签发证书 13 天
  • 本机提交:由本地控制私钥,通过 POST 部署接口提交本地生成的 CSR
  • 自动签发:查询已签发的证书直接部署
  • 定时检查:每天一次,随机选择明天 09:0023:59 的时间点执行;多证书续签间随机延迟 3090 秒
  • 已过期证书不再触发续签

API 接口

方法 路径 说明
GET /api/deploy?order_id=xxx 按订单 ID 查询(推荐)
GET /api/deploy?domain=xxx 按域名查询(首次获取 order_id)
POST /api/deploy 更新/续费证书(需要 order_id)
POST /api/deploy/callback 部署结果回调

认证方式:Authorization: Bearer {deploy_token}

Docker 支持

sslctl scan              # 自动检测本地或 Docker
sslctl deploy --site example.com  # 根据配置选择部署方式

Docker 站点配置添加 docker 字段:

{
  "docker": {
    "enabled": true,
    "compose_file": "/opt/app/docker-compose.yml",
    "service_name": "nginx",
    "deploy_mode": "auto"
  }
}

部署模式:volume(挂载卷)、copy(docker cp)、auto(自动检测)

开发测试

# 运行单元测试
go test -v ./...

# 运行测试并查看覆盖率
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out | grep total

# Linux 发行版服务管理测试(需要 Docker)
bash build/test-linux.sh

容器端到端测试

# 运行全部 E2E 测试(构建 + 全矩阵)
bash docker/test/scripts/run-tests.sh

# 指定发行版和服务器
bash docker/test/scripts/run-tests.sh --distro ubuntu --server nginx

# 指定测试文件(不含 .bats 后缀)
bash docker/test/scripts/run-tests.sh --test scan

# Docker-in-Docker 测试
bash docker/test/scripts/run-tests.sh --dind

# 跳过构建(已构建过镜像)
bash docker/test/scripts/run-tests.sh --no-build

测试矩阵:Nginx/Apache × Ubuntu/Debian/Alpine/Rocky + DinD,使用 Mock API 离线运行。

测试用例:setup、deploy、deploy-local、scan、status、rollback、daemon、upgrade、uninstall、docker-scan(共 10 个 bats 文件,docker-scan 在 DinD 容器中运行,uninstall 自动排最后执行)。

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors