Skip to content

Commit

Permalink
fix ssh bug
Browse files Browse the repository at this point in the history
  • Loading branch information
githubname1024 committed Apr 3, 2024
1 parent aa7fcc1 commit 204c594
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sohu.cache.configuration;

import com.sohu.cache.ssh.SSHMachineInfo;
import com.sohu.cache.ssh.SSHSessionPooledObjectFactory;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
Expand All @@ -24,7 +25,7 @@ public class SSHPoolConfig {
* @return
*/
@Bean
public GenericKeyedObjectPool<String, ClientSession> clientSessionPool() throws GeneralSecurityException, IOException {
public GenericKeyedObjectPool<SSHMachineInfo, ClientSession> clientSessionPool() throws GeneralSecurityException, IOException {
GenericKeyedObjectPoolConfig genericKeyedObjectPoolConfig = new GenericKeyedObjectPoolConfig();
genericKeyedObjectPoolConfig.setTestWhileIdle(true);
genericKeyedObjectPoolConfig.setTestOnReturn(true);
Expand All @@ -35,7 +36,7 @@ public GenericKeyedObjectPool<String, ClientSession> clientSessionPool() throws
genericKeyedObjectPoolConfig.setTimeBetweenEvictionRunsMillis(20000);
genericKeyedObjectPoolConfig.setJmxEnabled(false);
SSHSessionPooledObjectFactory factory = new SSHSessionPooledObjectFactory();
GenericKeyedObjectPool<String, ClientSession> genericKeyedObjectPool = new GenericKeyedObjectPool<>(
GenericKeyedObjectPool<SSHMachineInfo, ClientSession> genericKeyedObjectPool = new GenericKeyedObjectPool<>(
factory,
genericKeyedObjectPoolConfig);
return genericKeyedObjectPool;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.sohu.cache.ssh;

import lombok.Builder;
import lombok.Data;

import java.util.Objects;

/**
* @Author: zengyizhao
* @CreateTime: 2024/4/3 12:38
* @Description: ssh session key
* @Version: 1.0
*/
@Data
@Builder
public class SSHMachineInfo {

/**
* ip
*/
private String ip;

/**
* 用户名
*/
private String username;

/**
* 登录方式
*/
private int authType;

/**
* 密码
*/
private String password;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SSHMachineInfo that = (SSHMachineInfo) o;
return authType == that.authType && Objects.equals(ip, that.ip) && Objects.equals(password, that.password) && Objects.equals(username, that.username);
}

@Override
public int hashCode() {
return Objects.hash(ip, username, authType, password);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.config.keys.loader.KeyPairResourceLoader;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
Expand All @@ -19,7 +24,7 @@
* @Auther: yongfeigao
* @Date: 2023/10/20
*/
public class SSHSessionPooledObjectFactory implements KeyedPooledObjectFactory<String, ClientSession> {
public class SSHSessionPooledObjectFactory implements KeyedPooledObjectFactory<SSHMachineInfo, ClientSession> {

private final Logger logger = LoggerFactory.getLogger(getClass());

Expand All @@ -38,45 +43,53 @@ public SSHSessionPooledObjectFactory() throws GeneralSecurityException, IOExcept
}

@Override
public PooledObject<ClientSession> makeObject(String ip) throws Exception {
public PooledObject<ClientSession> makeObject(SSHMachineInfo sshMachineInfo) throws Exception {
int port = ConstUtils.SSH_PORT_DEFAULT;
ClientSession session = sshClient.getClient().connect(ConstUtils.USERNAME, ip,
ClientSession session = sshClient.getClient().connect(ConstUtils.USERNAME, sshMachineInfo.getIp(),
port).verify(ConstUtils.SSH_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS).getSession();
session.setUsername(sshMachineInfo.getUsername());
if(sshMachineInfo.getAuthType() == SshAuthTypeEnum.PASSWORD.getValue()){
session.addPasswordIdentity(sshMachineInfo.getPassword());
}else if(sshMachineInfo.getAuthType() == SshAuthTypeEnum.PUBLIC_KEY.getValue()){
KeyPairResourceLoader loader = SecurityUtils.getKeyPairResourceParser();
Collection<KeyPair> keys = loader.loadKeyPairs(null, Paths.get(ConstUtils.PUBLIC_KEY_PEM), null);
session.addPublicKeyIdentity(keys.iterator().next());
}
session.auth().verify(ConstUtils.SSH_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);
logger.info("create object, key:{}", ip);
logger.info("create object, key:{}", sshMachineInfo);
return new DefaultPooledObject<>(session);
}

@Override
public void destroyObject(String ip, PooledObject<ClientSession> pooledObject) throws Exception {
public void destroyObject(SSHMachineInfo sshMachineInfo, PooledObject<ClientSession> pooledObject) throws Exception {
ClientSession clientSession = pooledObject.getObject();
if (clientSession != null) {
try {
clientSession.close();
} catch (Exception e) {
logger.warn("close err, key:{}", ip, e);
logger.warn("close err, key:{}", sshMachineInfo, e);
}
}
logger.info("destroy object {}", ip);
logger.info("destroy object {}", sshMachineInfo);
}

@Override
public boolean validateObject(String ip, PooledObject<ClientSession> pooledObject) {
public boolean validateObject(SSHMachineInfo sshMachineInfo, PooledObject<ClientSession> pooledObject) {
boolean closed = pooledObject.getObject().isClosed();
if (closed) {
logger.warn("{} session closed", ip);
logger.warn("{} session closed", sshMachineInfo);
return false;
}
return true;
}

@Override
public void activateObject(String ip, PooledObject<ClientSession> pooledObject) throws Exception {
public void activateObject(SSHMachineInfo sshMachineInfo, PooledObject<ClientSession> pooledObject) throws Exception {

}

@Override
public void passivateObject(String ip, PooledObject<ClientSession> pooledObject) throws Exception {
public void passivateObject(SSHMachineInfo sshMachineInfo, PooledObject<ClientSession> pooledObject) throws Exception {

}
}
26 changes: 7 additions & 19 deletions cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

import com.sohu.cache.exception.SSHException;
import com.sohu.cache.util.ConstUtils;
import com.sohu.cache.web.enums.SshAuthTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.config.keys.loader.KeyPairResourceLoader;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.scp.client.ScpClient;
import org.apache.sshd.scp.client.ScpClientCreator;
import org.slf4j.Logger;
Expand All @@ -24,11 +21,8 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.security.KeyPair;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -44,7 +38,7 @@ public class SSHTemplate {
PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.GROUP_READ, PosixFilePermission.OTHERS_READ);

@Autowired
private GenericKeyedObjectPool<String, ClientSession> clientSessionPool;
private GenericKeyedObjectPool<SSHMachineInfo, ClientSession> clientSessionPool;

private static final int CONNCET_TIMEOUT = 5000;

Expand All @@ -67,21 +61,15 @@ public Result execute(String ip, SSHCallback callback) throws SSHException{
public Result execute(String ip, int port, String username, String password,
SSHCallback callback) throws SSHException{
ClientSession session = null;
SSHMachineInfo sshMachineInfo = SSHMachineInfo.builder().ip(ip).username(username)
.authType(ConstUtils.SSH_AUTH_TYPE).password(password).build();
try {
session = clientSessionPool.borrowObject(ip);
session.setUsername(username);
if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PASSWORD.getValue()) {
session.addPasswordIdentity(password);
} else if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PUBLIC_KEY.getValue()) {
KeyPairResourceLoader loader = SecurityUtils.getKeyPairResourceParser();
Collection<KeyPair> keys = loader.loadKeyPairs(null, Paths.get(ConstUtils.PUBLIC_KEY_PEM), null);
session.addPublicKeyIdentity(keys.iterator().next());
}
session = clientSessionPool.borrowObject(sshMachineInfo);
return callback.call(new SSHSession(session, ip));
} catch (Exception e) {
throw new SSHException("SSH exception: " + e.getMessage(), e);
} finally {
close(ip, session);
close(sshMachineInfo, session);
}
}

Expand Down Expand Up @@ -154,10 +142,10 @@ private void close(BufferedReader read) {
}
}

private void close(String ip, ClientSession session) {
private void close(SSHMachineInfo sshMachineInfo, ClientSession session) {
if (session != null) {
try {
clientSessionPool.returnObject(ip, session);
clientSessionPool.returnObject(sshMachineInfo, session);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
Expand Down

0 comments on commit 204c594

Please sign in to comment.