The web UI is not using the CLI client

TODO:
- Configure the CLI client to NOT use a keystore
- Configure the CLI client to NOT use ssh-agent
- Fix tests
- Comments
This commit is contained in:
Ev Kontsevoy 2017-02-02 22:54:48 -08:00
parent 2e59ee51cc
commit 2150cb31de
3 changed files with 84 additions and 7 deletions

View file

@ -721,11 +721,13 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error {
utils.Consolef(cfg.Console, "[PROXY] Web proxy service is starting on %v", cfg.Proxy.WebAddr.Addr)
webHandler, err := web.NewHandler(
web.Config{
Proxy: tsrv,
AuthServers: cfg.AuthServers[0],
DomainName: cfg.Hostname,
ProxyClient: conn.Client,
DisableUI: cfg.Proxy.DisableWebUI,
Proxy: tsrv,
AuthServers: cfg.AuthServers[0],
DomainName: cfg.Hostname,
ProxyClient: conn.Client,
DisableUI: cfg.Proxy.DisableWebUI,
ProxySSHAddr: cfg.Proxy.SSHAddr,
ProxyWebAddr: cfg.Proxy.WebAddr,
})
if err != nil {
utils.Consolef(cfg.Console, "[PROXY] starting the web server: %v", err)

View file

@ -26,6 +26,7 @@ import (
"html/template"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"strconv"
@ -35,6 +36,7 @@ import (
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/httplib"
"github.com/gravitational/teleport/lib/reversetunnel"
@ -90,6 +92,9 @@ type Config struct {
ProxyClient auth.ClientI
// DisableUI allows to turn off serving web based UI
DisableUI bool
// TODO
ProxySSHAddr utils.NetAddr
ProxyWebAddr utils.NetAddr
}
type RewritingHandler struct {
@ -950,6 +955,8 @@ func (m *Handler) siteNodeConnect(
req.Namespace, req.ServerID, req.Login)
req.Namespace = p.ByName("namespace")
req.ProxyHostPort = m.ProxyHostPort()
term, err := newTerminal(*req, ctx, site)
if err != nil {
return nil, trace.Wrap(err)
@ -1442,6 +1449,20 @@ func (h *Handler) AuthenticateRequest(w http.ResponseWriter, r *http.Request, ch
return ctx, nil
}
// ProxyHostPort returns the address of the proxy server using --proxy
// notation, i.e. "localhost:8030,8023"
func (h *Handler) ProxyHostPort() string {
// addr equals to "localhost:8030" at this point
addr := h.cfg.ProxyWebAddr.String()
// add the SSH port number and return
_, sshPort, err := net.SplitHostPort(h.cfg.ProxySSHAddr.String())
if err != nil {
log.Error(err)
sshPort = strconv.Itoa(defaults.SSHProxyListenPort)
}
return fmt.Sprintf("%s,%s", addr, sshPort)
}
func message(msg string) interface{} {
return map[string]interface{}{"message": msg}
}

View file

@ -17,8 +17,13 @@ limitations under the License.
package web
import (
"context"
"fmt"
"io"
"net"
"net/http"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/reversetunnel"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/session"
@ -44,6 +49,8 @@ type terminalRequest struct {
SessionID session.ID `json:"sid"`
// Namespace is node namespace
Namespace string `json:"namespace"`
// Proxy server address
ProxyHostPort string `json:"-"`
}
// newTerminal creates a web-based terminal based on WebSockets and returns a new
@ -177,10 +184,15 @@ func (t *terminalHandler) connectUpstream() (*sshutils.Upstream, error) {
// the "loop" piping the input/output of the SSH session into the
// js-based terminal.
func (t *terminalHandler) Run(w http.ResponseWriter, r *http.Request) {
errToTerm := func(err error, w io.Writer) {
fmt.Fprintf(w, "%s\n\r", err.Error())
log.Error(err)
}
webSocketLoop := func(ws *websocket.Conn) {
up, err := t.connectUpstream()
if err != nil {
log.Error(err)
errToTerm(err, ws)
return
}
t.up = up
@ -193,10 +205,52 @@ func (t *terminalHandler) Run(w http.ResponseWriter, r *http.Request) {
W: uint32(t.params.Term.W),
H: uint32(t.params.Term.H),
})
log.Infof("pipe shell finished with: %v", err)
}
// second version
v2 := func(ws *websocket.Conn) {
agent, err := t.ctx.GetAgent()
if err != nil {
errToTerm(err, ws)
return
}
defer agent.Close()
signers, err := agent.Signers()
if err != nil {
errToTerm(err, ws)
return
}
host, _, err := net.SplitHostPort(t.server.GetAddr())
if err != nil {
errToTerm(err, ws)
return
}
output := utils.NewWebSockWrapper(ws, utils.WebSocketTextMode)
tc, err := client.NewClient(&client.Config{
AuthMethods: []ssh.AuthMethod{ssh.PublicKeys(signers...)},
HostLogin: t.params.Login,
Namespace: t.params.Namespace,
Stdout: output,
Stderr: output,
Stdin: ws,
ProxyHostPort: t.params.ProxyHostPort,
Host: host,
})
if err != nil {
errToTerm(err, ws)
return
}
if err = tc.SSH(context.TODO(), nil, false); err != nil {
errToTerm(err, ws)
return
}
}
if true {
webSocketLoop = v2
}
// TODO(klizhentas)
// we instantiate a server explicitly here instead of using
// websocket.HandlerFunc to set empty origin checker