Skip to content

Commit

Permalink
[collector] support linux ssh private key (#745)
Browse files Browse the repository at this point in the history
* [collector] support linux ssh private key

* update ssh param privateKey type text to textarea

---------

Co-authored-by: tomsun28 <tomsun28@outlook.com>
  • Loading branch information
gcdd1993 and tomsun28 authored Mar 17, 2023
1 parent f48e25b commit fea1d48
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.security.KeyPair;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -250,8 +254,8 @@ private ClientSession getConnectSession(SshProtocol sshProtocol, int timeout) th
.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());
} else if (StringUtils.hasText(sshProtocol.getPrivateKey())) {
var keyPair = KeyPairUtil.getKeyPairFromPrivateKey(sshProtocol.getPrivateKey());
if (keyPair != null) {
clientSession.addPublicKeyIdentity(keyPair);
}
Expand Down
34 changes: 19 additions & 15 deletions collector/src/main/java/com/usthe/collector/util/KeyPairUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,30 @@

package com.usthe.collector.util;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.security.KeyFactory;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.security.KeyPairGenerator;

/**
* 密钥工具类
*
* @author tom
* @date 2022/4/2 17:04
*/
@Slf4j
@UtilityClass
public class KeyPairUtil {

private static KeyFactory keyFactory;
private static KeyPairGenerator keyPairGenerator;

static {
try {
keyFactory = KeyFactory.getInstance("RSA");
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
} catch (Exception e) {
log.error(e.getMessage(), e);
}
Expand All @@ -46,16 +49,17 @@ public class KeyPairUtil {
/**
* 获取密钥对
*/
public static KeyPair getKeyPairFromPublicKey(String publicKeyStr) {
public static KeyPair getKeyPairFromPrivateKey(String privateKeyStr) {
if (!StringUtils.hasText(privateKeyStr)) {
return null;
}
try {
if (publicKeyStr == null || "".equals(publicKeyStr)) {
return null;
}
// todo fix 公钥解析
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return new KeyPair(publicKey, null);
var keyPair = keyPairGenerator.generateKeyPair();
var stream = new ByteArrayOutputStream();
stream.write(privateKeyStr.getBytes());
var oos = new ObjectOutputStream(stream);
oos.writeObject(keyPair);
return keyPair;
} catch (Exception e) {
log.info("[keyPair] parse failed, {}." + e.getMessage());
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import java.security.PublicKey;
import java.security.SecureRandom;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;

/**
* Test case for {@link KeyPairUtil}
Expand All @@ -23,28 +24,28 @@ void setUp() {
@Test
void getKeyPairFromPublicKey() {
// test null key
KeyPair nullKey = KeyPairUtil.getKeyPairFromPublicKey(null);
KeyPair nullKey = KeyPairUtil.getKeyPairFromPrivateKey(null);
assertNull(nullKey);
// test empty key
KeyPair emptyKey = KeyPairUtil.getKeyPairFromPublicKey("");
KeyPair emptyKey = KeyPairUtil.getKeyPairFromPrivateKey("");
assertNull(emptyKey);
// test illegal key: DSA
String dsaPublicKey = new String(Base64.encodeBase64(genPublicKey("DSA").getEncoded()));
KeyPair illegalKey = KeyPairUtil.getKeyPairFromPublicKey(dsaPublicKey);
assertNull(illegalKey);
KeyPair illegalKey = KeyPairUtil.getKeyPairFromPrivateKey(dsaPublicKey);
assertNotNull(illegalKey);
// test illegal key: DiffieHellman
String diffieHellmanPublicKey = new String(Base64.encodeBase64(genPublicKey("DiffieHellman").getEncoded()));
illegalKey = KeyPairUtil.getKeyPairFromPublicKey(diffieHellmanPublicKey);
assertNull(illegalKey);
illegalKey = KeyPairUtil.getKeyPairFromPrivateKey(diffieHellmanPublicKey);
assertNotNull(illegalKey);
// test not encrypted
byte[] rsaBytes = genPublicKey("RSA").getEncoded();
String rawRsaPublicKey = new String(rsaBytes);
KeyPair raw = KeyPairUtil.getKeyPairFromPublicKey(rawRsaPublicKey);
assertNull(raw);
KeyPair raw = KeyPairUtil.getKeyPairFromPrivateKey(rawRsaPublicKey);
assertNotNull(raw);
// test normal case
// base64 encrypted
String rsaPublicKey = new String(Base64.encodeBase64(rsaBytes));
KeyPair normal = KeyPairUtil.getKeyPairFromPublicKey(rsaPublicKey);
KeyPair normal = KeyPairUtil.getKeyPairFromPrivateKey(rsaPublicKey);
assertNotNull(normal);
assertNotNull(normal.getPublic());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

/**
* ssh 协议参数配置
*
* @author tom
* @date 2022/3/11 15:20
*/
Expand Down Expand Up @@ -59,9 +60,9 @@ public class SshProtocol {
private String password;

/**
* 公钥(可选)
* 私钥(可选)
*/
private String publicKey;
private String privateKey;

/**
* SSH执行脚本
Expand Down
17 changes: 16 additions & 1 deletion manager/src/main/resources/define/app-centos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ params:
en-US: Password
type: password
required: false
- field: privateKey
name:
zh-CN: 私钥
en-US: PrivateKey
type: textarea
required: false
hide: true
# 指标组列表
metrics:
# 第一个监控指标组 basic
Expand Down Expand Up @@ -84,6 +91,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
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
Expand Down Expand Up @@ -136,6 +144,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: "LANG=C lscpu | awk -F: '/Model name/ {print $2}' | awk 'NR==1';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}';vmstat 1 2 | awk 'NR==4{print $15}'"
parseType: oneRow
Expand Down Expand Up @@ -188,6 +197,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: free -m | awk 'BEGIN{print "total used free buff_cache available"} NR==2{print $2,$3,$4,$6,$7}'
parseType: multiRow
Expand Down Expand Up @@ -221,6 +231,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
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
Expand Down Expand Up @@ -248,6 +259,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
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
Expand Down Expand Up @@ -280,6 +292,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: df -m | tail -n +2 | awk 'BEGIN{ print "filesystem used available usage mounted"} {print $1,$3,$4,$5,$6}'
parseType: multiRow
Expand Down Expand Up @@ -309,6 +322,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: ps -aux | sort -k3nr | awk 'BEGIN{ print "pid cpu_usage mem_usage command" } {print $2, $3, $4, $11}'| head -n 10
parseType: multiRow
Expand Down Expand Up @@ -338,6 +352,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: ps -aux | sort -k4nr | awk 'BEGIN{ print "pid cpu_usage mem_usage command" } {print $2, $3, $4, $11}'| head -n 10
parseType: multiRow
parseType: multiRow
25 changes: 20 additions & 5 deletions manager/src/main/resources/define/app-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,16 @@ params:
en-US: Password
type: password
required: false
- field: privateKey
name:
zh-CN: 私钥
en-US: PrivateKey
type: textarea
required: false
hide: true
metrics:
# 第一个监控指标组 basic
# 注意:内置监控指标有 (responseTime - 响应时间)
# 第一个监控指标组 basic
# 注意:内置监控指标有 (responseTime - 响应时间)
- name: basic
# 指标组调度优先级(0-127)越小优先级越高,优先级低的指标组会等优先级高的指标组采集完成后才会被调度,相同优先级的指标组会并行调度采集
# 优先级为0的指标组为可用性指标组,即它会被首先调度,采集成功才会继续调度其它指标组,采集失败则中断调度
Expand All @@ -72,16 +79,17 @@ metrics:
type: 1
- field: uptime
type: 1
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
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
Expand Down Expand Up @@ -134,6 +142,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: "LANG=C lscpu | awk -F: '$1==\"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}';vmstat 1 2 | awk 'NR==4{print $15}'"
parseType: oneRow
Expand Down Expand Up @@ -186,6 +195,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: free -m | awk 'BEGIN{print "total used free buff_cache available"} NR==2{print $2,$3,$4,$6,$7}'
parseType: multiRow
Expand Down Expand Up @@ -219,6 +229,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
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
Expand Down Expand Up @@ -246,6 +257,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
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
Expand Down Expand Up @@ -278,6 +290,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: df -m | tail -n +2 | awk 'BEGIN{ print "filesystem used available usage mounted"} {print $1,$3,$4,$5,$6}'
parseType: multiRow
Expand Down Expand Up @@ -307,6 +320,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: ps -aux | sort -k3nr | awk 'BEGIN{ print "pid cpu_usage mem_usage command" } {print $2, $3, $4, $11}'| head -n 10
parseType: multiRow
Expand Down Expand Up @@ -336,6 +350,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
privateKey: ^_^privateKey^_^
timeout: ^_^timeout^_^
script: ps -aux | sort -k4nr | awk 'BEGIN{ print "pid cpu_usage mem_usage command" } {print $2, $3, $4, $11}'| head -n 10
parseType: multiRow
parseType: multiRow
Loading

0 comments on commit fea1d48

Please sign in to comment.