Skip to content

Commit

Permalink
fix(sshx): add SFTP connection
Browse files Browse the repository at this point in the history
  • Loading branch information
nicklasfrahm committed Apr 20, 2022
1 parent f3231ea commit 33cb7ad
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 22 deletions.
33 changes: 33 additions & 0 deletions examples/ssh-proxy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Version may either be a specific k3s version or a release channel
# as listed here: https://update.k3s.io/v1-release/channels
version: stable

# Cluster provides cluster-wide settings that should be applied
# to all nodes in the cluster. All options are equivalent to the
# commmand line options of the `k3s` command.
cluster:
tls-san:
- kubeapi.example.com
disable:
- traefik
write-kubeconfig-mode: "644"

# A list of all nodes in the cluster and their connection information.
nodes:
- role: server
ssh:
host: 127.0.0.1
fingerprint: SHA256:t/bwWCelgcAEYmQW9XbM4p31e1Qq70ZPWOKK+FRxBCc
user: nicklasfrahm
key-file: ~/.ssh/id_ed25519
config:
node-label:
- cpu=i3-7100

# An SSH proxy, also known as jumpbox or a bastion host
# can be used to access nodes in a private network.
ssh-proxy:
host: tph99.nicklasfrahm.xyz
fingerprint: SHA256:t/bwWCelgcAEYmQW9XbM4p31e1Qq70ZPWOKK+FRxBCc
user: nicklasfrahm
key-file: ~/.ssh/id_ed25519
15 changes: 4 additions & 11 deletions examples/standalone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,10 @@ cluster:
nodes:
- role: server
ssh:
host: 127.0.0.1
host: tph99.nicklasfrahm.xyz
fingerprint: SHA256:t/bwWCelgcAEYmQW9XbM4p31e1Qq70ZPWOKK+FRxBCc
user: nicklasfrahm
key-file: ~/.ssh/id_ed25519
node-label:
- cpu=i3-7100

# An SSH proxy, also known as jumpbox or a bastion host
# can be used to access nodes in a private network.
ssh-proxy:
host: tph99.nicklasfrahm.xyz
fingerprint: SHA256:t/bwWCelgcAEYmQW9XbM4p31e1Qq70ZPWOKK+FRxBCc
user: nicklasfrahm
key-file: ~/.ssh/id_ed25519
config:
node-label:
- cpu=i3-7100
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/nicklasfrahm/k3se
go 1.17

require (
github.com/pkg/sftp v1.13.4
github.com/rs/zerolog v1.26.1
github.com/spf13/cobra v1.4.0
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921
Expand All @@ -11,6 +12,7 @@ require (

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 // indirect
)
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.4 h1:Lb0RYJCmgUcBgZosfoi9Y9sbl6+LJgOIgk/2Y4YjMFg=
github.com/pkg/sftp v1.13.4/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc=
github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
Expand All @@ -12,9 +20,13 @@ github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM=
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
Expand All @@ -23,12 +35,15 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand All @@ -46,5 +61,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
16 changes: 11 additions & 5 deletions pkg/engine/node.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package engine

import "github.com/nicklasfrahm/k3se/pkg/sshx"
import (
"github.com/nicklasfrahm/k3se/pkg/sshx"
)

const (
// Program is used to configure the name of the configuration file.
Expand All @@ -9,11 +11,11 @@ const (

// Node describes the configuration of a node.
type Node struct {
Role Role `yaml:"role"`
SSH sshx.Config `yaml:"ssh"`
NodeLabel []string `yaml:"node-label"`
Role Role `yaml:"role"`
SSH sshx.Config `yaml:"ssh"`
Config K3sConfig `yaml:"config"`

*sshx.Client `yaml:"-"`
Client *sshx.Client `yaml:"-"`
}

// Connect establishes a connection to the node.
Expand All @@ -37,5 +39,9 @@ func (node *Node) Connect(options ...Option) error {

// Disconnect closes the connection to the node.
func (node *Node) Disconnect() error {
if node.Client != nil {
return node.Client.Close()
}

return nil
}
6 changes: 6 additions & 0 deletions pkg/ops/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ func Up(options ...Option) error {
// TODO: Copy kubeconfig to /etc/rancher/k3s/k3s.yaml.

// TODO: Store state on server nodes to allow for configuration diffing later on.
// TODO: Fetch state from Git history.

// Disconnect from all nodes.
for _, node := range nodes {
node.Disconnect()
}

return nil
}
37 changes: 31 additions & 6 deletions pkg/sshx/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net"
"os/user"

"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
)

Expand All @@ -25,11 +26,13 @@ type Config struct {
// Client is an augmented SSH client.
type Client struct {
*Options
*ssh.Client

SSH *ssh.Client
SFTP *sftp.Client
}

// NewClient creates a new SSH client based on an SSH configuration
// and connects to it.
// NewClient creates a new SSH client and a new SFTP client based
// on an SSH configuration and connects to it.
func NewClient(config *Config, options ...Option) (*Client, error) {
opts, err := GetDefaultOptions().Apply(options...)
if err != nil {
Expand Down Expand Up @@ -57,7 +60,7 @@ func NewClient(config *Config, options ...Option) (*Client, error) {

if client.Proxy != nil {
// Create a TCP connection from the proxy host to the target.
netConn, err := client.Proxy.Client.Dial("tcp", address)
netConn, err := client.Proxy.SSH.Dial("tcp", address)
if err != nil {
return nil, err
}
Expand All @@ -67,9 +70,12 @@ func NewClient(config *Config, options ...Option) (*Client, error) {
return nil, err
}

client.Client = ssh.NewClient(targetConn, channel, req)
client.SSH = ssh.NewClient(targetConn, channel, req)
} else {
if client.Client, err = ssh.Dial("tcp", address, normalizedConfig); err != nil {
if client.SSH, err = ssh.Dial("tcp", address, normalizedConfig); err != nil {
return nil, err
}
if client.SFTP, err = sftp.NewClient(client.SSH); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -152,3 +158,22 @@ func (client *Client) normalizeConfig(config *Config) (*ssh.ClientConfig, error)
Timeout: client.Timeout,
}, nil
}

// Close closes the SFTP connection first as it
// piggy-backs on the SSH connection. After that
// the SSH connection of the client is closed.
func (client *Client) Close() error {
if client.SFTP != nil {
if err := client.SFTP.Close(); err != nil {
return err
}
}

if client.SSH != nil {
if err := client.SSH.Close(); err != nil {
return err
}
}

return nil
}

0 comments on commit 33cb7ad

Please sign in to comment.