mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 09:44:51 +00:00
Client application draft
This commit is contained in:
parent
a3998b1f20
commit
a952217066
32
tool/tsh/main.go
Normal file
32
tool/tsh/main.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2015 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/log"
|
||||
"github.com/gravitational/teleport/tool/tsh/tsh"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Initialize("console", "INFO")
|
||||
|
||||
err := tsh.Run(os.Args)
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
}
|
||||
}
|
92
tool/tsh/tsh/cmd.go
Normal file
92
tool/tsh/tsh/cmd.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
Copyright 2015 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package tsh
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
//"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/buger/goterm"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/trace"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent"
|
||||
//"github.com/gravitational/teleport/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func Run(args []string) error {
|
||||
app := kingpin.New("tsh", "teleport SSH client")
|
||||
|
||||
user := app.Flag("user", "SSH user").Required().String()
|
||||
sshAgentAddress := app.Flag("ssh-agent", "SSH agent address").OverrideDefaultFromEnvar("SSH_AUTH_SOCK").String()
|
||||
sshAgentNetwork := app.Flag("ssh-agent-network", "SSH agent address network type('tcp','unix' etc.)").Default("unix").String()
|
||||
|
||||
connect := app.Command("connect", "Helper operations with SSH keypairs")
|
||||
connectAddress := connect.Arg("address", "Target server address").Required().String()
|
||||
connectProxy := connect.Flag("proxy", "Optional proxy address").String()
|
||||
connectCommand := connect.Flag("command", "Run proveded command instead of shell").String()
|
||||
|
||||
upload := app.Command("upload", "Helper operations with SSH keypairs")
|
||||
uploadAddress := upload.Arg("address", "Target server address").Required().String()
|
||||
uploadProxy := upload.Flag("proxy", "Optional proxy address").String()
|
||||
uploadLocalSource := upload.Arg("source", "Local source path").Required().String()
|
||||
uploadRemoteDest := upload.Arg("dest", "Remote destination path").Required().String()
|
||||
|
||||
download := app.Command("download", "Helper operations with SSH keypairs")
|
||||
downloadAddress := download.Arg("address", "Target server address").Required().String()
|
||||
downloadProxy := download.Flag("proxy", "Optional proxy address").String()
|
||||
downloadLocalDest := download.Arg("dest", "Local destination path").Required().String()
|
||||
downloadRemoteSource := download.Arg("source", "Remote source path").Required().String()
|
||||
downloadRecursively := download.Flag("r", "Source path is directory").Bool()
|
||||
|
||||
getServers := app.Command("get-servers", "Returns list of servers")
|
||||
getServersProxy := getServers.Flag("proxy", "Target proxy address").String()
|
||||
getServersLabelName := getServers.Flag("label", "Label name").String()
|
||||
getServersLabelValue := getServers.Flag("value", "Label value regexp").String()
|
||||
|
||||
selectedCommand := kingpin.MustParse(app.Parse(args[1:]))
|
||||
|
||||
agent, err := connectToSSHAgent(*sshAgentNetwork, *sshAgentAddress)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
err = trace.Errorf("No command")
|
||||
|
||||
switch selectedCommand {
|
||||
case connect.FullCommand():
|
||||
err = Connect(*user, *connectAddress, *connectProxy, *connectCommand, agent)
|
||||
case upload.FullCommand():
|
||||
err = Upload(*user, *uploadAddress, *uploadProxy, *uploadLocalSource,
|
||||
*uploadRemoteDest, agent)
|
||||
case download.FullCommand():
|
||||
err = Download(*user, *downloadAddress, *downloadProxy,
|
||||
*downloadLocalDest, *downloadRemoteSource, *downloadRecursively, agent)
|
||||
case getServers.FullCommand():
|
||||
err = GetServers(*user, *getServersProxy, *getServersLabelName,
|
||||
*getServersLabelValue, agent)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func connectToSSHAgent(network, address string) (agent.Agent, error) {
|
||||
conn, err := net.Dial(network, address)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return agent.NewClient(conn), nil
|
||||
|
||||
}
|
187
tool/tsh/tsh/ths.go
Normal file
187
tool/tsh/tsh/ths.go
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
Copyright 2015 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package tsh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/gravitational/teleport/lib/client"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/trace"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/golang.org/x/crypto/ssh"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
func Connect(user, address, proxyAddress, command string, agent agent.Agent) error {
|
||||
var c *client.NodeClient
|
||||
if len(proxyAddress) > 0 {
|
||||
proxyClient, err := client.ConnectToProxy(proxyAddress, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
defer proxyClient.Close()
|
||||
c, err = proxyClient.ConnectToNode(address, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
c, err = client.ConnectToNode(address, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
if len(command) > 0 {
|
||||
out := bytes.Buffer{}
|
||||
err := c.Run(command, &out)
|
||||
if err != nil {
|
||||
return trace.Wrap(err, out.String())
|
||||
}
|
||||
fmt.Println(out.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
shell, err := c.Shell()
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
buf := make([]byte, 1000)
|
||||
for {
|
||||
n, err := shell.Read(buf)
|
||||
if err != nil && err != io.EOF {
|
||||
fmt.Println(trace.Wrap(err))
|
||||
return
|
||||
}
|
||||
if n > 0 {
|
||||
//fmt.Printf(string(buf[:n]))
|
||||
_, err = os.Stdout.Write(buf[:n])
|
||||
if err != nil {
|
||||
fmt.Println(trace.Wrap(err))
|
||||
return
|
||||
}
|
||||
/*err = os.Stdout.Sync()
|
||||
if err != nil {
|
||||
fmt.Println(trace.Wrap(err))
|
||||
return
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
_, err := io.Copy(shell, os.Stdin)
|
||||
if err != nil { // && err != io.EOF {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Upload(user, address, proxyAddress, localSourcePath, remoteDestPath string, agent agent.Agent) error {
|
||||
var c *client.NodeClient
|
||||
if len(proxyAddress) > 0 {
|
||||
proxyClient, err := client.ConnectToProxy(proxyAddress, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
defer proxyClient.Close()
|
||||
c, err = proxyClient.ConnectToNode(address, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
c, err = client.ConnectToNode(address, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
err := c.Upload(localSourcePath, remoteDestPath)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Download(user, address, proxyAddress, localDestPath, remoteSourcePath string, isDir bool, agent agent.Agent) error {
|
||||
var c *client.NodeClient
|
||||
if len(proxyAddress) > 0 {
|
||||
proxyClient, err := client.ConnectToProxy(proxyAddress, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
defer proxyClient.Close()
|
||||
c, err = proxyClient.ConnectToNode(address, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
c, err = client.ConnectToNode(address, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
err := c.Download(localDestPath, remoteSourcePath, isDir)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetServers(user, proxyAddress, labelName, labelValueRegexp string, agent agent.Agent) error {
|
||||
proxyClient, err := client.ConnectToProxy(proxyAddress, ssh.PublicKeysCallback(agent.Signers), user)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
defer proxyClient.Close()
|
||||
|
||||
var servers []services.Server
|
||||
|
||||
if (len(labelName) > 0) && (len(labelValueRegexp) > 0) {
|
||||
servers, err = proxyClient.FindServers(labelName, labelValueRegexp)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
} else {
|
||||
servers, err = proxyClient.GetServers()
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
fmt.Println(servers)
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue