diff --git a/collector/src/main/java/com/usthe/collector/collect/common/ssh/CommonSshClient.java b/collector/src/main/java/com/usthe/collector/collect/common/ssh/CommonSshClient.java index 509bbbc..c9e6d60 100644 --- a/collector/src/main/java/com/usthe/collector/collect/common/ssh/CommonSshClient.java +++ b/collector/src/main/java/com/usthe/collector/collect/common/ssh/CommonSshClient.java @@ -2,6 +2,9 @@ package com.usthe.collector.collect.common.ssh; import lombok.extern.slf4j.Slf4j; import org.apache.sshd.client.SshClient; +import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier; +import org.apache.sshd.common.PropertyResolverUtils; +import org.apache.sshd.core.CoreModuleProperties; /** * ssh公共client @@ -16,6 +19,14 @@ public class CommonSshClient { static { sshClient = SshClient.setUpDefaultClient(); + // 接受所有服务端公钥校验,会打印warn日志 Server at {} presented unverified {} key: {} + AcceptAllServerKeyVerifier verifier = AcceptAllServerKeyVerifier.INSTANCE; + sshClient.setServerKeyVerifier(verifier); + // 设置链接保活心跳10000毫秒一次, 客户端等待保活心跳超时响应时间3000毫秒 + PropertyResolverUtils.updateProperty( + sshClient, CoreModuleProperties.HEARTBEAT_INTERVAL.getName(), 10000); + PropertyResolverUtils.updateProperty( + sshClient, CoreModuleProperties.HEARTBEAT_REPLY_WAIT.getName(), 3000); sshClient.start(); } diff --git a/collector/src/main/java/com/usthe/collector/collect/ssh/SshCollectImpl.java b/collector/src/main/java/com/usthe/collector/collect/ssh/SshCollectImpl.java index 44c43fd..90a8ba3 100644 --- a/collector/src/main/java/com/usthe/collector/collect/ssh/SshCollectImpl.java +++ b/collector/src/main/java/com/usthe/collector/collect/ssh/SshCollectImpl.java @@ -5,6 +5,7 @@ import com.usthe.collector.collect.common.cache.CacheIdentifier; import com.usthe.collector.collect.common.cache.CommonCache; import com.usthe.collector.collect.common.ssh.CommonSshClient; import com.usthe.collector.util.CollectorConstants; +import com.usthe.collector.util.KeyPairUtil; import com.usthe.common.entity.job.Metrics; import com.usthe.common.entity.job.protocol.SshProtocol; import com.usthe.common.entity.message.CollectRep; @@ -19,6 +20,7 @@ import org.springframework.util.StringUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.ConnectException; +import java.security.KeyPair; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -56,8 +58,8 @@ public class SshCollectImpl extends AbstractCollect { return; } SshProtocol sshProtocol = metrics.getSsh(); - // 超时时间默认300毫秒 - int timeout = 3000; + // 超时时间默认6000毫秒 + int timeout = 6000; try { timeout = Integer.parseInt(sshProtocol.getTimeout()); } catch (Exception e) { @@ -181,6 +183,13 @@ public class SshCollectImpl extends AbstractCollect { .verify(timeout, TimeUnit.MILLISECONDS).getSession(); if (StringUtils.hasText(sshProtocol.getPassword())) { clientSession.addPasswordIdentity(sshProtocol.getPassword()); + } else if (StringUtils.hasText(sshProtocol.getPublicKey())) { + KeyPair keyPair = KeyPairUtil.getKeyPairFromPublicKey(sshProtocol.getPublicKey()); + if (keyPair != null) { + clientSession.addPublicKeyIdentity(keyPair); + } + } else { + throw new IllegalArgumentException("需填写账户登陆密码或公钥"); } // 进行认证 if (!clientSession.auth().verify(timeout, TimeUnit.MILLISECONDS).isSuccess()) { diff --git a/collector/src/main/java/com/usthe/collector/util/KeyPairUtil.java b/collector/src/main/java/com/usthe/collector/util/KeyPairUtil.java new file mode 100644 index 0000000..5cc8132 --- /dev/null +++ b/collector/src/main/java/com/usthe/collector/util/KeyPairUtil.java @@ -0,0 +1,48 @@ +package com.usthe.collector.util; + +import lombok.extern.slf4j.Slf4j; +import sun.misc.BASE64Decoder; + +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; + +/** + * 密钥工具类 + * @author tom + * @date 2022/4/2 17:04 + */ +@Slf4j +public class KeyPairUtil { + + private static KeyFactory keyFactory; + + static { + try { + keyFactory = KeyFactory.getInstance("RSA"); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + + /** + * 获取密钥对 + */ + public static KeyPair getKeyPairFromPublicKey(String publicKeyStr) { + try { + if (publicKeyStr == null || "".equals(publicKeyStr)) { + return null; + } + // todo fix 公钥解析 + byte[] publicKeyBytes = (new BASE64Decoder()).decodeBuffer(publicKeyStr); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); + PublicKey publicKey = keyFactory.generatePublic(keySpec); + return new KeyPair(publicKey, null); + } catch (Exception e) { + log.info("[keyPair] parse failed, {}." + e.getMessage()); + return null; + } + } + +} diff --git a/common/src/main/java/com/usthe/common/entity/job/protocol/SshProtocol.java b/common/src/main/java/com/usthe/common/entity/job/protocol/SshProtocol.java index 9c509f3..2d11fb8 100644 --- a/common/src/main/java/com/usthe/common/entity/job/protocol/SshProtocol.java +++ b/common/src/main/java/com/usthe/common/entity/job/protocol/SshProtocol.java @@ -29,7 +29,7 @@ public class SshProtocol { /** * 超时时间 */ - private String timeout = "3000"; + private String timeout = "6000"; /** * 用户名 diff --git a/common/src/main/java/com/usthe/common/entity/manager/Param.java b/common/src/main/java/com/usthe/common/entity/manager/Param.java index 1303292..7a7adf6 100644 --- a/common/src/main/java/com/usthe/common/entity/manager/Param.java +++ b/common/src/main/java/com/usthe/common/entity/manager/Param.java @@ -59,7 +59,7 @@ public class Param { * 参数值 */ @ApiModelProperty(value = "参数值", example = "8080", accessMode = READ_WRITE, position = 3) - @Length(max = 255) + @Length(max = 8126) private String value; /** diff --git a/manager/src/main/resources/define/app/linux.yml b/manager/src/main/resources/define/app/linux.yml index 6a8de26..d2dc7d7 100644 --- a/manager/src/main/resources/define/app/linux.yml +++ b/manager/src/main/resources/define/app/linux.yml @@ -16,6 +16,8 @@ configmap: type: 1 - key: password type: 2 + - key: timeout + type: 0 # 指标组列表 metrics: # 第一个监控指标组 basic @@ -44,6 +46,7 @@ metrics: port: ^_^port^_^ username: ^_^username^_^ password: ^_^password^_^ + timeout: ^_^timeout^_^ script: (uname -r ; hostname ; uptime | awk -F "," '{print $1}' | sed "s/ //g") | sed ":a;N;s/\n/^/g;ta" | awk -F '^' 'BEGIN{print "version hostname uptime"} {print $1, $2, $3}' # 响应数据解析方式:oneRow, multiRow parseType: multiRow @@ -75,6 +78,7 @@ metrics: port: ^_^port^_^ username: ^_^username^_^ password: ^_^password^_^ + timeout: ^_^timeout^_^ script: "LANG=C lscpu | awk -F: '/Model name/ {print $2}';awk '/processor/{core++} END{print core}' /proc/cpuinfo;uptime | sed 's/,/ /g' | awk '{for(i=NF-2;i<=NF;i++)print $i }' | xargs;vmstat 1 1 | awk 'NR==3{print $11}';vmstat 1 1 | awk 'NR==3{print $12}'" parseType: oneRow @@ -107,6 +111,7 @@ metrics: port: ^_^port^_^ username: ^_^username^_^ password: ^_^password^_^ + timeout: ^_^timeout^_^ script: free -m | grep Mem | awk 'BEGIN{print "total used free buff_cache available"} {print $2,$3,$4,$6,$7}' parseType: multiRow @@ -139,6 +144,7 @@ metrics: port: ^_^port^_^ username: ^_^username^_^ password: ^_^password^_^ + timeout: ^_^timeout^_^ script: vmstat -D | awk 'NR==1{print $1}';vmstat -D | awk 'NR==2{print $1}';vmstat 1 1 | awk 'NR==3{print $10}';vmstat 1 1 | awk 'NR==3{print $9}';vmstat 1 1 | awk 'NR==3{print $16}' parseType: oneRow @@ -164,5 +170,6 @@ metrics: port: ^_^port^_^ username: ^_^username^_^ password: ^_^password^_^ + timeout: ^_^timeout^_^ script: cat /proc/net/dev | tail -n +3 | awk 'BEGIN{ print "interface_name receive_bytes transmit_bytes"} {print $1,$2,$10}' parseType: multiRow \ No newline at end of file diff --git a/manager/src/main/resources/define/param/linux.yml b/manager/src/main/resources/define/param/linux.yml index f0a255a..bb4fe30 100644 --- a/manager/src/main/resources/define/param/linux.yml +++ b/manager/src/main/resources/define/param/linux.yml @@ -11,6 +11,12 @@ param: required: true defaultValue: 22 placeholder: '请输入端口' + - field: timeout + name: 超时时间 + type: number + required: false + defaultValue: 6000 + placeholder: '超时时间' - field: username name: 用户名 type: text @@ -19,4 +25,4 @@ param: - field: password name: 密码 type: password - required: true \ No newline at end of file + required: false \ No newline at end of file diff --git a/script/docker-compose/conf/sql/schema.sql b/script/docker-compose/conf/sql/schema.sql index fac0c8c..cd90efd 100644 --- a/script/docker-compose/conf/sql/schema.sql +++ b/script/docker-compose/conf/sql/schema.sql @@ -34,7 +34,7 @@ CREATE TABLE param id bigint not null auto_increment comment '参数ID', monitor_id bigint not null comment '监控ID', field varchar(100) not null comment '参数标识符', - value varchar(255) comment '参数值,最大字符长度255', + value varchar(8126) comment '参数值,最大字符长度8126', type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串', gmt_create timestamp default current_timestamp comment 'create time', gmt_update datetime default current_timestamp on update current_timestamp comment 'update time', diff --git a/script/docker-compose/conf/sureness.yml b/script/docker-compose/conf/sureness.yml index f95a3ad..cc02217 100644 --- a/script/docker-compose/conf/sureness.yml +++ b/script/docker-compose/conf/sureness.yml @@ -36,10 +36,10 @@ excludedResource: # eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289 account: - appId: admin - credential: admin@123. + credential: admin role: [role1,role2] - appId: tom - credential: tom@123. + credential: tom role: [role1,role2,role3] - appId: lili # 注意 Digest认证不支持加盐加密的密码账户 diff --git a/script/sql/schema.sql b/script/sql/schema.sql index fac0c8c..cd90efd 100644 --- a/script/sql/schema.sql +++ b/script/sql/schema.sql @@ -34,7 +34,7 @@ CREATE TABLE param id bigint not null auto_increment comment '参数ID', monitor_id bigint not null comment '监控ID', field varchar(100) not null comment '参数标识符', - value varchar(255) comment '参数值,最大字符长度255', + value varchar(8126) comment '参数值,最大字符长度8126', type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串', gmt_create timestamp default current_timestamp comment 'create time', gmt_update datetime default current_timestamp on update current_timestamp comment 'update time',