feat(M2): SSH 密钥管理 — 公钥上传/重命名/吊销、authorized_keys 原子同步与吊销即时失效
- KeyService:crypto/ssh 解析校验(单行/类型/长度/去重指纹,拒 ssh-dss 与 RSA<2048), Create/Rename/Revoke/List,变更后以 DB 状态全量重写 authorized_keys(同步失败回滚) - system 层:SyncAuthorizedKeys 完善 —— sudo 模式经白名单命令(mkdir/chown/chmod/install) 落位并修正属主(sshd StrictModes),direct 模式 root 时同样修正属主;dry-run 计划日志 - API:GET/POST /me/keys、PATCH/DELETE /me/keys/:id(user 会话)、GET /users/:id/keys(admin), 密钥操作带审计;deploy/sudoers.example 补充密钥同步白名单 - 版本 0.3.0-m2;测试:service 单元(校验/生命周期/回滚/权限)、system 直写落盘、 API 全流程集成;容器 E2E 32 项 PASS(真实 useradd/authorized_keys/吊销即时失效/禁用清空/删除回收)
This commit is contained in:
@@ -211,8 +211,8 @@ func (s *UserService) Enable(ctx context.Context, id uint) error {
|
||||
if !s.systemAccountOK(ctx, u.Username) {
|
||||
return ErrSystemAccountMissing
|
||||
}
|
||||
// 恢复有效密钥(M1 阶段用户尚无密钥,M2 接入后按 DB 同步)
|
||||
keys, err := s.activeKeys(ctx, u.ID)
|
||||
// 恢复有效密钥(以 DB 状态全量同步)
|
||||
keys, err := activeUserKeys(s.db, ctx, u.ID, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -239,7 +239,7 @@ func (s *UserService) Extend(ctx context.Context, id uint, days int) error {
|
||||
if !s.systemAccountOK(ctx, u.Username) {
|
||||
return ErrSystemAccountMissing
|
||||
}
|
||||
keys, err := s.activeKeys(ctx, u.ID)
|
||||
keys, err := activeUserKeys(s.db, ctx, u.ID, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -271,14 +271,19 @@ func (s *UserService) Delete(ctx context.Context, id uint) error {
|
||||
})
|
||||
}
|
||||
|
||||
// activeKeys 返回用户当前有效(active)密钥,供授权同步(M2 完善密钥管理)。
|
||||
func (s *UserService) activeKeys(ctx context.Context, userID uint) ([]system.Key, error) {
|
||||
// activeUserKeys 返回用户当前有效(active)密钥,供 authorized_keys 全量同步
|
||||
// (UserService.Enable/Extend 与 KeyService 变更共用,保证同步口径一致)。
|
||||
// excludeKeyID 非 0 时排除指定密钥(吊销场景:先同步剩余密钥,再落 DB)。
|
||||
func activeUserKeys(db *gorm.DB, ctx context.Context, userID uint, excludeKeyID uint) ([]system.Key, error) {
|
||||
var rows []model.SSHKey
|
||||
if err := s.db.WithContext(ctx).Where("user_id = ? AND status = ?", userID, model.StatusActive).Find(&rows).Error; err != nil {
|
||||
if err := db.WithContext(ctx).Where("user_id = ? AND status = ?", userID, model.StatusActive).Find(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys := make([]system.Key, 0, len(rows))
|
||||
for _, k := range rows {
|
||||
if excludeKeyID != 0 && k.ID == excludeKeyID {
|
||||
continue
|
||||
}
|
||||
keys = append(keys, system.Key{Type: k.KeyType, PublicKey: k.PublicKey})
|
||||
}
|
||||
return keys, nil
|
||||
|
||||
Reference in New Issue
Block a user