use ssh agent to auth to remote

This commit is contained in:
William Banfield
2022-11-30 14:12:12 -05:00
parent fcb92561ce
commit 5e8028da5d
5 changed files with 29 additions and 21 deletions

View File

@@ -38,6 +38,7 @@ type InfrastructureData struct {
// one of the nodes in the testnet.
type InstanceData struct {
IPAddress net.IP `json:"ip_address"`
Port uint32 `json:"port"`
}
func NewDockerInfrastructureData(m Manifest) (InfrastructureData, error) {
@@ -49,6 +50,8 @@ func NewDockerInfrastructureData(m Manifest) (InfrastructureData, error) {
if err != nil {
return InfrastructureData{}, fmt.Errorf("invalid IP network address %q: %w", netAddress, err)
}
portGen := newPortGenerator(proxyPortFirst)
ipGen := newIPGenerator(ipNet)
ifd := InfrastructureData{
Provider: "docker",
@@ -58,6 +61,7 @@ func NewDockerInfrastructureData(m Manifest) (InfrastructureData, error) {
for name := range m.Nodes {
ifd.Instances[name] = InstanceData{
IPAddress: ipGen.Next(),
Port: portGen.Next(),
}
}
return ifd, nil

View File

@@ -5,6 +5,7 @@ import (
"path/filepath"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"golang.org/x/crypto/ssh/knownhosts"
)
@@ -22,24 +23,23 @@ func Exec(cfg *ssh.ClientConfig, addr, cmd string) error {
return nil
}
func NewClientConfig(keyFile string) (*ssh.ClientConfig, error) {
func NewClientConfig(ac agent.ExtendedAgent) (*ssh.ClientConfig, error) {
hkc, err := knownhosts.New(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
if err != nil {
return nil, err
}
key, err := os.ReadFile(keyFile)
signers, err := ac.Signers()
if err != nil {
return nil, err
}
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
return nil, err
am := make([]ssh.AuthMethod, 0, len(signers))
for _, signer := range signers {
am = append(am, ssh.PublicKeys(signer))
}
return &ssh.ClientConfig{
HostKeyCallback: hkc,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
User: "root",
HostKeyCallback: hkc,
Auth: am,
HostKeyAlgorithms: []string{ssh.KeyAlgoED25519},
}, nil
}

View File

@@ -1,6 +1,7 @@
package e2e
import (
"bytes"
"errors"
"fmt"
"io"
@@ -102,7 +103,6 @@ type Node struct {
func LoadTestnet(manifest Manifest, fname string, ifd InfrastructureData) (*Testnet, error) {
dir := strings.TrimSuffix(fname, filepath.Ext(fname))
keyGen := newKeyGenerator(randomSeed)
proxyPortGen := newPortGenerator(proxyPortFirst)
_, ipNet, err := net.ParseCIDR(ifd.Network)
if err != nil {
return nil, fmt.Errorf("invalid IP network address %q: %w", ifd.Network, err)
@@ -153,7 +153,7 @@ func LoadTestnet(manifest Manifest, fname string, ifd InfrastructureData) (*Test
PrivvalKey: keyGen.Generate(manifest.KeyType),
NodeKey: keyGen.Generate("ed25519"),
IP: ind.IPAddress,
ProxyPort: proxyPortGen.Next(),
ProxyPort: ind.Port,
Mode: ModeValidator,
SyncApp: nodeManifest.SyncApp,
Database: "goleveldb",
@@ -297,7 +297,7 @@ func (n Node) Validate(testnet Testnet) error {
return fmt.Errorf("local port %v must be >1024", n.ProxyPort)
}
for _, peer := range testnet.Nodes {
if peer.Name != n.Name && peer.ProxyPort == n.ProxyPort {
if peer.Name != n.Name && peer.ProxyPort == n.ProxyPort && bytes.Equal(peer.IP, n.IP) {
return fmt.Errorf("peer %q also has local port %v", peer.Name, n.ProxyPort)
}
}
@@ -437,7 +437,7 @@ func (n Node) AddressRPC() string {
// Client returns an RPC client for a node.
func (n Node) Client() (*rpchttp.HTTP, error) {
return rpchttp.New(fmt.Sprintf("http://127.0.0.1:%v", n.ProxyPort), "/websocket")
return rpchttp.New(fmt.Sprintf("http://%s:%v", n.IP, n.ProxyPort), "/websocket")
}
// Stateless returns true if the node is either a seed node or a light node

View File

@@ -5,11 +5,12 @@ import (
"errors"
"fmt"
"math/rand"
"net"
"os"
"path/filepath"
"strconv"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/agent"
"github.com/tendermint/tendermint/libs/log"
e2e "github.com/tendermint/tendermint/test/e2e/pkg"
@@ -91,10 +92,13 @@ func NewCLI() *CLI {
switch inft {
case "docker":
cli.infp = &docker.Provider{Testnet: testnet}
case "digitalocean":
// TMP: hardcoded key
cfg, err := e2essh.NewClientConfig(filepath.Join(os.Getenv("HOME"), ".ssh", "PVT_KEY"))
case "digital-ocean":
c, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")) // TODO(williambanfield): Ensure this is a consistent location for the authentication socket of the agent.
if err != nil {
return err
}
ac := agent.NewClient(c)
cfg, err := e2essh.NewClientConfig(ac)
if err != nil {
return err
}

View File

@@ -56,7 +56,7 @@ func Start(testnet *e2e.Testnet, p infra.Provider) error {
if _, err := waitForNode(node, 0, 15*time.Second); err != nil {
return err
}
logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://127.0.0.1:%v", node.Name, node.ProxyPort))
logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://%s:%v", node.Name, node.IP, node.ProxyPort))
}
networkHeight := testnet.InitialHeight
@@ -116,8 +116,8 @@ func Start(testnet *e2e.Testnet, p infra.Provider) error {
if err != nil {
return err
}
logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://127.0.0.1:%v at height %v",
node.Name, node.ProxyPort, status.SyncInfo.LatestBlockHeight))
logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://%s:%v at height %v",
node.Name, node.IP, node.ProxyPort, status.SyncInfo.LatestBlockHeight))
}
return nil