Skip to content

Commit

Permalink
remove use of temporary file to authenticate with password
Browse files Browse the repository at this point in the history
improve tests
add new test
  • Loading branch information
ltamaster committed Jun 16, 2023
1 parent 91e1985 commit 7fc6c3e
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,9 @@ public NodeExecutorResult executeCommand(ExecutionContext context, String[] comm
sshexec.execute(sshClient);
success = true;
} catch (Exception e) {
final ExtractFailure extractJschFailure = extractFailure(e, node, commandtimeout, contimeout, context.getFramework());
errormsg = extractJschFailure.getErrormsg();
failureReason = extractJschFailure.getReason();
final ExtractFailure extractFailure = extractFailure(e, node, commandtimeout, contimeout, context.getFramework());
errormsg = extractFailure.getErrormsg();
failureReason = extractFailure.getReason();
context.getExecutionListener().log(
3,
String.format(
Expand Down
56 changes: 28 additions & 28 deletions src/main/java/com/plugin/sshjplugin/model/SSHJAuthentication.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package com.plugin.sshjplugin.model;
import com.dtolabs.rundeck.plugins.PluginLogger;
import com.dtolabs.utils.Streams;
import com.plugin.sshjplugin.SSHJBuilder;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
import java.io.File;
import java.io.IOException;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;
import net.schmizz.sshj.userauth.keyprovider.KeyFormat;
import net.schmizz.sshj.userauth.keyprovider.KeyProviderUtil;
import net.schmizz.sshj.userauth.password.PasswordUtils;

import java.io.*;

public class SSHJAuthentication {

SSHJConnection.AuthenticationType authenticationType;
String username;
String password;
String privateKeyFile;
String privateKeyContent;
String passphrase;
PluginLogger logger;
SSHJConnection connectionParameters;
Expand All @@ -28,35 +33,34 @@ void authenticate(final SSHClient ssh) throws IOException {

switch (authenticationType) {
case privateKey:
try{
privateKeyFile = connectionParameters.getPrivateKeyPath();
logger.log(3, "Authenticating using private key");
logger.log(3, "Authenticating using private key");

} catch (IOException e) {
logger.log(0, "Failed to get SSH key: " + e.getMessage());
String privateKeyPath = connectionParameters.getPrivateKeyStoragePath();
try{
privateKeyContent = connectionParameters.getPrivateKeyStorage(privateKeyPath);
} catch (Exception e) {
throw new SSHJBuilder.BuilderException("Failed to read SSH Key Storage stored at path: " + privateKeyPath);
}

String passphrasePath = connectionParameters.getPrivateKeyPassphraseStoragePath();
try{
passphrase = connectionParameters.getPrivateKeyPassphrase(passphrasePath);
} catch (IOException e) {
logger.log(0, "Failed to read SSH Passphrase stored at path: " + passphrasePath);
} catch (Exception e) {
throw new SSHJBuilder.BuilderException("Failed to read SSH Passphrase stored at path: " + passphrasePath);
}

KeyProvider key = null;
if (null != privateKeyFile && !"".equals(privateKeyFile)) {
if (!new File(privateKeyFile).exists()) {
throw new SSHJBuilder.BuilderException("SSH Keyfile does not exist: " + privateKeyFile);
}
logger.log(3, "[sshj-debug] Using ssh keyfile: " + privateKeyFile);
}
KeyFormat format = KeyProviderUtil.detectKeyFileFormat(privateKeyContent,true);
FileKeyProvider keys = Factory.Named.Util.create(ssh.getTransport().getConfig().getFileKeyProviderFactories(), format.toString());

logger.log(3, "[sshj-debug] Using ssh keyfile: " + privateKeyPath);

if (passphrase == null) {
key = ssh.loadKeys(privateKeyFile);
keys.init(new StringReader(privateKeyContent), null);
} else {
key = ssh.loadKeys(privateKeyFile, passphrase);
logger.log(3, "[sshj-debug] Using Passphrase: " + passphrasePath);
keys.init(new StringReader(privateKeyContent), PasswordUtils.createOneOff(passphrase.toCharArray()));
}
ssh.authPublickey(username, key);
ssh.authPublickey(username, keys);
break;
case password:
String passwordPath = connectionParameters.getPasswordStoragePath();
Expand All @@ -65,15 +69,11 @@ void authenticate(final SSHClient ssh) throws IOException {
}
try{
password = connectionParameters.getPassword(passwordPath);
} catch (IOException e) {
logger.log(0, "Failed to read SSH Password stored at path: " + passwordPath);
} catch (Exception e) {
throw new SSHJBuilder.BuilderException("Failed to read SSH Password stored at path: " + passwordPath);
}

if (password != null) {
ssh.authPassword(username, password);
}else{
throw new SSHJBuilder.BuilderException("SSH password wasn't set, please define a password");
}
ssh.authPassword(username, password);
break;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/plugin/sshjplugin/model/SSHJConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ static enum AuthenticationType {

InputStream getPrivateKeyStorageData(String path);

String getPrivateKeyStorage(String path) throws IOException;

String getPasswordStoragePath();

String getPassword(String path) throws IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ public String getPrivateKeyPath() throws IOException {

@Override
public String getPrivateKeyStoragePath(){

String path = propertyResolver.resolve(SSHJNodeExecutorPlugin.NODE_ATTR_SSH_KEY_RESOURCE);
if (path == null && framework.hasProperty(Constants.SSH_KEYRESOURCE_PROP)) {
//return default framework level
Expand All @@ -85,14 +84,18 @@ public String getPrivateKeyStoragePath(){
@Override
public InputStream getPrivateKeyStorageData(String path){
try {
InputStream sshKey = propertyResolver.getPrivateKeyStorageData(path);
return sshKey;
return propertyResolver.getPrivateKeyStorageData(path);
} catch (IOException e) {
throw new RuntimeException(e);
}

}

@Override
public String getPrivateKeyStorage(String path) throws IOException {
return propertyResolver.getPrivateKeyStorage(path);
}

String getPrivateKeyfilePath() {
String path = propertyResolver.resolve(SSHJNodeExecutorPlugin.NODE_ATTR_SSH_KEYPATH);
if (path == null && framework.hasProperty(Constants.SSH_KEYPATH_PROP)) {
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/com/plugin/sshjplugin/util/PropertyResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ public InputStream getPrivateKeyStorageData(String path) throws IOException {

}

public String getPrivateKeyStorage(String path) throws IOException {
//expand properties in path
if (path != null && path.contains("${")) {
path = DataContextUtils.replaceDataReferencesInString(path, context.getDataContext());
}
if (null == path) {
return null;
}

ResourceMeta contents = context.getStorageTree().getResource(path).getContents();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
contents.writeContent(byteArrayOutputStream);
return byteArrayOutputStream.toString();

}

public String getStoragePath(String property) {
String path = resolve(property);

Expand All @@ -83,8 +99,7 @@ public String getPasswordFromPath(String path) throws IOException {
ResourceMeta contents = context.getStorageTree().getResource(path).getContents();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
contents.writeContent(byteArrayOutputStream);
String password = new String(byteArrayOutputStream.toByteArray());
return password;
return byteArrayOutputStream.toString();
}

public String nonBlank(final String input) {
Expand Down
Loading

0 comments on commit 7fc6c3e

Please sign in to comment.