Skip to content

Commit

Permalink
add config ssh jump server
Browse files Browse the repository at this point in the history
  • Loading branch information
SimoneDutto committed Jan 14, 2025
1 parent f69e130 commit 96052d7
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 26 deletions.
15 changes: 14 additions & 1 deletion cmd/jimmsrv/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Canonical.
// Copyright 2025 Canonical.

package main

Expand Down Expand Up @@ -209,5 +209,18 @@ func start(ctx context.Context, s *service.Service) error {
})
s.Go(httpsrv.ListenAndServe)
zapctx.Info(ctx, "Successfully started JIMM server")

// // this is to show the integration, we will uncommented it once the ssh implementation is ready.
// sshJumpServer, err := ssh.NewJumpSSHServer(ctx, ssh.SSHServerConfig{
// Port: os.Getenv("JIMM_SSH_PORT"),
// HostKey: []byte(os.Getenv("JIMM_SSH_HOST_KEY")),
// MaxConcurrentConnections: os.Getenv("JIMM_SSH_MAX_CONCURRENT_CONNECTIONS"),
// }, jimmsvc.JIMM().SSHManager())
// if err != nil {
// return err
// }
// s.Go(sshJumpServer.ListenAndServe)
// zapctx.Info(ctx, "Successfully started JIMM ssh jump server")

return nil
}
24 changes: 7 additions & 17 deletions internal/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,16 @@ type Resolver interface {
AddrFromModelUUID(ctx context.Context, user openfga.User, modelUUID string) (string, error)
}

// fowardMessage is the struct holding the information about the jump message received by the ssh client.
type forwardMessage struct {
DestAddr string
DestPort uint32
SrcAddr string
SrcPort uint32
}

// Server is the custom struct to embed the gliderlabs.ssh server and a resolver.
type Server struct {
*ssh.Server

resolver Resolver
}

// NewJumpSSHServer creates the jump server struct.
func NewJumpSSHServer(ctx context.Context, port int, resolver Resolver) (Server, error) {
func NewJumpSSHServer(ctx context.Context, config SSHServerConfig, resolver Resolver) (Server, error) {
zapctx.Info(ctx, "NewSSHServer")

if resolver == nil {
return Server{}, fmt.Errorf("Cannot create JumpSSHServer with a nil resolver.")
}
server := Server{
Server: &ssh.Server{
Addr: fmt.Sprintf(":%d", port),
Addr: fmt.Sprintf(":%s", config.Port),
ChannelHandlers: map[string]ssh.ChannelHandler{
"direct-tcpip": directTCPIPHandler(resolver),
},
Expand All @@ -59,6 +44,11 @@ func NewJumpSSHServer(ctx context.Context, port int, resolver Resolver) (Server,
},
resolver: resolver,
}
s, err := gossh.ParsePrivateKey([]byte(config.HostKey))
if err != nil {
return Server{}, fmt.Errorf("Cannot parse hostkey.")
}
server.AddHostKey(s)

return server, nil
}
Expand Down
30 changes: 22 additions & 8 deletions internal/ssh/ssh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type sshSuite struct {
jumpSSHServer ssh.Server
jumpServerPort int
privateKey gossh.Signer
hostKey gossh.Signer
testInDestinationServerF func(fm ssh.ForwardMessage)
received chan bool
}
Expand Down Expand Up @@ -71,13 +72,29 @@ func (s *sshSuite) Init(c *qt.C) {
port, err = jimmtest.GetFreePort()
c.Assert(err, qt.IsNil)
s.jumpServerPort = port
s.jumpSSHServer, err = ssh.NewJumpSSHServer(context.Background(), port, resolver{})
k, err := rsa.GenerateKey(rand.Reader, 2048)
c.Assert(err, qt.IsNil)
hostKey := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(k),
},
)
s.hostKey, err = gossh.ParsePrivateKey(hostKey)
c.Assert(err, qt.IsNil)

s.jumpSSHServer, err = ssh.NewJumpSSHServer(context.Background(),
ssh.SSHServerConfig{
Port: fmt.Sprint(port),
HostKey: hostKey},
resolver{},
)
c.Assert(err, qt.IsNil)
go func() {
_ = s.jumpSSHServer.ListenAndServe()
}()

k, err := rsa.GenerateKey(rand.Reader, 2048)
k, err = rsa.GenerateKey(rand.Reader, 2048)
c.Assert(err, qt.IsNil)
keyPEM := pem.EncodeToMemory(
&pem.Block{
Expand All @@ -98,8 +115,7 @@ func (s *sshSuite) Init(c *qt.C) {

func (s *sshSuite) TestSSHJump(c *qt.C) {
client, err := gossh.Dial("tcp", fmt.Sprintf(":%d", s.jumpServerPort), &gossh.ClientConfig{
//nolint:gosec // this will be removed once we handle hostkeys
HostKeyCallback: gossh.InsecureIgnoreHostKey(),
HostKeyCallback: gossh.FixedHostKey(s.hostKey.PublicKey()),
Auth: []gossh.AuthMethod{
gossh.PublicKeys(s.privateKey),
},
Expand Down Expand Up @@ -130,8 +146,7 @@ func (s *sshSuite) TestSSHJump(c *qt.C) {

func (s *sshSuite) TestSSHJumpDialFail(c *qt.C) {
_, err := gossh.Dial("tcp", fmt.Sprintf(":%d", 1), &gossh.ClientConfig{
//nolint:gosec // this will be removed once we handle hostkeys
HostKeyCallback: gossh.InsecureIgnoreHostKey(),
HostKeyCallback: gossh.FixedHostKey(s.hostKey.PublicKey()),
Auth: []gossh.AuthMethod{
gossh.PublicKeys(s.privateKey),
},
Expand All @@ -142,8 +157,7 @@ func (s *sshSuite) TestSSHJumpDialFail(c *qt.C) {
func (s *sshSuite) TestSSHFinalDestinationDialFail(c *qt.C) {

client, err := gossh.Dial("tcp", fmt.Sprintf(":%d", s.jumpServerPort), &gossh.ClientConfig{
//nolint:gosec // this will be removed once we handle hostkeys
HostKeyCallback: gossh.InsecureIgnoreHostKey(),
HostKeyCallback: gossh.FixedHostKey(s.hostKey.PublicKey()),
Auth: []gossh.AuthMethod{
gossh.PublicKeys(s.privateKey),
},
Expand Down
25 changes: 25 additions & 0 deletions internal/ssh/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2025 Canonical.
package ssh

import "github.com/gliderlabs/ssh"

// fowardMessage is the struct holding the information about the jump message received by the ssh client.
type forwardMessage struct {
DestAddr string
DestPort uint32
SrcAddr string
SrcPort uint32
}

// Server is the custom struct to embed the gliderlabs.ssh server and a resolver.
type Server struct {
*ssh.Server

resolver Resolver
}

type SSHServerConfig struct {
Port string
HostKey []byte
MaxConcurrentConnections string
}

0 comments on commit 96052d7

Please sign in to comment.