测试主机连接接口,秘钥连接完善

This commit is contained in:
蒲先生 2025-07-21 17:28:16 +08:00
parent cd90dd7e28
commit d6c5ab4d98
8 changed files with 87 additions and 19 deletions

View File

@ -22,4 +22,17 @@ public enum AuthenticationType implements IntArrayValuable {
public int[] array() { public int[] array() {
return ARRAYS; return ARRAYS;
} }
public static AuthenticationType of(int code) {
if (code == 0) {
return null;
}
for (AuthenticationType value : values()) {
if (value.code==code) {
return value;
}
}
return null;
}
} }

View File

@ -9,6 +9,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import static cd.casic.framework.commons.pojo.CommonResult.success; import static cd.casic.framework.commons.pojo.CommonResult.success;
@ -42,5 +43,12 @@ public class TerminalController {
return success(terminalService.getTerminalTransferToken()); return success(terminalService.getTerminalTransferToken());
} }
@GetMapping("/test")
@Operation(summary = "测试主机连接")
// @PreAuthorize("@ss.hasPermission('asset:host:update')")
public CommonResult testHostConnect(@RequestParam Long id) {
return terminalService.testHostConnect(id);
}
} }

View File

@ -64,22 +64,18 @@ public class TerminalConnectDTO {
@Schema(description = "用户名") @Schema(description = "用户名")
private String username; private String username;
// @Desensitize(toEmpty = true)
@Schema(description = "密码") @Schema(description = "密码")
private String password; private String password;
@Schema(description = "密钥id") @Schema(description = "密钥id")
private Long keyId; private Long keyId;
// @Desensitize(toEmpty = true)
@Schema(description = "公钥文本") @Schema(description = "公钥文本")
private String publicKey; private String publicKey;
// @Desensitize(toEmpty = true)
@Schema(description = "私钥文本") @Schema(description = "私钥文本")
private String privateKey; private String privateKey;
// @Desensitize(toEmpty = true)
@Schema(description = "私钥密码") @Schema(description = "私钥密码")
private String privateKeyPassword; private String privateKeyPassword;

View File

@ -73,13 +73,13 @@ public class SessionStores {
if (useKey) { if (useKey) {
// 加载密钥 // 加载密钥
String publicKey = Optional.ofNullable(conn.getPublicKey()) String publicKey = Optional.ofNullable(conn.getPublicKey())
.map(CryptogramUtil::doDecrypt) .map(obj->CryptogramUtil.doDecrypt(obj))
.orElse(null); .orElse(null);
String privateKey = Optional.ofNullable(conn.getPrivateKey()) String privateKey = Optional.ofNullable(conn.getPrivateKey())
.map(CryptogramUtil::doDecrypt) .map(obj->CryptogramUtil.doDecrypt(obj))
.orElse(null); .orElse(null);
String password = Optional.ofNullable(conn.getPrivateKeyPassword()) String password = Optional.ofNullable(conn.getPrivateKeyPassword())
.map(CryptogramUtil::doDecrypt) .map(obj->CryptogramUtil.doDecrypt(obj))
.orElse(null); .orElse(null);
sessionHolder.addIdentityValue(String.valueOf(conn.getKeyId()), sessionHolder.addIdentityValue(String.valueOf(conn.getKeyId()),
privateKey, privateKey,

View File

@ -33,9 +33,9 @@ import java.util.Map;
/** /**
* 终端连接检查 * 终端连接检查
* *
* @author Jiahang Li * @author Yuru Pu
* @version 1.0.0 * @version 1.0
* @since 2023/12/29 15:32 * @since 2025/7/21 14:17
*/ */
@Slf4j @Slf4j
@Component @Component
@ -50,8 +50,6 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
@Resource @Resource
private TerminalConnectLogService terminalConnectLogService; private TerminalConnectLogService terminalConnectLogService;
/*@Resource
private OperatorLogFrameworkService operatorLogFrameworkService;*/
@Override @Override
public void handle(WebSocketSession channel, TerminalCheckRequest payload) { public void handle(WebSocketSession channel, TerminalCheckRequest payload) {

View File

@ -13,6 +13,14 @@ import cd.casic.module.terminal.controller.dto.TerminalConnectDTO;
*/ */
public interface HostConnectService { public interface HostConnectService {
/**
* 获取 SSH 连接信息
*
* @param hostId hostId
* @return session
*/
TerminalConnectDTO getSshConnectInfo(Long hostId);
/** /**
* 使用用户配置获取 SSH 连接信息 * 使用用户配置获取 SSH 连接信息
* *

View File

@ -5,6 +5,7 @@ import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.dal.dataobject.SecretKeyDO; import cd.casic.module.machine.dal.dataobject.SecretKeyDO;
import cd.casic.module.machine.dal.mysql.MachineInfoMapper; import cd.casic.module.machine.dal.mysql.MachineInfoMapper;
import cd.casic.module.machine.dal.mysql.SecretKeyMapper; import cd.casic.module.machine.dal.mysql.SecretKeyMapper;
import cd.casic.module.machine.enums.AuthenticationType;
import cd.casic.module.machine.utils.CryptogramUtil; import cd.casic.module.machine.utils.CryptogramUtil;
import cd.casic.module.terminal.common.ErrorMessage; import cd.casic.module.terminal.common.ErrorMessage;
import cd.casic.module.terminal.controller.dto.TerminalConnectDTO; import cd.casic.module.terminal.controller.dto.TerminalConnectDTO;
@ -13,6 +14,7 @@ import cd.casic.module.terminal.host.config.model.HostSshConfigModel;
import cd.casic.module.terminal.host.extra.model.HostSshExtraModel; import cd.casic.module.terminal.host.extra.model.HostSshExtraModel;
import cd.casic.module.terminal.service.HostConnectService; import cd.casic.module.terminal.service.HostConnectService;
import cn.orionsec.kit.lang.utils.Valid; import cn.orionsec.kit.lang.utils.Valid;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -38,7 +40,17 @@ public class HostConnectServiceImpl implements HostConnectService {
private HostSshConfigModel CONFIG = HostSshConfigModel.builder().authType(HostSshAuthTypeEnum.KEY.name()).connectTimeout(10000).charset("UTF-8").fileContentCharset("UTF-8").fileNameCharset("UTF-8").build(); private final HostSshConfigModel CONFIG = HostSshConfigModel.builder().connectTimeout(10000).charset("UTF-8").fileContentCharset("UTF-8").fileNameCharset("UTF-8").build();
@Override
public TerminalConnectDTO getSshConnectInfo(Long hostId) {
log.info("HostConnectService.getSshConnectInfo-withHost hostId: {}", hostId);
// 查询主机
MachineInfoDO host = machineInfoMapper.selectById(hostId);
// 获取配置
return this.getHostConnectInfo(host, CONFIG, null);
}
@Override @Override
@ -93,7 +105,7 @@ public class HostConnectServiceImpl implements HostConnectService {
conn.setHostName(host.getName()); conn.setHostName(host.getName());
// conn.setHostCode(host.getCode()); // conn.setHostCode(host.getCode());
conn.setHostAddress(host.getHostIp()); conn.setHostAddress(host.getHostIp());
conn.setHostPort(config.getPort()); conn.setHostPort(host.getSshPort());
conn.setTimeout(config.getConnectTimeout()); conn.setTimeout(config.getConnectTimeout());
conn.setCharset(config.getCharset()); conn.setCharset(config.getCharset());
conn.setFileNameCharset(config.getFileNameCharset()); conn.setFileNameCharset(config.getFileNameCharset());
@ -116,9 +128,8 @@ public class HostConnectServiceImpl implements HostConnectService {
config.setAuthType(HostSshAuthTypeEnum.IDENTITY.name()); config.setAuthType(HostSshAuthTypeEnum.IDENTITY.name());
config.setIdentityId(extra.getIdentityId()); config.setIdentityId(extra.getIdentityId());
} }
// 身份认证 // 身份认证
HostSshAuthTypeEnum authType = HostSshAuthTypeEnum.of(config.getAuthType()); HostSshAuthTypeEnum authType = AuthenticationType.of(host.getAuthenticationType()).name().equals(AuthenticationType.SECRET_KEY.name()) ? HostSshAuthTypeEnum.KEY : HostSshAuthTypeEnum.PASSWORD;
if (HostSshAuthTypeEnum.IDENTITY.equals(authType)) { if (HostSshAuthTypeEnum.IDENTITY.equals(authType)) {
// 身份认证 // 身份认证
Valid.notNull(config.getIdentityId(), ErrorMessage.IDENTITY_ABSENT); Valid.notNull(config.getIdentityId(), ErrorMessage.IDENTITY_ABSENT);
@ -138,13 +149,13 @@ public class HostConnectServiceImpl implements HostConnectService {
} }
// 填充认证信息 // 填充认证信息
conn.setUsername(config.getUsername()); conn.setUsername(host.getUsername());
if (HostSshAuthTypeEnum.PASSWORD.equals(authType)) { if (HostSshAuthTypeEnum.PASSWORD.equals(authType)) {
// 密码认证 // 密码认证
conn.setPassword(config.getPassword()); conn.setPassword(host.getPassword());
} else if (HostSshAuthTypeEnum.KEY.equals(authType)) { } else if (HostSshAuthTypeEnum.KEY.equals(authType)) {
// 密钥认证 // 密钥认证
Long keyId = config.getKeyId(); Long keyId = host.getSecretKeyId();
Valid.notNull(keyId, ErrorMessage.KEY_ABSENT); Valid.notNull(keyId, ErrorMessage.KEY_ABSENT);
SecretKeyDO key = secretKeyMapper.selectById(keyId); SecretKeyDO key = secretKeyMapper.selectById(keyId);
Valid.notNull(key, ErrorMessage.KEY_ABSENT); Valid.notNull(key, ErrorMessage.KEY_ABSENT);

View File

@ -1,13 +1,27 @@
package cd.casic.module.terminal.service.impl; package cd.casic.module.terminal.service.impl;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.pojo.CommonResult;
import cd.casic.framework.security.core.LoginUser; import cd.casic.framework.security.core.LoginUser;
import cd.casic.framework.security.core.util.SecurityFrameworkUtils; import cd.casic.framework.security.core.util.SecurityFrameworkUtils;
import cd.casic.module.terminal.controller.dto.TerminalAccessDTO; import cd.casic.module.terminal.controller.dto.TerminalAccessDTO;
import cd.casic.module.terminal.controller.dto.TerminalConnectDTO;
import cd.casic.module.terminal.controller.dto.TerminalTransferDTO; import cd.casic.module.terminal.controller.dto.TerminalTransferDTO;
import cd.casic.module.terminal.dal.redis.TerminalRedisDAO; import cd.casic.module.terminal.dal.redis.TerminalRedisDAO;
import cd.casic.module.terminal.define.cache.TerminalCacheKeyDefine; import cd.casic.module.terminal.define.cache.TerminalCacheKeyDefine;
import cd.casic.module.terminal.enums.HostTypeEnum;
import cd.casic.module.terminal.enums.TerminalConnectTypeEnum;
import cd.casic.module.terminal.host.jsch.SessionMessage;
import cd.casic.module.terminal.host.jsch.SessionStores;
import cd.casic.module.terminal.service.HostConnectService;
import cn.orionsec.kit.lang.id.UUIds; import cn.orionsec.kit.lang.id.UUIds;
import static cd.casic.framework.commons.pojo.CommonResult.error;
import static cd.casic.framework.commons.pojo.CommonResult.success;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.Valid; import cn.orionsec.kit.lang.utils.Valid;
import cn.orionsec.kit.lang.utils.io.Streams;
import cn.orionsec.kit.net.host.SessionStore;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -25,6 +39,9 @@ public class TerminalService{
@Resource @Resource
private TerminalRedisDAO terminalRedisDAO; private TerminalRedisDAO terminalRedisDAO;
@Resource
private HostConnectService hostConnectService;
public String getTerminalAccessToken() { public String getTerminalAccessToken() {
LoginUser user = Valid.notNull(SecurityFrameworkUtils.getLoginUser()); LoginUser user = Valid.notNull(SecurityFrameworkUtils.getLoginUser());
log.info("HostTerminalService.getTerminalAccessToken userId: {}", user.getId()); log.info("HostTerminalService.getTerminalAccessToken userId: {}", user.getId());
@ -54,4 +71,21 @@ public class TerminalService{
return transferToken; return transferToken;
} }
public CommonResult testHostConnect(Long id) {
HostTypeEnum type = HostTypeEnum.of(TerminalConnectTypeEnum.SSH.name());
if (HostTypeEnum.SSH.equals(type)) {
// SSH 连接测试
SessionStore sessionStore = null;
TerminalConnectDTO info = null;
try {
info = hostConnectService.getSshConnectInfo(id);
sessionStore = SessionStores.openSessionStore(info);
} catch (Exception e) {
return error(new ServiceException().setMessage(Strings.format(SessionMessage.SERVER_UNREACHABLE,info.getHostAddress())));
} finally {
Streams.close(sessionStore);
}
}
return success();
}
} }