diff --git a/docs/about/update.md b/docs/about/update.md index d43f0be1..007a893f 100644 --- a/docs/about/update.md +++ b/docs/about/update.md @@ -1,5 +1,13 @@ ⚡ 注意: 应用不支持跨版本升级, 可以进行多次升级 +## v1.0.1 + +> sql 脚本 + +```sql + +``` + ## v1.0.0 > sql 脚本 diff --git a/docs/operator/host_audit.md b/docs/operator/host_audit.md index 5360cccd..b298118e 100644 --- a/docs/operator/host_audit.md +++ b/docs/operator/host_audit.md @@ -1,3 +1,8 @@ ### 连接日志 -在主机终端页面打开的 `SSH` `SFTP` 连接都会记录下来, 这里默认只展示 `SSH` 连接记录, 可以展开条件进行修改。 +在主机终端页面打开的 `SSH` `SFTP` 连接都会记录下来。 + +* 详情: 查看连接详情 +* 断开: 断开连接 +* 删除: 删除连接记录 +* 清理: 根据条件清理数据 diff --git a/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/ErrorMessage.java b/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/ErrorMessage.java index 3ccfc298..163be171 100644 --- a/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/ErrorMessage.java +++ b/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/ErrorMessage.java @@ -85,4 +85,8 @@ public interface ErrorMessage { String FILE_ABSENT = "文件不存在"; + String LOG_ABSENT = "日志不存在"; + + String ILLEGAL_STATUS = "当前状态不支持此操作"; + } diff --git a/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java b/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java index 36e22a92..85f0cfa6 100644 --- a/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java +++ b/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java @@ -47,4 +47,12 @@ public interface FieldConst { String MOD = "mod"; + String COUNT = "count"; + + String LOCATION = "location"; + + String USER_AGENT = "userAgent"; + + String ERROR_MESSAGE = "errorMessage"; + } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/HostConnectLogController.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/HostConnectLogController.java index e91cdf28..97ea4623 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/HostConnectLogController.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/HostConnectLogController.java @@ -1,22 +1,23 @@ package com.orion.ops.module.asset.controller; import com.orion.lang.define.wrapper.DataGrid; +import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog; +import com.orion.ops.framework.common.validator.group.Id; import com.orion.ops.framework.common.validator.group.Page; import com.orion.ops.framework.log.core.annotation.IgnoreLog; import com.orion.ops.framework.log.core.enums.IgnoreLogMode; import com.orion.ops.framework.web.core.annotation.RestWrapper; +import com.orion.ops.module.asset.define.operator.HostConnectLogOperatorType; import com.orion.ops.module.asset.entity.request.host.HostConnectLogQueryRequest; import com.orion.ops.module.asset.entity.vo.HostConnectLogVO; import com.orion.ops.module.asset.service.HostConnectLogService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; @@ -55,5 +56,36 @@ public class HostConnectLogController { return hostConnectLogService.getLatestConnectHostId(request); } + @OperatorLog(HostConnectLogOperatorType.DELETE) + @DeleteMapping("/delete") + @Operation(summary = "删除主机连接日志") + @Parameter(name = "idList", description = "idList", required = true) + @PreAuthorize("@ss.hasPermission('asset:host-connect-log:management:delete')") + public Integer deleteHostConnectLog(@RequestParam("idList") List idList) { + return hostConnectLogService.deleteHostConnectLog(idList); + } + + @PostMapping("/query-count") + @Operation(summary = "查询主机连接日志数量") + public Long getHostConnectLogCount(@RequestBody HostConnectLogQueryRequest request) { + return hostConnectLogService.getHostConnectLogCount(request); + } + + @OperatorLog(HostConnectLogOperatorType.CLEAR) + @PostMapping("/clear") + @Operation(summary = "清空主机连接日志") + @PreAuthorize("@ss.hasPermission('asset:host-connect-log:management:clear')") + public Integer clearHostConnectLog(@RequestBody HostConnectLogQueryRequest request) { + return hostConnectLogService.clearHostConnectLog(request); + } + + @OperatorLog(HostConnectLogOperatorType.FORCE_OFFLINE) + @PutMapping("/force-offline") + @Operation(summary = "强制断开主机连接") + @PreAuthorize("@ss.hasPermission('asset:host-connect-log:management:force-offline')") + public Integer forceOffline(@Validated(Id.class) @RequestBody HostConnectLogQueryRequest request) { + return hostConnectLogService.forceOffline(request); + } + } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/operator/HostConnectLogOperatorType.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/operator/HostConnectLogOperatorType.java new file mode 100644 index 00000000..d58dea10 --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/operator/HostConnectLogOperatorType.java @@ -0,0 +1,34 @@ +package com.orion.ops.module.asset.define.operator; + +import com.orion.ops.framework.biz.operator.log.core.annotation.Module; +import com.orion.ops.framework.biz.operator.log.core.factory.InitializingOperatorTypes; +import com.orion.ops.framework.biz.operator.log.core.model.OperatorType; + +import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.*; + +/** + * 主机连接日志 操作日志类型 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/3/2 14:37 + */ +@Module("asset:host-connect-log") +public class HostConnectLogOperatorType extends InitializingOperatorTypes { + + public static final String DELETE = "host-connect-log:delete"; + + public static final String CLEAR = "host-connect-log:clear"; + + public static final String FORCE_OFFLINE = "host-connect-log:force-offline"; + + @Override + public OperatorType[] types() { + return new OperatorType[]{ + new OperatorType(H, DELETE, "删除主机连接记录 ${count}条"), + new OperatorType(H, CLEAR, "清理主机连接记录 ${count}条"), + new OperatorType(M, FORCE_OFFLINE, "强制下线主机连接 ${hostName}"), + }; + } + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/dto/HostConnectLogExtraDTO.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/dto/HostConnectLogExtraDTO.java new file mode 100644 index 00000000..44e3792d --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/dto/HostConnectLogExtraDTO.java @@ -0,0 +1,53 @@ +package com.orion.ops.module.asset.entity.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 主机连接日志推展信息对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024-3-12 23:31 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "HostConnectLogExtraDTO", description = "主机连接日志推展信息对象") +public class HostConnectLogExtraDTO { + + @Schema(description = "主机 id") + private Long hostId; + + @Schema(description = "主机名称") + private String hostName; + + @Schema(description = "连接类型") + private String connectType; + + @Schema(description = "channelId") + private String channelId; + + @Schema(description = "sessionId") + private String sessionId; + + @Schema(description = "traceId") + private String traceId; + + @Schema(description = "请求地址") + private String address; + + @Schema(description = "请求位置") + private String location; + + @Schema(description = "ua") + private String userAgent; + + @Schema(description = "错误信息") + private String errorMessage; + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/request/host/HostConnectLogQueryRequest.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/request/host/HostConnectLogQueryRequest.java index 75ec8373..9cb62906 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/request/host/HostConnectLogQueryRequest.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/request/host/HostConnectLogQueryRequest.java @@ -23,6 +23,9 @@ import java.util.Date; @Schema(name = "HostConnectLogQueryRequest", description = "主机连接日志 查询请求对象") public class HostConnectLogQueryRequest extends PageRequest { + @Schema(description = "id") + private Long id; + @Schema(description = "用户id") private Long userId; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostConnectLogVO.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostConnectLogVO.java index f09caf65..d69d7090 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostConnectLogVO.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostConnectLogVO.java @@ -46,9 +46,6 @@ public class HostConnectLogVO implements Serializable { @Schema(description = "类型") private String type; - @Schema(description = "token") - private String token; - @Schema(description = "状态") private String status; @@ -67,10 +64,4 @@ public class HostConnectLogVO implements Serializable { @Schema(description = "修改时间") private Date updateTime; - @Schema(description = "创建人") - private String creator; - - @Schema(description = "修改人") - private String updater; - } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/enums/HostConnectStatusEnum.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/enums/HostConnectStatusEnum.java index 546df6fb..35706cb8 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/enums/HostConnectStatusEnum.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/enums/HostConnectStatusEnum.java @@ -24,6 +24,11 @@ public enum HostConnectStatusEnum { */ FAILED, + /** + * 强制下线 + */ + FORCE_OFFLINE, + ; public static HostConnectStatusEnum of(String type) { diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java index 3950c022..c2b23247 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java @@ -173,7 +173,7 @@ public class TerminalCheckHandler extends AbstractTerminalHandler extra = Maps.newMap(); - extra.put(OperatorLogs.ID, hostId); + extra.put(OperatorLogs.HOST_ID, hostId); extra.put(OperatorLogs.HOST_NAME, hostName); extra.put(OperatorLogs.CONNECT_TYPE, connectType.name()); extra.put(OperatorLogs.CHANNEL_ID, channel.getId()); @@ -194,6 +194,13 @@ public class TerminalCheckHandler extends AbstractTerminalHandler> getLatestConnectHostIdAsync(HostConnectTypeEnum type, Long userId); + /** + * 删除主机连接日志 + * + * @param idList idList + * @return effect + */ + Integer deleteHostConnectLog(List idList); + + /** + * 获取主机连接日志数量 + * + * @param request request + * @return count + */ + Long getHostConnectLogCount(HostConnectLogQueryRequest request); + + /** + * 清理主机连接日志 + * + * @param request request + * @return effect + */ + Integer clearHostConnectLog(HostConnectLogQueryRequest request); + + /** + * 强制断开主机连接 + * + * @param request request + * @return effect + */ + Integer forceOffline(HostConnectLogQueryRequest request); + } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostConnectLogServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostConnectLogServiceImpl.java index e6a1cfea..2f1239ee 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostConnectLogServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostConnectLogServiceImpl.java @@ -5,16 +5,22 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.orion.lang.constant.Const; import com.orion.lang.define.wrapper.DataGrid; import com.orion.lang.utils.Arrays1; +import com.orion.lang.utils.Valid; +import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs; +import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.mybatis.core.query.Conditions; import com.orion.ops.framework.security.core.utils.SecurityUtils; import com.orion.ops.module.asset.convert.HostConnectLogConvert; import com.orion.ops.module.asset.dao.HostConnectLogDAO; import com.orion.ops.module.asset.entity.domain.HostConnectLogDO; +import com.orion.ops.module.asset.entity.dto.HostConnectLogExtraDTO; import com.orion.ops.module.asset.entity.request.host.HostConnectLogCreateRequest; import com.orion.ops.module.asset.entity.request.host.HostConnectLogQueryRequest; import com.orion.ops.module.asset.entity.vo.HostConnectLogVO; import com.orion.ops.module.asset.enums.HostConnectStatusEnum; import com.orion.ops.module.asset.enums.HostConnectTypeEnum; +import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager; +import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession; import com.orion.ops.module.asset.service.HostConnectLogService; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; @@ -40,6 +46,9 @@ public class HostConnectLogServiceImpl implements HostConnectLogService { @Resource private HostConnectLogDAO hostConnectLogDAO; + @Resource + private TerminalManager terminalManager; + @Override public void create(HostConnectTypeEnum type, HostConnectLogCreateRequest request) { HostConnectLogDO record = HostConnectLogConvert.MAPPER.to(request); @@ -66,12 +75,12 @@ public class HostConnectLogServiceImpl implements HostConnectLogService { } @Override - public void updateStatusByToken(String token, HostConnectStatusEnum status) { + public Integer updateStatusByToken(String token, HostConnectStatusEnum status) { log.info("HostConnectLogService-updateStatusByToken token: {}, status: {}", token, status); HostConnectLogDO update = new HostConnectLogDO(); update.setStatus(status.name()); update.setEndTime(new Date()); - hostConnectLogDAO.update(update, Conditions.eq(HostConnectLogDO::getToken, token)); + return hostConnectLogDAO.update(update, Conditions.eq(HostConnectLogDO::getToken, token)); } @Override @@ -86,6 +95,55 @@ public class HostConnectLogServiceImpl implements HostConnectLogService { return CompletableFuture.completedFuture(hostIdList); } + @Override + public Integer deleteHostConnectLog(List idList) { + // TODO 测试一下参数 + log.info("HostConnectLogService.deleteHostConnectLog start {}", JSON.toJSONString(idList)); + int effect = hostConnectLogDAO.deleteBatchIds(idList); + log.info("HostConnectLogService.deleteHostConnectLog finish {}", effect); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.COUNT, effect); + return effect; + } + + @Override + public Long getHostConnectLogCount(HostConnectLogQueryRequest request) { + return hostConnectLogDAO.selectCount(this.buildQueryWrapper(request)); + } + + @Override + public Integer clearHostConnectLog(HostConnectLogQueryRequest request) { + // TODO 测试一下参数 + log.info("HostConnectLogService.clearHostConnectLog start {}", JSON.toJSONString(request)); + // 删除 + LambdaQueryWrapper wrapper = this.buildQueryWrapper(request); + int effect = hostConnectLogDAO.delete(wrapper); + log.info("HostConnectLogService.clearHostConnectLog finish {}", effect); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.COUNT, effect); + return effect; + } + + @Override + public Integer forceOffline(HostConnectLogQueryRequest request) { + Long id = request.getId(); + // 查询数据是否存在 + HostConnectLogDO connect = hostConnectLogDAO.selectById(id); + Valid.notNull(connect, ErrorMessage.LOG_ABSENT); + Valid.eq(connect.getStatus(), HostConnectStatusEnum.CONNECTING.name(), ErrorMessage.ILLEGAL_STATUS); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.HOST_NAME, connect.getHostName()); + // 获取会话 + HostConnectLogExtraDTO extra = JSON.parseObject(connect.getExtraInfo(), HostConnectLogExtraDTO.class); + ITerminalSession session = terminalManager.getSession(extra.getChannelId(), extra.getSessionId()); + if (session != null) { + // 关闭会话 + session.forceOffline(); + } + // 更新状态 + return this.updateStatusByToken(connect.getToken(), HostConnectStatusEnum.FORCE_OFFLINE); + } + /** * 构建查询 wrapper * @@ -94,6 +152,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService { */ private LambdaQueryWrapper buildQueryWrapper(HostConnectLogQueryRequest request) { return hostConnectLogDAO.wrapper() + .eq(HostConnectLogDO::getId, request.getId()) .eq(HostConnectLogDO::getUserId, request.getUserId()) .eq(HostConnectLogDO::getHostId, request.getHostId()) .like(HostConnectLogDO::getHostAddress, request.getHostAddress())