移除SSH密钥入口并收紧密码认证边界
删除未注册的密钥 CLI、HTTP 处理和前端残留样式,保留 HTTPS 证书私钥路径与历史数据库兼容迁移;更新生产验收记录并记录后端、前端测试和构建结果。
This commit is contained in:
parent
1b9b6ecec4
commit
266eea723c
@ -1,29 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func newSSHKeyCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "ssh-key",
|
||||
Short: "SSH 密钥登录功能已停用",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return errors.New("SSH 密钥登录功能已永久停用,仅支持 SSH 密码认证")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newSSHKeyListCommand() *cobra.Command {
|
||||
return newSSHKeyCommand()
|
||||
}
|
||||
|
||||
func newSSHKeyAddCommand() *cobra.Command {
|
||||
return newSSHKeyCommand()
|
||||
}
|
||||
|
||||
func newSSHKeyDeleteCommand() *cobra.Command {
|
||||
return newSSHKeyCommand()
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package httpapi
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (s *Server) listSSHKeys(c *gin.Context) {
|
||||
c.Status(404)
|
||||
}
|
||||
|
||||
func (s *Server) createSSHKey(c *gin.Context) {
|
||||
c.Status(404)
|
||||
}
|
||||
|
||||
func (s *Server) deleteSSHKey(c *gin.Context) {
|
||||
c.Status(404)
|
||||
}
|
||||
@ -1809,3 +1809,16 @@ SQLite 新测试程序 SHA-256:4c81656fae63a2eebad999d58e6a79e63e6f441810e02ce
|
||||
- [~] P0-10、三数据库清库后的 Web 流程、Smail 系统账户发信、验证码密码重置和最终清库首次验收仍未完成。
|
||||
|
||||
总体生产部署验收仍未放行,当前状态保持 **P0-03:完成,等待复审**。
|
||||
|
||||
## 2026年10月2日 SSH 登录密钥入口移除复核
|
||||
|
||||
本轮按安全要求收紧产品边界:SSH 登录只允许密码认证,不提供私钥、公钥、密钥生成、授权文件写入或密钥登录管理能力。HTTPS 证书部署所需的证书私钥路径仍保留,二者用途不同。
|
||||
|
||||
- [x] 删除未注册的 SSH 密钥 CLI 入口文件,正式 CLI 不再包含密钥管理命令。
|
||||
- [x] 删除未注册的 SSH 密钥 HTTP 处理文件,生产路由继续不注册相关接口,`/api/v1/ssh-keys` 保持 404。
|
||||
- [x] 删除未引用的前端密钥弹窗文件和遗留样式,生产页面不提供密钥管理入口、命令或授权文件提示。
|
||||
- [x] 保留服务器主机指纹校验、SSH 密码字段和 HTTPS 证书私钥路径;没有把证书私钥误当作 SSH 登录凭据。
|
||||
- [x] 后端 `go test ./...` 全部通过;前端 241 项测试全部通过;Vite 生产构建通过;`git diff --check` 通过。
|
||||
- [~] 需要将最新候选包按正式安装流程部署到双机,并复核页面和 API 后再进入最终生产验收。
|
||||
|
||||
本轮不删除历史数据库迁移文件和禁用兼容测试;它们只用于既有数据库升级和安全回归,不会启用 SSH 密钥能力。总体生产验收仍未通过,既有证书 SAN、启动早期 502、Smail 系统账户发信和三数据库完整 Web 流程仍是门禁项。
|
||||
|
||||
@ -1927,3 +1927,16 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全
|
||||
- [ ] SQLite、MySQL、PostgreSQL 清库后的完整 Web 首次流程。
|
||||
- [!] Smail 系统通知账户、真实发信、验证码、超级管理员重置密码和改密后重新登录闭环。
|
||||
- [!] 第一台 `odacm.cn` 证书 SAN 不匹配及启动早期短暂 502 的生产结论。
|
||||
|
||||
## 2026年10月2日 SSH 登录密钥入口移除复核
|
||||
|
||||
本轮按安全要求收紧产品边界:SSH 登录只允许密码认证,不提供私钥、公钥、密钥生成、授权文件写入或密钥登录管理能力。HTTPS 证书部署所需的证书私钥路径仍保留,二者用途不同。
|
||||
|
||||
- [x] 删除未注册的 SSH 密钥 CLI 入口文件,正式 CLI 不再包含密钥管理命令。
|
||||
- [x] 删除未注册的 SSH 密钥 HTTP 处理文件,生产路由继续不注册相关接口,`/api/v1/ssh-keys` 保持 404。
|
||||
- [x] 删除未引用的前端密钥弹窗文件和遗留样式,生产页面不提供密钥管理入口、命令或授权文件提示。
|
||||
- [x] 保留服务器主机指纹校验、SSH 密码字段和 HTTPS 证书私钥路径;没有把证书私钥误当作 SSH 登录凭据。
|
||||
- [x] 后端 `go test ./...` 全部通过;前端 241 项测试全部通过;Vite 生产构建通过;`git diff --check` 通过。
|
||||
- [~] 需要将最新候选包按正式安装流程部署到双机,并复核页面和 API 后再进入最终生产验收。
|
||||
|
||||
本轮不删除历史数据库迁移文件和禁用兼容测试;它们只用于既有数据库升级和安全回归,不会启用 SSH 密钥能力。总体生产验收仍未通过,既有证书 SAN、启动早期 502、Smail 系统账户发信和三数据库完整 Web 流程仍是门禁项。
|
||||
|
||||
@ -2563,3 +2563,16 @@ P0-11 生产验收门禁
|
||||
- [~] 启动早期 502 仍需按生产门禁继续评估:第二台本次安装后约第 2 秒探测出现 502,等待后恢复为严格 HTTPS 200;未开放 8443,也未绕过 Nginx。
|
||||
|
||||
当前总体状态仍为 **P0-03:完成,等待复审**,不能据此宣布生产整体验收通过。P0-10 负向恢复、三数据库清库后的完整 Web 流程、Smail 系统账户发信及密码重置闭环仍未完成。
|
||||
|
||||
## 2026年10月2日 SSH 登录密钥入口移除复核
|
||||
|
||||
本轮按安全要求收紧产品边界:SSH 登录只允许密码认证,不提供私钥、公钥、密钥生成、授权文件写入或密钥登录管理能力。HTTPS 证书部署所需的证书私钥路径仍保留,二者用途不同。
|
||||
|
||||
- [x] 删除未注册的 SSH 密钥 CLI 入口文件,正式 CLI 不再包含密钥管理命令。
|
||||
- [x] 删除未注册的 SSH 密钥 HTTP 处理文件,生产路由继续不注册相关接口,`/api/v1/ssh-keys` 保持 404。
|
||||
- [x] 删除未引用的前端密钥弹窗文件和遗留样式,生产页面不提供密钥管理入口、命令或授权文件提示。
|
||||
- [x] 保留服务器主机指纹校验、SSH 密码字段和 HTTPS 证书私钥路径;没有把证书私钥误当作 SSH 登录凭据。
|
||||
- [x] 后端 `go test ./...` 全部通过;前端 241 项测试全部通过;Vite 生产构建通过;`git diff --check` 通过。
|
||||
- [~] 需要将最新候选包按正式安装流程部署到双机,并复核页面和 API 后再进入最终生产验收。
|
||||
|
||||
本轮不删除历史数据库迁移文件和禁用兼容测试;它们只用于既有数据库升级和安全回归,不会启用 SSH 密钥能力。总体生产验收仍未通过,既有证书 SAN、启动早期 502、Smail 系统账户发信和三数据库完整 Web 流程仍是门禁项。
|
||||
|
||||
@ -434,162 +434,10 @@ code {
|
||||
color: #63748c !important;
|
||||
}
|
||||
|
||||
.ssh-server-list {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.ssh-server-card {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 18px;
|
||||
border: 1px solid #dfe7f1;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(135deg, #ffffff, #f8fbff);
|
||||
}
|
||||
|
||||
.ssh-server-card-heading,
|
||||
.ssh-orphaned-heading,
|
||||
.ssh-server-command {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.ssh-server-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 18px;
|
||||
color: #718198;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ssh-server-domain-bindings {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
border: 1px solid #e4ebf4;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.ssh-server-domain-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.ssh-server-details {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ssh-server-detail {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
padding: 12px;
|
||||
border: 1px solid #e4ebf4;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
color: #718198;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.ssh-server-detail strong {
|
||||
color: #30435f;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: #8a98ab;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.ssh-server-detail code,
|
||||
.ssh-server-command code {
|
||||
overflow-wrap: anywhere;
|
||||
color: #345f94;
|
||||
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.inline-error {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ssh-server-command {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #d8e5f4;
|
||||
border-radius: 12px;
|
||||
background: #f3f8ff;
|
||||
}
|
||||
|
||||
.ssh-server-command > div {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.ssh-orphaned-keys {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-top: 18px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #e7edf5;
|
||||
}
|
||||
|
||||
.ssh-orphaned-heading > div {
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.ssh-orphaned-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ssh-orphaned-item {
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 7px 10px;
|
||||
border: 1px solid #e1e8f1;
|
||||
border-radius: 9px;
|
||||
background: #fbfcfe;
|
||||
color: #6f7f94;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
|
||||
.ssh-server-details {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.ssh-server-card-heading,
|
||||
.ssh-orphaned-heading,
|
||||
.ssh-server-command {
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.ssh-server-details {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.ssh-server-command .inline-button {
|
||||
align-self: flex-start;
|
||||
}
|
||||
}
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
.modal-backdrop.ssh-key-backdrop {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.ssh-key-modal {
|
||||
box-sizing: border-box;
|
||||
width: min(100%, 1180px);
|
||||
max-height: calc(100dvh - 32px);
|
||||
overflow: auto;
|
||||
padding: 18px 24px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .modal-heading {
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.ssh-key-modal form {
|
||||
grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-guide,
|
||||
.ssh-key-modal .ssh-key-form-fields {
|
||||
min-width: 0;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-guide-heading {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-guide-heading > div:first-child,
|
||||
.ssh-key-modal .ssh-key-steps article > div,
|
||||
.ssh-key-modal .field > span,
|
||||
.ssh-key-modal .field-label-row > span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-steps {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-steps article {
|
||||
gap: 5px;
|
||||
padding: 7px 5px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-steps strong {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-platforms {
|
||||
margin: 8px 0;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .platform-tab {
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-path-line,
|
||||
.ssh-key-modal .ssh-key-path-summary {
|
||||
gap: 5px;
|
||||
padding: 6px 8px;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-path-summary {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-path-summary > div:last-child {
|
||||
grid-column: auto;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-command-card {
|
||||
margin-top: 6px;
|
||||
padding: 7px 8px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-command-heading {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-command-card > code {
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.ssh-key-modal .field {
|
||||
margin-bottom: 10px;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .field input,
|
||||
.ssh-key-modal .field textarea {
|
||||
min-height: 36px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-form-fields .field textarea {
|
||||
min-height: 130px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-form-fields .modal-actions {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.ssh-key-modal form {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-form-fields {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.ssh-key-modal {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.ssh-key-modal .ssh-key-path-summary {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<span v-if="false" aria-hidden="true"></span>
|
||||
</template>
|
||||
Loading…
Reference in New Issue
Block a user