How it works...

The SSHd Shell integration with Spring Boot provides you with many commands out of the box. We can invoke the same management end points that were available to us over HTTP and JMX. We can get access to the JVM information, make changes to the logging configuration, and even interact with the JMX server and all the registered MBeans. The list of all the possibilities is really impressive and very rich in functionalities, so I would definitely advise you to read the reference documentation on SSHd Shell by going to https://github.com/anand1st/sshd-shell-spring-boot.

In Spring Boot, the expectation is that any class annotated with @SshdShellCommand will be automatically picked up and registered as an SSHd Shell command. The value of the annotation attribute translates into the main command name. In our case, we set the class annotation attribute value field to publishers and this became the top-level command name in the SSH Shell console.

If the command contains sub-commands, as in our publishers command example, then, the methods of the class that are also annotated with @SshdShellCommand get registered as sub-commands to the main command. If a class has only one method, it will automatically become the only command for a given class that would be executed when the command name is typed. If we want multiple sub-commands to reside in the class command, as we did with publishers, each method that translates into a command needs to be annotated with @SshdShellCommand.

Currently, SSHd Shell framework has a limitation of being able to pass only one attribute argument to the command, but there is work going on to expand on that capability. In the mean time, it is recommended that JSON payload is used to communicate with the commands as inputs or outputs.

The following attributes are available on the annotations:

  • value: This attribute defines the command or sub-command name. Even though the name of the method does not need to match the name of the command, it is a good convention for keeping the two in sync to make the code more readable.
  • description: This attribute defines the text that gets displayed when the help command is invoked. It is a good place to communicate with the users how the command is expected to be used, what inputs it takes, and so on. It is a good idea to provide as much description and documentation as possible as in the Shell, one would like to clearly educate the users of what needs to happen and how to call the command. The man pages are great so keep the documentation top notch.
  • roles: This attribute enables us to define a security constraint on who is allowed to execute the given command. If Spring Security is also used, SSHd Shell provides the ability to configure a custom or specific AuthenticationProvider to be used for handling user authentication and role binding. For example, it would be easy to connect your application to the company's LDAP server and allow developers to use their regular credentials and also configure different role access controls, based on the needs of the particular organization.

Each command can be queried for its usage by using help, or in the case of a command containing sub-commands, by typing the name of the top-level command.

While SSHd Shell comes with many built-in commands, one can easily add custom commands, taking advantage of standard Spring / Spring Boot programming style, using the @Autowired and @Component annotations to get the necessary dependencies to be wired in and automatically configured during the application start life cycle.

SSHd Shell also provides a nice functionality enabling the use of post-processors, invoked by a pipe (|) symbol. The current support allows for output highlighting | h packt, which will highlight the word packt in the output, or emailing response output  | m [email protected], which will email the response of a command to the specified email address, given that Spring Mail is also configured and available.

It would be great if we could chain different commands together, like in Linux proper, so as to help process the output and filter out the necessary data when the amount of information tends to get overwhelming. Imagine that our publishers list command returns not 2, but 2000 publishers. From this list, we want to find the ones that start with Pa.

Even though SSHd Shell does not provide this type of functionality out of the box, it does offer us an ability to implement our own post-processors by defining beans that extend the BaseUserInputProcessor class. Let's create one that would provide support for filtering JSON responses, something similar to how the jq command-line utility works.

To achieve this, let's create another class named JsonPathUserInputProcessor.java in the src/main/java/com/example/bookpub/command directory at the root of our project with the following content:

@Component 
@Order(3) 
public class JsonPathUserInputProcessor 
extends BaseUserInputProcessor { private final Pattern pattern = Pattern.compile("[wW]+s?|s?jq (.+)"); @Override public Optional<UsageInfo> getUsageInfo() { return Optional.of(new UsageInfo(Arrays.<UsageInfo.Row>asList( new UsageInfo.Row("jq <arg>", "JSON Path Query <arg> in response output of command execution"), new UsageInfo.Row("", "Example usage: help | jq $.<name>")))); } @Override public Pattern getPattern() { return pattern; } @Override public void processUserInput(String userInput) throws
InterruptedException, ShellException{ String[] part = splitAndValidateCommand(userInput, "|", 2); Matcher matcher = pattern.matcher(userInput); Assert.isTrue(matcher.find(), "Unexpected error"); String jsonQuery = matcher.group(1).trim(); try { String output = processCommands(part[0]); Object response = JsonPath.read(output, jsonQuery); ConsoleIO.writeJsonOutput(response); } catch (Exception e) { ConsoleIO.writeOutput(String.format("Unable to process
query %s%n%s", jsonQuery, e.getMessage())); } } }

Using the pipe functionality, we can easily chain the publishers list command with the jq command in the following way:

publishers list | jq $..[?(@.name =~ /Pa.*/i)]

In our example, this should return us only one record, as follows:

[ {
"id" : 1,
"name" : "Packt"
} ]

While it is not a full-fledged pipe functionality, the use of input processors allows for adding functionalities such as sorting, filtering, and displaying rendering, which give more flexibility to modularize and reuse common behaviors.

The SSHd Shell Spring Boot integration comes with a number of configuration options allowing us to disable the component, configure authentication settings, and specify usernames, passwords, and even key certificates. For example, if we want to use a specific username and password, we can do so by configuring the following properties:

sshd.shell.username=remote
sshd.shell.password=shell
  

In a real-world enterprise environment, it is more common to use the shared keys for restricted access and these can be configured using the sshd.shell.publicKeyFile=<key path> or sshd.shell.hostKeyFile=<key path> properties. Alternatively, and probably a better approach, as was already mentioned earlier, using a custom AuthenticationProvider implementation together with Spring Security allows the integrate of authentication mechanisms into the company's authentication system.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.156.46