diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/Const.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/Const.java index 74b25a24..1fcd64f8 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/Const.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/Const.java @@ -51,6 +51,11 @@ public interface Const extends cn.orionsec.kit.lang.constant.Const, FieldConst, String SYSTEM_USERNAME = "system"; + // FIXME KIT + String ADMINISTRATOR = "Administrator"; + + Long ALL_HOST_ID = -1L; + int BATCH_COUNT = 500; } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java index 7af51c47..9e981d47 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java @@ -88,7 +88,7 @@ public enum ErrorCode implements CodeInfo { EXCEL_PASSWORD_ERROR(905, "文档密码错误"), - PASER_FAILED(906, "解析失败"), + PASER_FAILED(906, "表达式解析失败"), ENCRYPT_ERROR(907, "数据加密异常"), @@ -134,9 +134,10 @@ public enum ErrorCode implements CodeInfo { * 获取 wapper * * @param data data + * @param T * @return HttpWrapper */ - public HttpWrapper wrapper() { + public HttpWrapper wrapper() { return HttpWrapper.of(this); } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java index 292af480..ae874b64 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java @@ -24,6 +24,14 @@ package org.dromara.visor.common.constant; import cn.orionsec.kit.lang.exception.ApplicationException; import cn.orionsec.kit.lang.exception.argument.InvalidArgumentException; +import cn.orionsec.kit.lang.utils.Strings; +import org.springframework.validation.BindException; +import org.springframework.web.bind.MissingServletRequestParameterException; + +import javax.validation.ConstraintViolationException; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; /** * 错误信息 @@ -52,6 +60,12 @@ public interface ErrorMessage { String IDENTITY_ABSENT = "主机身份不存在"; + String CHECK_IDENTITY_PASSWORD = "请选择类型为[密码]的主机身份"; + + String KEY_ABSENT_WITH = "主机密钥不存在 {}"; + + String IDENTITY_ABSENT_WITH = "主机身份不存在 {}"; + String CONFIG_ABSENT = "配置不存在"; String CONFIG_PRESENT = "配置已存在"; @@ -96,24 +110,36 @@ public interface ErrorMessage { String UNSUPPORTED_CHARSET = "不支持的编码 [{}]"; - String DECRYPT_ERROR = "数据解密失败"; - String PASSWORD_MISSING = "请输入密码"; String BEFORE_PASSWORD_ERROR = "原密码错误"; String DATA_NO_PERMISSION = "数据无权限"; + String EXPRESSION_ERROR = "表达式错误"; + String ANY_NO_PERMISSION = "{}无权限"; + String OPT_NO_PERMISSION = "无操作权限"; + String SESSION_PRESENT = "会话已存在"; String SESSION_ABSENT = "会话不存在"; + String SESSION_CLOSED = "会话已关闭"; + + String USER_UNSUPPORTED_OPT = "用户不支持此操作"; + + String CURRENT_USER_UNSUPPORTED_OPT = "当前" + USER_UNSUPPORTED_OPT; + String PATH_NOT_NORMALIZE = "路径不合法"; String OPERATE_ERROR = "操作失败"; + String ENCRYPT_KEY_UNSET = "加密密钥未配置"; + + String DECRYPT_ERROR = "数据解密失败"; + String UNKNOWN_TYPE = "未知类型"; String ERROR_TYPE = "错误的类型"; @@ -148,8 +174,26 @@ public interface ErrorMessage { String CLIENT_ABORT = "手动中断"; + String COMMAND_EXEC_ERROR = "命令执行失败 [{}]"; + + String COMPRESS_ERROR = "压缩失败"; + + String DECOMPRESS_ERROR = "解压失败"; + + String COMPRESS_FILE_ABSENT = "压缩文件不存在"; + String UNABLE_DOWNLOAD_FOLDER = "无法下载文件夹"; + String VALID_ERROR = "验证失败"; + + String CONVERT_ERROR = "转换失败"; + + String PRESENT_MODIFY = "{} 已存在, 请修改后重试"; + + String ILLEGAL_MODIFY = "{} 不正确, 请修改后重试"; + + String PLEASE_SELECT_SUFFIX_FILE = "请选择 {} 类型的文件"; + /** * 是否为业务异常 * @@ -187,4 +231,37 @@ public interface ErrorMessage { return defaultMsg; } + /** + * 获取验证错误消息 + * + * @param ex ex + * @param defaultMsg defaultMsg + * @return message + */ + static String getValidErrorMessage(Exception ex, String defaultMsg) { + if (ex == null) { + return null; + } + // 参数不存在异常 + if (ex instanceof MissingServletRequestParameterException) { + return Strings.format(ErrorMessage.MISSING, ((MissingServletRequestParameterException) ex).getParameterName()); + } + // 参数绑定异常 + if (ex instanceof BindException) { + return Optional.ofNullable(((BindException) ex) + .getFieldError()) + .map(error -> error.getField() + Const.SPACE + error.getDefaultMessage()) + .orElse(defaultMsg); + } + // 参数验证异常 + if (ex instanceof ConstraintViolationException) { + return Optional.ofNullable(((ConstraintViolationException) ex).getConstraintViolations()) + .map(Set::iterator) + .map(Iterator::next) + .map(s -> s.getPropertyPath().toString() + Const.SPACE + s.getMessage()) + .orElse(defaultMsg); + } + return getErrorMessage(ex, defaultMsg); + } + } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java index fcbf2ce6..acbaf3e1 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java @@ -55,7 +55,7 @@ public interface ExtraFieldConst extends FieldConst { String GRANT_NAME = "grantName"; - String CHANNEL_ID = "channelId"; + String CHANNEL = "channel"; String SESSION_ID = "sessionId"; diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java index 7931edaf..9097021a 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java @@ -103,8 +103,20 @@ public interface FieldConst { String FILTER = "filter"; + String LICENSE = "license"; + + String SESSION = "session"; + + String CONNECT = "connect"; + String ALL = "all"; + String PROPS = "props"; + + String SENDER = "sender"; + + String RESULT = "result"; + String CONFIG = "config"; } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/enums/EnableStatus.java b/orion-visor-common/src/main/java/org/dromara/visor/common/enums/EnableStatus.java index 2db0e372..9c7e939e 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/enums/EnableStatus.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/enums/EnableStatus.java @@ -52,14 +52,26 @@ public enum EnableStatus { public static EnableStatus of(Integer value) { if (value == null) { - return null; + return DISABLED; } for (EnableStatus e : values()) { if (e.value.equals(value)) { return e; } } - return null; + return DISABLED; + } + + public static EnableStatus of(String value) { + if (value == null) { + return DISABLED; + } + for (EnableStatus e : values()) { + if (e.name().equals(value)) { + return e; + } + } + return DISABLED; } } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/enums/StatisticsRange.java b/orion-visor-common/src/main/java/org/dromara/visor/common/enums/StatisticsRange.java new file mode 100644 index 00000000..a944819b --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/enums/StatisticsRange.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.enums; + +import cn.orionsec.kit.lang.utils.collect.Lists; +import cn.orionsec.kit.lang.utils.time.DateStream; +import cn.orionsec.kit.lang.utils.time.Dates; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 统计区间枚举 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/12/23 14:02 + */ +public enum StatisticsRange { + + /** + * 当天 + */ + TODAY { + @Override + public Date getRangeEndTime(Date startTime) { + return DateStream.of(startTime) + .dayEnd() + .date(); + } + + @Override + public List getDateRanges(Date startTime) { + return Lists.singleton(Dates.format(startTime, Dates.YMD)); + } + }, + + /** + * 日视图 + */ + DAY { + @Override + public Date getRangeEndTime(Date startTime) { + return DateStream.of(startTime) + .dayEnd() + .date(); + } + + @Override + public List getDateRanges(Date startTime) { + return Lists.singleton(Dates.format(startTime, Dates.YMD)); + } + }, + + /** + * 周视图 + */ + WEEK { + @Override + public Date getRangeEndTime(Date startTime) { + return DateStream.of(startTime) + .addDay(7) + .dayEnd() + .date(); + } + + @Override + public List getDateRanges(Date startTime) { + return Arrays.stream(Dates.getIncrementDayDates(startTime, 1, 7)) + .map(s -> Dates.format(s, Dates.YMD)) + .collect(Collectors.toList()); + } + }, + + /** + * 月视图 + */ + MONTH { + @Override + public Date getRangeEndTime(Date startTime) { + return DateStream.of(startTime) + .addMonth(1) + .dayEnd() + .date(); + } + + @Override + public List getDateRanges(Date startTime) { + int monthLastDay = Dates.getMonthLastDay(startTime); + return Arrays.stream(Dates.getIncrementDayDates(startTime, 1, monthLastDay - 1)) + .map(s -> Dates.format(s, Dates.YMD)) + .collect(Collectors.toList()); + } + }, + + ; + + /** + * 获取区间结束时间 + * + * @param startTime startTime + * @return end + */ + public abstract Date getRangeEndTime(Date startTime); + + /** + * 获取时间区间 + * + * @param startTime startTime + * @return ranges + */ + public abstract List getDateRanges(Date startTime); + + public static StatisticsRange of(String type) { + if (type == null) { + return TODAY; + } + for (StatisticsRange value : values()) { + if (value.name().equals(type)) { + return value; + } + } + return TODAY; + } + +} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/session/SessionMessage.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/SessionMessage.java new file mode 100644 index 00000000..658d0930 --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/SessionMessage.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.session; + +import cn.orionsec.kit.lang.exception.AuthenticationException; +import cn.orionsec.kit.lang.exception.argument.InvalidArgumentException; +import cn.orionsec.kit.lang.utils.Exceptions; +import cn.orionsec.kit.lang.utils.Strings; +import org.dromara.visor.common.constant.Const; + +/** + * 连接消息 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/7/11 16:30 + */ +public interface SessionMessage { + + String AUTHENTICATION_FAILURE = "身份认证失败. {}"; + + String SERVER_UNREACHABLE = "无法连接至服务器. {}"; + + String CONNECTION_TIMEOUT = "连接服务器超时. {}"; + + /** + * 获取错误信息 + * + * @param address address + * @param e e + * @return errorMessage + */ + static String getErrorMessage(String address, Exception e) { + if (e == null) { + return null; + } + String message = e.getMessage(); + if (Strings.contains(message, Const.TIMEOUT)) { + // 连接超时 + return Strings.format(SessionMessage.CONNECTION_TIMEOUT, address); + } else if (Exceptions.isCausedBy(e, AuthenticationException.class)) { + // 认证失败 + return Strings.format(SessionMessage.AUTHENTICATION_FAILURE, address); + } else if (Exceptions.isCausedBy(e, InvalidArgumentException.class)) { + // 参数错误 + if (Strings.isBlank(message)) { + return Strings.format(SessionMessage.SERVER_UNREACHABLE, address); + } else { + return message; + } + } else { + // 其他错误 + return Strings.format(SessionMessage.SERVER_UNREACHABLE, address); + } + } + +} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/BaseConnectConfig.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/BaseConnectConfig.java new file mode 100644 index 00000000..e9d0d82b --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/BaseConnectConfig.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.session.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 基础连接配置实现 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/4/1 16:59 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "BaseConnectConfig", description = "基础连接参数") +public class BaseConnectConfig implements IBaseConnectConfig { + + @Schema(description = "系统类型") + private String osType; + + @Schema(description = "系统架构") + private String archType; + + @Schema(description = "hostId") + private Long hostId; + + @Schema(description = "hostName") + private String hostName; + + @Schema(description = "主机编码") + private String hostCode; + + @Schema(description = "主机地址") + private String hostAddress; + + @Schema(description = "主机端口") + private Integer hostPort; + + @Schema(description = "用户名") + private String username; + + @Schema(description = "密码") + private String password; + +} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/IBaseConnectConfig.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/IBaseConnectConfig.java new file mode 100644 index 00000000..f6893156 --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/IBaseConnectConfig.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.session.config; + +/** + * 基础连接配置定义 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/6/24 17:11 + */ +public interface IBaseConnectConfig { + + // -------------------- getter/setter -------------------- + + String getOsType(); + + void setOsType(String osType); + + String getArchType(); + + void setArchType(String archType); + + Long getHostId(); + + void setHostId(Long hostId); + + String getHostName(); + + void setHostName(String hostName); + + String getHostCode(); + + void setHostCode(String hostCode); + + String getHostAddress(); + + void setHostAddress(String hostAddress); + + Integer getHostPort(); + + void setHostPort(Integer hostPort); + + String getUsername(); + + void setUsername(String username); + + String getPassword(); + + void setPassword(String password); + +} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/RdpConnectConfig.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/RdpConnectConfig.java new file mode 100644 index 00000000..8a916894 --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/RdpConnectConfig.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.session.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * RDP 连接参数 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/4/1 16:57 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Schema(name = "RdpConnectConfig", description = "RDP 连接参数") +public class RdpConnectConfig extends BaseConnectConfig { + + @Schema(description = "低带宽模式") + private Boolean lowBandwidthMode; + + @Schema(description = "RDP 版本是否大于8.1") + private Boolean versionGt81; + + @Schema(description = "时区") + private String timezone; + + @Schema(description = "键盘布局") + private String keyboardLayout; + + @Schema(description = "剪切板规范") + private String clipboardNormalize; + + @Schema(description = "域") + private String domain; + + @Schema(description = "预连接id") + private String preConnectionId; + + @Schema(description = "预连接数据") + private String preConnectionBlob; + + @Schema(description = "远程应用") + private String remoteApp; + + @Schema(description = "远程应用路径") + private String remoteAppDir; + + @Schema(description = "远程应用参数") + private String remoteAppArgs; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/dto/TerminalConnectDTO.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/SshConnectConfig.java similarity index 56% rename from orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/dto/TerminalConnectDTO.java rename to orion-visor-common/src/main/java/org/dromara/visor/common/session/config/SshConnectConfig.java index 55757246..183f1645 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/dto/TerminalConnectDTO.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/SshConnectConfig.java @@ -20,57 +20,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.dromara.visor.module.asset.entity.dto; +package org.dromara.visor.common.session.config; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.dromara.visor.framework.desensitize.core.annotation.Desensitize; -import org.dromara.visor.framework.desensitize.core.annotation.DesensitizeObject; +import lombok.experimental.SuperBuilder; /** - * 终端连接参数 + * SSH 连接参数 * * @author Jiahang Li * @version 1.0.0 * @since 2023/12/26 15:47 */ @Data -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor -@DesensitizeObject -@Schema(name = "TerminalConnectDTO", description = "终端连接参数") -public class TerminalConnectDTO { - - @Schema(description = "logId") - private Long logId; - - @Schema(description = "连接类型") - private String connectType; - - @Schema(description = "hostId") - private Long hostId; - - @Schema(description = "hostName") - private String hostName; - - @Schema(description = "主机编码") - private String hostCode; - - @Schema(description = "主机地址") - private String hostAddress; - - @Schema(description = "主机端口") - private Integer hostPort; - - @Schema(description = "系统类型") - private String osType; - - @Schema(description = "系统架构") - private String archType; +@EqualsAndHashCode(callSuper = true) +@Schema(name = "SshConnectConfig", description = "SSH 连接参数") +public class SshConnectConfig extends BaseConnectConfig { @Schema(description = "超时时间") private Integer timeout; @@ -84,25 +56,15 @@ public class TerminalConnectDTO { @Schema(description = "文件内容编码") private String fileContentCharset; - @Schema(description = "用户名") - private String username; - - @Desensitize(toEmpty = true) - @Schema(description = "密码") - private String password; - @Schema(description = "密钥id") private Long keyId; - @Desensitize(toEmpty = true) @Schema(description = "公钥文本") private String publicKey; - @Desensitize(toEmpty = true) @Schema(description = "私钥文本") private String privateKey; - @Desensitize(toEmpty = true) @Schema(description = "私钥密码") private String privateKeyPassword; diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/jsch/SessionStores.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/ssh/SessionStores.java similarity index 53% rename from orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/jsch/SessionStores.java rename to orion-visor-common/src/main/java/org/dromara/visor/common/session/ssh/SessionStores.java index 102208f9..c0de57e7 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/jsch/SessionStores.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/ssh/SessionStores.java @@ -20,10 +20,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.dromara.visor.module.asset.handler.host.jsch; +package org.dromara.visor.common.session.ssh; -import cn.orionsec.kit.lang.exception.AuthenticationException; -import cn.orionsec.kit.lang.exception.argument.InvalidArgumentException; import cn.orionsec.kit.lang.utils.Exceptions; import cn.orionsec.kit.lang.utils.Strings; import cn.orionsec.kit.net.host.SessionHolder; @@ -31,9 +29,9 @@ import cn.orionsec.kit.net.host.SessionLogger; import cn.orionsec.kit.net.host.SessionStore; import lombok.extern.slf4j.Slf4j; import org.dromara.visor.common.constant.AppConst; -import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.session.SessionMessage; +import org.dromara.visor.common.session.config.SshConnectConfig; import org.dromara.visor.common.utils.AesEncryptUtils; -import org.dromara.visor.module.asset.entity.dto.TerminalConnectDTO; import java.util.Optional; @@ -47,25 +45,22 @@ import java.util.Optional; @Slf4j public class SessionStores { - protected static final ThreadLocal CURRENT_ADDRESS = new ThreadLocal<>(); - /** * 打开 sessionStore * - * @param conn conn + * @param config config * @return sessionStore */ - public static SessionStore openSessionStore(TerminalConnectDTO conn) { - Long hostId = conn.getHostId(); - String address = conn.getHostAddress(); - String username = conn.getUsername(); + public static SessionStore openSessionStore(SshConnectConfig config) { + Long hostId = config.getHostId(); + String address = config.getHostAddress(); + String username = config.getUsername(); log.info("SessionStores-open-start hostId: {}, address: {}, username: {}", hostId, address, username); try { - CURRENT_ADDRESS.set(address); // 创建会话 SessionHolder sessionHolder = SessionHolder.create(); sessionHolder.setLogger(SessionLogger.INFO); - SessionStore session = createSessionStore(conn, sessionHolder); + SessionStore session = createSessionStore(config, sessionHolder); // 设置版本 session.getSession().setClientVersion("SSH-2.0-ORION_VISOR_V" + AppConst.VERSION); // 连接 @@ -75,81 +70,48 @@ public class SessionStores { } catch (Exception e) { String message = e.getMessage(); log.error("SessionStores-open-error hostId: {}, address: {}, username: {}, message: {}", hostId, address, username, message, e); - throw Exceptions.app(getErrorMessage(e), e); - } finally { - CURRENT_ADDRESS.remove(); + throw Exceptions.app(SessionMessage.getErrorMessage(address, e), e); } } /** * 创建 sessionStore * - * @param conn conn + * @param config config * @param sessionHolder sessionHolder * @return sessionStore */ - private static SessionStore createSessionStore(TerminalConnectDTO conn, SessionHolder sessionHolder) { - final boolean useKey = conn.getKeyId() != null; + private static SessionStore createSessionStore(SshConnectConfig config, SessionHolder sessionHolder) { + final boolean useKey = config.getKeyId() != null; // 使用密钥认证 if (useKey) { // 加载密钥 - String publicKey = Optional.ofNullable(conn.getPublicKey()) + String publicKey = Optional.ofNullable(config.getPublicKey()) .map(AesEncryptUtils::decryptAsString) .orElse(null); - String privateKey = Optional.ofNullable(conn.getPrivateKey()) + String privateKey = Optional.ofNullable(config.getPrivateKey()) .map(AesEncryptUtils::decryptAsString) .orElse(null); - String password = Optional.ofNullable(conn.getPrivateKeyPassword()) + String password = Optional.ofNullable(config.getPrivateKeyPassword()) .map(AesEncryptUtils::decryptAsString) .orElse(null); - sessionHolder.addIdentityValue(String.valueOf(conn.getKeyId()), + sessionHolder.addIdentityValue(String.valueOf(config.getKeyId()), privateKey, publicKey, password); } // 获取会话 - SessionStore session = sessionHolder.getSession(conn.getHostAddress(), conn.getHostPort(), conn.getUsername()); + SessionStore session = sessionHolder.getSession(config.getHostAddress(), config.getHostPort(), config.getUsername()); // 使用密码认证 if (!useKey) { - String password = conn.getPassword(); + String password = config.getPassword(); if (!Strings.isEmpty(password)) { session.password(AesEncryptUtils.decryptAsString(password)); } } // 超时时间 - session.timeout(conn.getTimeout()); + session.timeout(config.getTimeout()); return session; } - /** - * 获取错误信息 - * - * @param e e - * @return errorMessage - */ - private static String getErrorMessage(Exception e) { - if (e == null) { - return null; - } - String host = CURRENT_ADDRESS.get(); - String message = e.getMessage(); - if (Strings.contains(message, Const.TIMEOUT)) { - // 连接超时 - return Strings.format(SessionMessage.CONNECTION_TIMEOUT, host); - } else if (Exceptions.isCausedBy(e, AuthenticationException.class)) { - // 认证失败 - return Strings.format(SessionMessage.AUTHENTICATION_FAILURE, host); - } else if (Exceptions.isCausedBy(e, InvalidArgumentException.class)) { - // 参数错误 - if (Strings.isBlank(message)) { - return Strings.format(SessionMessage.SERVER_UNREACHABLE, host); - } else { - return message; - } - } else { - // 其他错误 - return Strings.format(SessionMessage.SERVER_UNREACHABLE, host); - } - } - } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/ConfigUtils.java b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/ConfigUtils.java index 42d4931e..e20a0e9c 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/ConfigUtils.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/ConfigUtils.java @@ -22,7 +22,7 @@ */ package org.dromara.visor.common.utils; -import cn.orionsec.kit.lang.constant.Const; +import org.dromara.visor.common.constant.Const; import java.util.Arrays; import java.util.List; diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/SqlUtils.java b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/SqlUtils.java index 0af399c1..c0aa6e1c 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/SqlUtils.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/SqlUtils.java @@ -43,6 +43,9 @@ public class SqlUtils { * @return limit */ public static String limit(Number limit) { + if (limit == null) { + return Const.EMPTY; + } return Const.LIMIT + Const.SPACE + limit; } @@ -54,6 +57,9 @@ public class SqlUtils { * @return limit */ public static String limit(Number offset, Number limit) { + if (offset == null) { + return limit(limit); + } return Const.LIMIT + Const.SPACE + offset + Const.COMMA + limit; } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/Valid.java b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/Valid.java index 35fecb7a..6c61ac17 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/Valid.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/Valid.java @@ -25,6 +25,7 @@ package org.dromara.visor.common.utils; import cn.orionsec.kit.lang.utils.Arrays1; import cn.orionsec.kit.lang.utils.io.Files1; import cn.orionsec.kit.spring.SpringHolder; +import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.ErrorMessage; import javax.validation.ConstraintViolation; @@ -159,4 +160,17 @@ public class Valid extends cn.orionsec.kit.lang.utils.Valid { return Files1.getPath(path); } + /** + * 检查后缀 + * + * @param file file + * @param suffix suffix + * @return file + */ + public static String checkSuffix(String file, String suffix) { + Valid.notBlank(file); + Valid.isTrue(file.toLowerCase().endsWith(Const.DOT + suffix), ErrorMessage.PLEASE_SELECT_SUFFIX_FILE, suffix); + return file; + } + } diff --git a/orion-visor-dependencies/pom.xml b/orion-visor-dependencies/pom.xml index 0e27d55d..f617b4c6 100644 --- a/orion-visor-dependencies/pom.xml +++ b/orion-visor-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/dromara/orion-visor - 2.3.9 + 2.4.0 2.7.17 2.7.15 1.5.0 @@ -34,6 +34,7 @@ 4.11.0 1.0.7 7.2.11.RELEASE + 1.5.5 @@ -312,6 +313,13 @@ podam ${podam.version} + + + + org.apache.guacamole + guacamole-common + ${guacd.version} + diff --git a/orion-visor-launch/pom.xml b/orion-visor-launch/pom.xml index f2ad92f5..fa4e9ee6 100644 --- a/orion-visor-launch/pom.xml +++ b/orion-visor-launch/pom.xml @@ -23,13 +23,26 @@ true - + org.springframework.boot spring-boot-starter - + + + org.dromara.visor + orion-visor-common + + + + + org.dromara.visor + orion-visor-module-common + ${revision} + + + org.dromara.visor orion-visor-module-infra-service @@ -40,6 +53,16 @@ orion-visor-module-asset-service ${revision} + + org.dromara.visor + orion-visor-module-exec-service + ${revision} + + + org.dromara.visor + orion-visor-module-terminal-service + ${revision} + diff --git a/orion-visor-launch/src/main/resources/application-dev.yaml b/orion-visor-launch/src/main/resources/application-dev.yaml index 7763d778..2be013cd 100644 --- a/orion-visor-launch/src/main/resources/application-dev.yaml +++ b/orion-visor-launch/src/main/resources/application-dev.yaml @@ -24,6 +24,11 @@ spring: server: enabled: false +guacd: + host: ${GUACD_HOST:127.0.0.1} + port: ${GUACD_PORT:4822} + drive-path: ${GUACD_DRIVE_PATH:/home/guacd} + management: endpoints: enabled-by-default: false @@ -33,7 +38,7 @@ management: mybatis-plus: configuration: - # sql 日志打印 + # 日志打印 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl no: diff --git a/orion-visor-launch/src/main/resources/application-prod.yaml b/orion-visor-launch/src/main/resources/application-prod.yaml index 6ea73dd7..244f939c 100644 --- a/orion-visor-launch/src/main/resources/application-prod.yaml +++ b/orion-visor-launch/src/main/resources/application-prod.yaml @@ -41,6 +41,11 @@ spring: server: enabled: true +guacd: + host: ${GUACD_HOST:127.0.0.1} + port: ${GUACD_PORT:4822} + drive-path: ${GUACD_DRIVE_PATH:/usr/share/guacd/drive} + management: endpoints: enabled-by-default: true diff --git a/orion-visor-launch/src/main/resources/application.yaml b/orion-visor-launch/src/main/resources/application.yaml index ada803a1..a84f28e7 100644 --- a/orion-visor-launch/src/main/resources/application.yaml +++ b/orion-visor-launch/src/main/resources/application.yaml @@ -196,6 +196,12 @@ orion: asset: group: "asset - 资产模块" path: "asset" + exec: + group: "exec - 执行模块" + path: "exec" + terminal: + group: "terminal - 终端模块" + path: "terminal" logging: # 全局日志打印 printer: @@ -208,6 +214,7 @@ orion: field: ignore: - password,beforePassword,newPassword,useNewPassword,publicKey,privateKey,privateKeyPassword + - accessKey,secretKey - metrics desensitize: storage: diff --git a/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java b/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java index bde1e71d..4f675802 100644 --- a/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java +++ b/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java @@ -39,9 +39,9 @@ import java.util.function.Function; */ public class ReplaceVersion { - private static final String TARGET_VERSION = "2.3.8"; + private static final String TARGET_VERSION = "2.3.9"; - private static final String REPLACE_VERSION = "2.3.9"; + private static final String REPLACE_VERSION = "2.4.0"; private static final String PATH = new File("").getAbsolutePath(); @@ -50,6 +50,7 @@ public class ReplaceVersion { "docker/adminer/build.sh", "docker/mysql/build.sh", "docker/redis/build.sh", + "docker/guacd/build.sh", "docker/service/build.sh", "docker/ui/build.sh", "docker-compose.yml",