This commit is contained in:
parent
32d7ad9a36
commit
580e0c775a
@ -6,24 +6,95 @@ if [ "$(id -u)" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
root_dir="${1:-$(cd "$(dirname "$0")/.." && pwd)}"
|
||||
install -d -m 0750 /var/lib/smail /run/smail /usr/local/lib/smail
|
||||
if ! getent group smail >/dev/null; then groupadd --system smail; fi
|
||||
if ! getent passwd smail >/dev/null; then useradd --system --gid smail --home-dir /var/lib/smail --shell /usr/sbin/nologin smail; fi
|
||||
chown smail:smail /var/lib/smail
|
||||
root_dir="$(realpath -e -- "${1:-$(dirname "$0")/..}")"
|
||||
runtime_dir=/opt/smail
|
||||
case "$(uname -m)" in
|
||||
x86_64) arch=amd64 ;;
|
||||
aarch64|arm64) arch=arm64 ;;
|
||||
*) echo "不支持的系统架构" >&2; exit 1 ;;
|
||||
esac
|
||||
install -o root -g root -m 0755 "$root_dir/out/backend/smail_linux_$arch" /usr/local/lib/smail/smail
|
||||
install -o root -g root -m 0750 "$root_dir/out/backend/smail-admin_linux_$arch" /usr/local/lib/smail/smail-admin
|
||||
|
||||
# 安装前先检查所有输入和运行状态,不能覆盖仍在运行的程序。
|
||||
for file in "$root_dir/out/backend/smail_linux_$arch" "$root_dir/out/backend/smail-admin_linux_$arch" \
|
||||
"$root_dir/deploy/systemd/smail.service" "$root_dir/deploy/systemd/smail-admin.service"; do
|
||||
if [ ! -f "$file" ] || [ -L "$file" ] || [ ! -s "$file" ]; then
|
||||
echo "安装输入不存在或不是普通文件:$file" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if systemctl is-active --quiet smail.service || systemctl is-active --quiet smail-admin.service; then
|
||||
echo "请先停止 Smail 主服务和管理员重置服务,安装不会自动中断现有业务。" >&2
|
||||
exit 1
|
||||
fi
|
||||
for process in /proc/[0-9]*/exe; do
|
||||
executable="$(readlink "$process" 2>/dev/null || true)"
|
||||
case "$executable" in
|
||||
"$runtime_dir/smail"|"$runtime_dir/smail (deleted)"|"$runtime_dir/smail-admin"|"$runtime_dir/smail-admin (deleted)")
|
||||
echo "部署目录中的程序仍在运行,请确认并停止后再安装。" >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
done
|
||||
if [ -L /opt ] || [ -L "$runtime_dir" ] || { [ -e "$runtime_dir" ] && [ ! -d "$runtime_dir" ]; }; then
|
||||
echo "部署路径不能是链接或普通文件。" >&2
|
||||
exit 1
|
||||
fi
|
||||
for directory in config data ssl log plugins; do
|
||||
target="$runtime_dir/$directory"
|
||||
if [ -L "$target" ] || { [ -e "$target" ] && [ ! -d "$target" ]; }; then
|
||||
echo "运行目录不能是链接或普通文件:$target" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
for target in "$runtime_dir/smail" "$runtime_dir/smail-admin" \
|
||||
/etc/systemd/system/smail.service /etc/systemd/system/smail-admin.service; do
|
||||
if [ -L "$target" ] || { [ -e "$target" ] && [ ! -f "$target" ]; }; then
|
||||
echo "程序或服务文件不能是链接或特殊文件:$target" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if [ -L /run/smail ] || { [ -e /run/smail ] && [ ! -d /run/smail ]; }; then
|
||||
echo "本机控制目录不能是链接或普通文件。" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -L /run/smail/admin-control.sock ] || { [ -e /run/smail/admin-control.sock ] && [ ! -S /run/smail/admin-control.sock ]; }; then
|
||||
echo "本机控制路径不是安全套接字。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 安装备份存放在系统备份目录,不在部署根目录遗留 .bak 文件。
|
||||
backup_dir="$(mktemp -d /var/backups/smail-deploy-XXXXXXXX)"
|
||||
for name in smail smail-admin; do
|
||||
if [ -f "$runtime_dir/$name" ]; then cp -p -- "$runtime_dir/$name" "$backup_dir/$name"; fi
|
||||
done
|
||||
for name in smail.service smail-admin.service; do
|
||||
if [ -f "/etc/systemd/system/$name" ]; then cp -p -- "/etc/systemd/system/$name" "$backup_dir/$name"; fi
|
||||
done
|
||||
|
||||
if ! getent group smail >/dev/null; then groupadd --system smail; fi
|
||||
if ! getent passwd smail >/dev/null; then useradd --system --gid smail --home-dir "$runtime_dir" --shell /usr/sbin/nologin smail; fi
|
||||
install -d -o root -g root -m 0755 "$runtime_dir"
|
||||
for directory in config data ssl log plugins; do
|
||||
target="$runtime_dir/$directory"
|
||||
# 内置插件在临时沙箱中展开,只兼容已存在的历史插件目录。
|
||||
if [ "$directory" = plugins ] && [ ! -d "$target" ]; then continue; fi
|
||||
install -d -o smail -g smail -m 0700 "$target"
|
||||
# 不跟随链接,也不越过挂载点;仅为本部署的存量运行数据调整属主。
|
||||
find -P "$target" -xdev \( -type d -o -type f \) -exec chown --no-dereference smail:smail {} +
|
||||
done
|
||||
install -d -o smail -g smail -m 0750 /run/smail
|
||||
if [ -S /run/smail/admin-control.sock ]; then
|
||||
# 从旧版 root 主服务迁移时保留残留套接字,由主程序验证失活后自行处理。
|
||||
chown --no-dereference smail:smail /run/smail/admin-control.sock
|
||||
fi
|
||||
install -d -o root -g root -m 0755 /run/systemd/ask-password
|
||||
install -o root -g root -m 0755 "$root_dir/out/backend/smail_linux_$arch" "$runtime_dir/smail"
|
||||
install -o root -g root -m 0700 "$root_dir/out/backend/smail-admin_linux_$arch" "$runtime_dir/smail-admin"
|
||||
install -o root -g root -m 0644 "$root_dir/deploy/systemd/smail.service" /etc/systemd/system/smail.service
|
||||
install -o root -g root -m 0644 "$root_dir/deploy/systemd/smail-admin.service" /etc/systemd/system/smail-admin.service
|
||||
chown smail:smail /run/smail
|
||||
chmod 0750 /run/smail
|
||||
systemctl daemon-reload
|
||||
systemctl enable smail
|
||||
# 清理旧版本可能留下的开机启动关系。smail-admin 单元没有 [Install],不能再次 enable。
|
||||
systemctl disable smail-admin >/dev/null 2>&1 || true
|
||||
echo "Smail 安装完成;smail-admin 仅允许按需执行 start/stop,不支持开机自启动。"
|
||||
echo "Smail 已安装到 $runtime_dir,旧程序和服务文件备份在 $backup_dir。"
|
||||
echo "配置、数据库和证书未覆盖;请使用 systemctl start smail 启动并检查运行状态。"
|
||||
echo "smail-admin 仅允许按需执行 start/stop,不支持开机自启动。"
|
||||
|
||||
@ -8,8 +8,8 @@ Type=oneshot
|
||||
RemainAfterExit=no
|
||||
User=root
|
||||
Group=root
|
||||
WorkingDirectory=/var/lib/smail
|
||||
ExecStart=/usr/local/lib/smail/smail-admin
|
||||
WorkingDirectory=/opt/smail
|
||||
ExecStart=/opt/smail/smail-admin
|
||||
Restart=no
|
||||
UMask=0077
|
||||
NoNewPrivileges=true
|
||||
@ -18,6 +18,8 @@ PrivateNetwork=true
|
||||
PrivateDevices=true
|
||||
ProtectHome=true
|
||||
ProtectSystem=strict
|
||||
# 密码代理只在本机临时目录收集无回显输入,不允许写入业务配置或数据库。
|
||||
ReadWritePaths=/run/systemd/ask-password
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelLogs=true
|
||||
@ -28,5 +30,5 @@ RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
TimeoutStartSec=30s
|
||||
TimeoutStartSec=180s
|
||||
TimeoutStopSec=5s
|
||||
|
||||
@ -7,9 +7,9 @@ Wants=network-online.target
|
||||
Type=simple
|
||||
User=smail
|
||||
Group=smail
|
||||
EnvironmentFile=/etc/smail/smail.env
|
||||
WorkingDirectory=/var/lib/smail
|
||||
ExecStart=/usr/local/lib/smail/smail
|
||||
Environment=SMAIL_ROOT=/opt/smail
|
||||
WorkingDirectory=/opt/smail
|
||||
ExecStart=/opt/smail/smail
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
RuntimeDirectory=smail
|
||||
@ -22,7 +22,7 @@ CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
PrivateTmp=true
|
||||
ProtectHome=true
|
||||
ProtectSystem=full
|
||||
ReadWritePaths=/var/lib/smail /run/smail
|
||||
ReadWritePaths=/opt/smail/config /opt/smail/data /opt/smail/ssl /opt/smail/log -/opt/smail/plugins /run/smail
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
32
docs/密码恢复实机验收.md
Normal file
32
docs/密码恢复实机验收.md
Normal file
@ -0,0 +1,32 @@
|
||||
# 密码恢复实机验收
|
||||
|
||||
## 本轮需求
|
||||
|
||||
- [~] 管理员、普通用户通过已验证外部邮箱及离线安全凭据恢复密码。
|
||||
- [~] 超级管理员登录后通过外部安全邮箱验证码修改密码。
|
||||
- [~] 超级管理员通过部署端受保护本机通道重置密码。
|
||||
- [!] 独立恢复域名与邮箱主域名联动:待确认是恢复指引入口还是新增网页重置入口,不能在确认前把本机通道暴露到公网。
|
||||
|
||||
## 当前实现边界
|
||||
|
||||
- 普通用户邮箱恢复通过后可以设置新密码。
|
||||
- 管理员邮箱恢复通过后仍需要未使用的离线恢复码。
|
||||
- 离线恢复需要密保问题、密保答案和离线恢复码,不是只填写一个安全码。
|
||||
- 超级管理员不能通过公开忘记密码接口恢复。登录后安全中心使用已验证外部邮箱验证码改密。
|
||||
- 改密成功会使旧会话和相关恢复、客户端凭据失效;测试后需要重新配置下一轮所需凭据。
|
||||
|
||||
## Linux 本机通道部署整改
|
||||
|
||||
- 部署根目录为 `/opt/smail`,配置、证书、数据和日志保持原位置。
|
||||
- 主服务使用 `smail` 系统账户,低端口仅通过 `CAP_NET_BIND_SERVICE` 授权。
|
||||
- `smail-admin` 使用 root 和系统服务上下文,仅通过 `/run/smail/admin-control.sock` 通信。
|
||||
- 恢复服务不允许开机自动运行,且只允许向本机密码代理临时目录写入交互请求。
|
||||
- 安装前拒绝覆盖运行中程序,旧程序和服务文件备份到 `/var/backups`,不覆盖业务配置、数据库或证书。
|
||||
|
||||
部署人员在可信终端执行 `systemctl start smail-admin`,并按密码代理提示无回显输入两次新密码;如终端没有收到提示,可在另一个可信终端执行 `systemd-tty-ask-password-agent --query`。不得把密码放到命令行、环境变量或日志里。
|
||||
|
||||
## 验收说明
|
||||
|
||||
Web 功能使用 MCP 模拟键鼠测试;终端仅用于源码检查、构建、部署以及本机重置工具本身的交互,不调用业务 API 或编写功能测试脚本。保留现有测试业务库,不清空邮件、账号或外部邮箱绑定。
|
||||
|
||||
具体测试结果记录到 `test-log/日期/测试log`;收到验证码、页面提示请求已受理、构建成功均不单独等于密码恢复闭环完成。
|
||||
Loading…
Reference in New Issue
Block a user