-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added helper commands to the ssh server, implemented whoami command
- Loading branch information
Showing
4 changed files
with
122 additions
and
30 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
src/main/java/lt/pow/nukagit/ssh/NukagitCliCommandFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package lt.pow.nukagit.ssh; | ||
|
||
import org.apache.sshd.server.channel.ChannelSession; | ||
import org.apache.sshd.server.command.Command; | ||
import org.apache.sshd.server.command.CommandFactory; | ||
import org.apache.sshd.server.shell.UnknownCommandFactory; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.slf4j.MDC; | ||
|
||
import java.io.IOException; | ||
|
||
public class NukagitCliCommandFactory implements CommandFactory { | ||
Logger LOGGER = LoggerFactory.getLogger(NukagitCliCommandFactory.class); | ||
|
||
@Override | ||
public Command createCommand(ChannelSession channel, String command) throws IOException { | ||
String username = (String) channel.getSession().getIoSession().getAttribute("username"); | ||
MDC.put("username", username); | ||
MDC.put("command", command); | ||
LOGGER.info("User '{}' ran command '{}'", username, command); | ||
if ("whoami".equals(command.strip())) | ||
return new WhoAmICommand(command); | ||
else | ||
return UnknownCommandFactory.INSTANCE.createCommand(channel, command); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package lt.pow.nukagit.ssh; | ||
|
||
import org.apache.sshd.server.command.AbstractCommandSupport; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
public class WhoAmICommand extends AbstractCommandSupport { | ||
public WhoAmICommand(String command) { | ||
super(command, null); | ||
} | ||
|
||
@Override | ||
public void run() { | ||
String username = (String) this.getServerSession().getIoSession().getAttribute("username"); | ||
try { | ||
this.getOutputStream().write(String.format("You are: %s\n", username).getBytes(StandardCharsets.UTF_8)); | ||
onExit(0); | ||
} catch (IOException e) { | ||
onExit(1); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,9 @@ import lt.pow.nukagit.proto.RepositoriesServiceGrpc | |
import lt.pow.nukagit.proto.Users | ||
import lt.pow.nukagit.proto.UsersServiceGrpc | ||
import org.apache.sshd.client.SshClient | ||
import org.apache.sshd.client.channel.ClientChannel | ||
import org.apache.sshd.client.channel.ClientChannelEvent | ||
import org.apache.sshd.common.channel.Channel | ||
import org.apache.sshd.git.transport.GitSshdSessionFactory | ||
import org.bouncycastle.openssl.PEMKeyPair | ||
import org.bouncycastle.openssl.PEMParser | ||
|
@@ -26,7 +29,9 @@ import org.testcontainers.utility.DockerImageName | |
import spock.lang.Specification | ||
import spock.lang.TempDir | ||
|
||
import java.nio.charset.StandardCharsets | ||
import java.security.KeyPair | ||
import java.util.concurrent.TimeUnit | ||
|
||
@Testcontainers | ||
class NukagitIntegrationTest extends Specification { | ||
|
@@ -41,6 +46,7 @@ class NukagitIntegrationTest extends Specification { | |
.withExposedPorts(9000) | ||
.withCommand("server /data --console-address :9001") | ||
|
||
static final String USERNAME = "testuser" | ||
var component = DaggerTestComponent.create() | ||
SshClient sshClient | ||
KeyPair keyPair | ||
|
@@ -98,9 +104,10 @@ class NukagitIntegrationTest extends Specification { | |
|
||
keyPair = loadKeyPair('/fixtures/id_ecdsa') | ||
sshClient.addPublicKeyIdentity(keyPair) | ||
sshClient.start() | ||
|
||
usersGrpcClient.createUser(Users.CreateUserRequest.newBuilder() | ||
.setUsername("user") | ||
.setUsername(USERNAME) | ||
.setPublicKey(loadPublicKeyString('/fixtures/id_ecdsa.pub')) | ||
.build()) | ||
|
||
|
@@ -158,4 +165,36 @@ class NukagitIntegrationTest extends Specification { | |
git.commit().setAuthor("test", "[email protected]").setMessage("Test Change").call() | ||
git.push().call() | ||
} | ||
|
||
def sshRun(String command) { | ||
def session = sshClient.connect("git", "localhost", sshPort).verify().getSession() | ||
session.auth().verify() | ||
ByteArrayOutputStream responseStream = new ByteArrayOutputStream() | ||
ByteArrayOutputStream errorStream = new ByteArrayOutputStream() | ||
ClientChannel channel = session.createChannel(Channel.CHANNEL_EXEC, command) | ||
channel.setOut(responseStream) | ||
channel.setErr(errorStream) | ||
channel.open().await(1, TimeUnit.SECONDS) | ||
channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 5000) | ||
channel.close(false) | ||
return [responseStream.toString(StandardCharsets.UTF_8), errorStream.toString(StandardCharsets.UTF_8), channel.exitStatus] | ||
} | ||
|
||
def "test whoami"() { | ||
when: | ||
def (out, err, status) = sshRun("whoami") | ||
then: | ||
status == 0 | ||
err == "" | ||
out == "You are: ${USERNAME}\n" | ||
} | ||
|
||
def "test invalid command"() { | ||
when: | ||
def (out, err, status) = sshRun("dummy") | ||
then: | ||
status == 1 | ||
err == "Unknown command: dummy\n" | ||
out == "" | ||
} | ||
} |