wish

package module
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2024 License: MIT Imports: 15 Imported by: 128

README

Wish


Latest Release GoDoc Build Status Codecov branch Go Report Card

Make SSH apps, just like that! 💫

SSH is an excellent platform to build remotely accessible applications on. It offers:

  • secure communication without the hassle of HTTPS certificates
  • user identification with SSH keys
  • accessiblity from anywhere with a terminal

Powerful protocols like Git work over SSH and you can even render TUIs directly over an SSH connection.

Wish is an SSH server with sensible defaults and a collection of middlewares that makes building SSH apps easy. Wish is built on gliderlabs/ssh and should be easy to integrate into any existing projects.

What are SSH Apps?

Usually, when we think about SSH, we think about remote shell access into servers, most commonly through openssh-server.

That's a perfectly valid and probably the most common use of SSH, but it can do so much more than that. Just like HTTP, SMTP, FTP and others, SSH is a protocol! It is a cryptographic network protocol for operating network services securely over an unsecured network. ^1

That means, among other things, that we can write custom SSH servers without touching openssh-server, so we can securely do more things than just providing a shell.

Wish is a library that helps writing these kind of apps using Go.

Middleware

Wish middlewares are analogous to those in several HTTP frameworks. They are essentially SSH handlers that you can use to do specific tasks, and then call the next middleware.

Notice that middlewares are composed from first to last, which means the last one is executed first.

Bubble Tea

The bubbletea middleware makes it easy to serve any Bubble Tea application over SSH. Each SSH session will get their own tea.Program with the SSH pty input and output connected. Client window dimension and resize messages are also natively handled by the tea.Program.

You can see a demo of the Wish middleware in action at: ssh git.charm.sh

Git

The git middleware adds git server functionality to any ssh server. It supports repo creation on initial push and custom public key based auth.

This middleware requires that git is installed on the server.

Logging

The logging middleware provides basic connection logging. Connects are logged with the remote address, invoked command, TERM setting, window dimensions and if the auth was public key based. Disconnect will log the remote address and connection duration.

Access Control

Not all applications will support general SSH connections. To restrict access to supported methods, you can use the activeterm middleware to only allow connections with active terminals connected and the accesscontrol middleware that lets you specify allowed commands.

Default Server

Wish includes the ability to easily create an always authenticating default SSH server with automatic server key generation.

Examples

There are examples for a standalone Bubble Tea application and Git server in the examples folder.

Apps Built With Wish

Pro Tip

When building various Wish applications locally you can add the following to your ~/.ssh/config to avoid having to clear out localhost entries in your ~/.ssh/known_hosts file:

Host localhost
    UserKnownHostsFile /dev/null

How it works?

Wish uses gliderlabs/ssh to implement its SSH server, and OpenSSH is never used nor needed — you can even uninstall it if you want to.

Incidentally, there's no risk of accidentally sharing a shell because there's no default behavior that does that on Wish.

Running with SystemD

If you want to run a Wish app with systemd, you can create an unit like so:

/etc/systemd/system/myapp.service:

[Unit]
Description=My App
After=network.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/home/myapp/
ExecStart=/usr/bin/myapp
Restart=on-failure

[Install]
WantedBy=multi-user.target

You can tune the values below, and once you're happy with them, you can run:

# need to run this every time you change the unit file
sudo systemctl daemon-reload

# start/restart/stop/etc:
sudo systemctl start myapp

If you use a new user for each app (which is good), you'll need to create them first:

useradd --system --user-group --create-home myapp

That should do it.

Feedback

We’d love to hear your thoughts on this project. Feel free to drop us a note!

License

MIT


Part of Charm.

The Charm logo

Charm热爱开源 • Charm loves open source

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Error added in v0.4.0

func Error(s ssh.Session, v ...interface{})

Error prints the given error the the session's STDERR.

func Errorf added in v0.5.0

func Errorf(s ssh.Session, f string, v ...interface{})

Errorf formats according to the given format and prints to the session's STDERR.

func Errorln added in v0.5.0

func Errorln(s ssh.Session, v ...interface{})

Errorf formats according to the default format and prints to the session's STDERR.

func Fatal added in v0.4.0

func Fatal(s ssh.Session, v ...interface{})

Fatal prints to the given session's STDERR and exits 1.

func Fatalf added in v0.5.0

func Fatalf(s ssh.Session, f string, v ...interface{})

Fatalf formats according to the given format, prints to the session's STDERR followed by an exit 1.

Notice that this might cause formatting issues if you don't add a \r\n in the end of your string.

func Fatalln added in v0.5.0

func Fatalln(s ssh.Session, v ...interface{})

Fatalln formats according to the default format, prints to the session's STDERR, followed by a new line and an exit 1.

func NewServer

func NewServer(ops ...ssh.Option) (*ssh.Server, error)

NewServer is returns a default SSH server with the provided Middleware. A new SSH key pair of type ed25519 will be created if one does not exist. By default this server will accept all incoming connections, password and public key.

func Print added in v0.5.0

func Print(s ssh.Session, v ...interface{})

Print writes to the session's STDOUT followed.

func Printf added in v0.5.0

func Printf(s ssh.Session, f string, v ...interface{})

Printf formats according to the given format and writes to the session's STDOUT.

func Println added in v0.5.0

func Println(s ssh.Session, v ...interface{})

Println formats according to the default format and writes to the session's STDOUT.

func WithAddress

func WithAddress(addr string) ssh.Option

WithAddress returns an ssh.Option that sets the address to listen on.

func WithAuthorizedKeys added in v0.2.0

func WithAuthorizedKeys(path string) ssh.Option

WithAuthorizedKeys allows the use of an SSH authorized_keys file to allowlist users.

func WithBanner added in v1.3.0

func WithBanner(banner string) ssh.Option

WithBanner return an ssh.Option that sets the server banner.

func WithBannerHandler added in v1.3.0

func WithBannerHandler(h ssh.BannerHandler) ssh.Option

WithBannerHandler return an ssh.Option that sets the server banner handler, overriding WithBanner.

func WithHostKeyPEM

func WithHostKeyPEM(pem []byte) ssh.Option

WithHostKeyPEM returns an ssh.Option that sets the host key from a PEM block.

func WithHostKeyPath

func WithHostKeyPath(path string) ssh.Option

WithHostKeyFile returns an ssh.Option that sets the path to the private key.

func WithIdleTimeout added in v0.1.2

func WithIdleTimeout(d time.Duration) ssh.Option

WithIdleTimeout returns an ssh.Option that sets the connection's idle timeout.

func WithKeyboardInteractiveAuth added in v0.6.0

func WithKeyboardInteractiveAuth(h ssh.KeyboardInteractiveHandler) ssh.Option

WithKeyboardInteractiveAuth returns an ssh.Option that sets the keyboard interactive auth handler.

func WithMaxTimeout added in v0.1.2

func WithMaxTimeout(d time.Duration) ssh.Option

WithMaxTimeout returns an ssh.Option that sets the connection's absolute timeout.

func WithMiddleware

func WithMiddleware(mw ...Middleware) ssh.Option

WithMiddleware composes the provided Middleware and returns an ssh.Option. This is useful if you manually create an ssh.Server and want to set the Server.Handler.

Notice that middlewares are composed from first to last, which means the last one is executed first.

func WithPasswordAuth

func WithPasswordAuth(p ssh.PasswordHandler) ssh.Option

WithPasswordAuth returns an ssh.Option that sets the password auth handler.

func WithPublicKeyAuth

func WithPublicKeyAuth(h ssh.PublicKeyHandler) ssh.Option

WithPublicKeyAuth returns an ssh.Option that sets the public key auth handler.

func WithSubsystem added in v1.3.0

func WithSubsystem(key string, h ssh.SubsystemHandler) ssh.Option

WithSubsystem returns an ssh.Option that sets the subsystem handler for a given protocol.

func WithTrustedUserCAKeys added in v0.4.0

func WithTrustedUserCAKeys(path string) ssh.Option

WithTrustedUserCAKeys authorize certificates that are signed with the given Certificate Authority public key, and are valid. Analogous to the TrustedUserCAKeys OpenSSH option.

func WithVersion

func WithVersion(version string) ssh.Option

WithVersion returns an ssh.Option that sets the server version.

func WriteString added in v0.5.0

func WriteString(s ssh.Session, v string) (int, error)

WriteString writes the given string to the session's STDOUT.

Types

type Cmd added in v1.3.0

type Cmd struct {
	// contains filtered or unexported fields
}

Cmd wraps a *exec.Cmd and a ssh.Pty so a command can be properly run.

func Command added in v1.3.0

func Command(s ssh.Session, name string, args ...string) *Cmd

Command sets stdin, stdout, and stderr to the current session's PTY.

If the current session does not have a PTY, it sets them to the session itself.

This will use the session's context as the context for exec.Command.

func CommandContext added in v1.3.0

func CommandContext(ctx context.Context, s ssh.Session, name string, args ...string) *Cmd

CommandContext is like Command but includes a context.

If the current session does not have a PTY, it sets them to the session itself.

func (*Cmd) Environ added in v1.3.0

func (c *Cmd) Environ() []string

Environ returns the underlying exec.Cmd environment.

func (*Cmd) Run added in v1.3.0

func (c *Cmd) Run() error

Run runs the program and waits for it to finish.

func (*Cmd) SetDir added in v1.3.0

func (c *Cmd) SetDir(dir string)

SetDir set the underlying exec.Cmd dir.

func (*Cmd) SetEnv added in v1.3.0

func (c *Cmd) SetEnv(env []string)

SetDir set the underlying exec.Cmd env.

func (*Cmd) SetStderr added in v1.3.0

func (*Cmd) SetStderr(io.Writer)

SetStderr conforms with tea.ExecCommand.

func (*Cmd) SetStdin added in v1.3.0

func (*Cmd) SetStdin(io.Reader)

SetStdin conforms with tea.ExecCommand.

func (*Cmd) SetStdout added in v1.3.0

func (*Cmd) SetStdout(io.Writer)

SetStdout conforms with tea.ExecCommand.

type Middleware

type Middleware func(next ssh.Handler) ssh.Handler

Middleware is a function that takes an ssh.Handler and returns an ssh.Handler. Implementations should call the provided handler argument.

Directories

Path Synopsis
Package accesscontrol provides a middleware that allows you to restrict the commands the user can execute.
Package accesscontrol provides a middleware that allows you to restrict the commands the user can execute.
Package activeterm provides a middleware to block inactive PTYs.
Package activeterm provides a middleware to block inactive PTYs.
Package bubbletea provides middleware for serving bubbletea apps over SSH.
Package bubbletea provides middleware for serving bubbletea apps over SSH.
Package ratelimiter provides basic rate limiting functionality as a with middleware.
Package ratelimiter provides basic rate limiting functionality as a with middleware.
Package scp provides a SCP middleware for wish.
Package scp provides a SCP middleware for wish.
Package testsession provides utilities to test SSH sessions.
Package testsession provides utilities to test SSH sessions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL