Split public_addr into web_proxy_addr and ssh_proxy_addr.

This commit is contained in:
Russell Jones 2018-08-29 22:54:35 +00:00 committed by Russell Jones
parent 1439408b34
commit 97074076cb
14 changed files with 246 additions and 157 deletions

View file

@ -847,31 +847,23 @@ func (i *TeleInstance) NewUnauthenticatedClient(cfg ClientConfig) (tc *client.Te
return nil, err
}
// break down proxy address into host, ssh_port and web_port:
proxyConf := &i.Config.Proxy
proxyHost, sp, err := net.SplitHostPort(proxyConf.SSHAddr.Addr)
proxyHost, _, err := net.SplitHostPort(proxyConf.SSHAddr.Addr)
if err != nil {
return nil, trace.Wrap(err)
}
// use alternative proxy if necessary
var proxySSHPort, proxyWebPort int
var webProxyAddr string
var sshProxyAddr string
if cfg.Proxy == nil {
proxySSHPort, err = strconv.Atoi(sp)
if err != nil {
return nil, trace.Wrap(err)
}
_, sp, err = net.SplitHostPort(proxyConf.WebAddr.Addr)
if err != nil {
return nil, trace.Wrap(err)
}
proxyWebPort, err = strconv.Atoi(sp)
if err != nil {
return nil, trace.Wrap(err)
}
webProxyAddr = proxyConf.WebAddr.Addr
sshProxyAddr = proxyConf.SSHAddr.Addr
} else {
proxySSHPort, proxyWebPort = cfg.Proxy.SSHPort, cfg.Proxy.WebPort
webProxyAddr = net.JoinHostPort(proxyHost, strconv.Itoa(cfg.Proxy.WebPort))
sshProxyAddr = net.JoinHostPort(proxyHost, strconv.Itoa(cfg.Proxy.SSHPort))
}
cconf := &client.Config{
Username: cfg.Login,
Host: cfg.Host,
@ -881,8 +873,9 @@ func (i *TeleInstance) NewUnauthenticatedClient(cfg ClientConfig) (tc *client.Te
KeysDir: keyDir,
SiteName: cfg.Cluster,
ForwardAgent: cfg.ForwardAgent,
WebProxyAddr: webProxyAddr,
SSHProxyAddr: sshProxyAddr,
}
cconf.SetProxy(proxyHost, proxyWebPort, proxySSHPort)
return client.NewClient(cconf)
}

View file

@ -116,22 +116,13 @@ type Config struct {
// port setting via -p flag, otherwise '0' is passed which means "use server default"
HostPort int
// ProxySSHHost is host or IP of the SSH proxy. It is derived from either
// the --proxy flag or from the value the proxy advertises in public_addr.
ProxySSHHost string
// WebProxyAddr is the host:port the web proxy can be accessed at.
WebProxyAddr string
// ProxySSHPort is the port to use to connect to the SSH proxy. It is
// derived from either the --proxy flag or from the value the proxy
// advertises in listen_addr.
ProxySSHPort int
// SSHProxyAddr is the host:port the SSH proxy can be accessed at.
SSHProxyAddr string
// ProxyWebHost is host or IP of the web proxy.
ProxyWebHost string
// ProxyWebPort is the port to use to connect to the web proxy.
ProxyWebPort int
// KubeProxyAddr is a kubernetes proxy address in host:port format
// KubeProxyAddr is the host:port the Kubernetes proxy can be accessed at.
KubeProxyAddr string
// KeyTTL is a time to live for the temporary SSH keypair to remain valid:
@ -278,7 +269,7 @@ func readProfile(profileDir string, profileName string) (*ProfileStatus, error)
if err != nil {
return nil, trace.Wrap(err)
}
keys, err := store.GetKey(profile.ProxyWebHost, profile.Username)
keys, err := store.GetKey(profile.Name(), profile.Username)
if err != nil {
return nil, trace.Wrap(err)
}
@ -320,7 +311,7 @@ func readProfile(profileDir string, profileName string) (*ProfileStatus, error)
return &ProfileStatus{
ProxyURL: url.URL{
Scheme: "https",
Host: net.JoinHostPort(profile.ProxyWebHost, strconv.Itoa(profile.ProxyWebPort)),
Host: profile.WebProxyAddr,
},
Username: profile.Username,
Logins: cert.ValidPrincipals,
@ -451,26 +442,33 @@ func (c *Config) LoadProfile(profileDir string, proxyName string) error {
return trace.Wrap(err)
}
// DELETE IN: 3.1.0
// The "proxy_host" field (and associated ports) have been deprecated and
// replaced with "proxy_web_addr" and "proxy_ssh_addr".
if cp.ProxyHost != "" {
if cp.ProxyWebPort == 0 {
cp.ProxyWebPort = defaults.HTTPListenPort
}
if cp.ProxySSHPort == 0 {
cp.ProxySSHPort = defaults.SSHProxyListenPort
}
c.WebProxyAddr = net.JoinHostPort(cp.ProxyHost, strconv.Itoa(cp.ProxyWebPort))
c.SSHProxyAddr = net.JoinHostPort(cp.ProxyHost, strconv.Itoa(cp.ProxySSHPort))
}
c.Username = cp.Username
c.SiteName = cp.SiteName
c.KubeProxyAddr = cp.KubeProxyAddr
// Read in the value for the web proxy (obtained by parsing --proxy). If
// the value of the SSH proxy is not available, fallback to the to the
// value of the web proxy.
c.ProxyWebHost = cp.ProxyWebHost
if cp.ProxySSHHost != "" {
c.ProxySSHHost = cp.ProxySSHHost
} else {
c.ProxySSHHost = cp.ProxyWebHost
// UPDATE IN: 3.1.0
// Remove the above DELETE IN block and below if statements and always set
// WebProxyAddr and SSHProxyAddr. This needs to be done right now to support
// backward compatibility with Teleport 2.0.
if cp.WebProxyAddr != "" {
c.WebProxyAddr = cp.WebProxyAddr
}
// Same logic as above but apply it to the web and SSH port values as well.
c.ProxyWebPort = cp.ProxyWebPort
if cp.ProxySSHPort != 0 {
c.ProxySSHPort = cp.ProxySSHPort
} else {
c.ProxySSHPort = cp.ProxyWebPort
if cp.SSHProxyAddr != "" {
c.SSHProxyAddr = cp.SSHProxyAddr
}
c.LocalForwardPorts, err = ParsePortForwardSpec(cp.ForwardedPorts)
@ -484,18 +482,19 @@ func (c *Config) LoadProfile(profileDir string, proxyName string) error {
// SaveProfile updates the given profiles directory with the current configuration
// If profileDir is an empty string, the default ~/.tsh is used
func (c *Config) SaveProfile(profileDir string, profileOptions ...ProfileOptions) error {
if c.ProxyWebHost == "" {
if c.WebProxyAddr == "" {
return nil
}
// The profile is saved to a directory with the name of the proxy web endpoint.
webProxyHost, _ := c.WebProxyHostPort()
profileDir = FullProfilePath(profileDir)
profilePath := path.Join(profileDir, c.ProxyWebHost) + ".yaml"
profilePath := path.Join(profileDir, webProxyHost) + ".yaml"
var cp ClientProfile
cp.Username = c.Username
cp.ProxyWebHost = c.ProxyWebHost
cp.ProxySSHHost = c.ProxySSHHost
cp.ProxyWebPort = c.ProxyWebPort
cp.ProxySSHPort = c.ProxySSHPort
cp.WebProxyAddr = c.WebProxyAddr
cp.SSHProxyAddr = c.SSHProxyAddr
cp.KubeProxyAddr = c.KubeProxyAddr
cp.ForwardedPorts = c.LocalForwardPorts.ToStringSpec()
cp.SiteName = c.SiteName
@ -519,7 +518,7 @@ func (c *Config) SaveProfile(profileDir string, profileOptions ...ProfileOptions
// ParseProxyHost parses the proxyHost string and updates the config.
//
// Format of proxyHost string:
// proxy_host:<https_proxy_port>,<ssh_proxy_port>
// proxy_web_addr:<proxy_web_port>,<proxy_ssh_portt>
func (c *Config) ParseProxyHost(proxyHost string) error {
host, port, err := net.SplitHostPort(proxyHost)
if err != nil {
@ -527,36 +526,34 @@ func (c *Config) ParseProxyHost(proxyHost string) error {
port = ""
}
// The command line flag specifies both the Web and SSH proxy host.
c.ProxyWebHost = host
c.ProxySSHHost = host
// Split on comma.
parts := strings.Split(port, ",")
switch {
// Default ports for both the SSH and Web proxy.
case len(parts) == 0:
c.ProxyWebPort = defaults.HTTPListenPort
c.ProxySSHPort = defaults.SSHProxyListenPort
c.WebProxyAddr = net.JoinHostPort(host, strconv.Itoa(defaults.HTTPListenPort))
c.SSHProxyAddr = net.JoinHostPort(host, strconv.Itoa(defaults.SSHProxyListenPort))
// User defined HTTP proxy port, default SSH proxy port.
case len(parts) == 1:
webPort, err := strconv.Atoi(parts[0])
if err != nil {
webPort = defaults.HTTPListenPort
webPort := parts[0]
if webPort == "" {
webPort = strconv.Itoa(defaults.HTTPListenPort)
}
c.ProxyWebPort = webPort
c.ProxySSHPort = defaults.SSHProxyListenPort
c.WebProxyAddr = net.JoinHostPort(host, webPort)
c.SSHProxyAddr = net.JoinHostPort(host, strconv.Itoa(defaults.SSHProxyListenPort))
// User defined HTTP and SSH proxy ports.
case len(parts) == 2:
webPort, err := strconv.Atoi(parts[0])
if err != nil {
webPort = defaults.HTTPListenPort
webPort := parts[0]
if webPort == "" {
webPort = strconv.Itoa(defaults.HTTPListenPort)
}
sshPort, err := strconv.Atoi(parts[1])
if err != nil {
sshPort = defaults.SSHProxyListenPort
sshPort := parts[1]
if sshPort == "" {
sshPort = strconv.Itoa(defaults.SSHProxyListenPort)
}
c.ProxyWebPort = webPort
c.ProxySSHPort = sshPort
c.WebProxyAddr = net.JoinHostPort(host, webPort)
c.SSHProxyAddr = net.JoinHostPort(host, sshPort)
default:
return trace.BadParameter("unable to parse port: %v", port)
}
@ -564,7 +561,7 @@ func (c *Config) ParseProxyHost(proxyHost string) error {
return nil
}
// KubeProxyHostPort returns kubernetes proxy host and port
// KubeProxyHostPort returns the host and port of the Kubernetes proxy.
func (c *Config) KubeProxyHostPort() (string, int) {
if c.KubeProxyAddr != "" {
addr, err := utils.ParseAddr(c.KubeProxyAddr)
@ -572,7 +569,35 @@ func (c *Config) KubeProxyHostPort() (string, int) {
return addr.Host(), addr.Port(defaults.KubeProxyListenPort)
}
}
return c.ProxyWebHost, defaults.KubeProxyListenPort
webProxyHost, _ := c.WebProxyHostPort()
return webProxyHost, defaults.KubeProxyListenPort
}
// WebProxyHostPort returns the host and port of the web proxy.
func (c *Config) WebProxyHostPort() (string, int) {
if c.WebProxyAddr != "" {
addr, err := utils.ParseAddr(c.WebProxyAddr)
if err == nil {
return addr.Host(), addr.Port(defaults.HTTPListenPort)
}
}
webProxyHost, _ := c.WebProxyHostPort()
return webProxyHost, defaults.HTTPListenPort
}
// SSHProxyHostPort returns the host and port of the SSH proxy.
func (c *Config) SSHProxyHostPort() (string, int) {
if c.SSHProxyAddr != "" {
addr, err := utils.ParseAddr(c.SSHProxyAddr)
if err == nil {
return addr.Host(), addr.Port(defaults.SSHProxyListenPort)
}
}
webProxyHost, _ := c.WebProxyHostPort()
return webProxyHost, defaults.SSHProxyListenPort
}
// ProxyHost returns the hostname of the proxy server (without any port numbers)
@ -584,17 +609,9 @@ func ProxyHost(proxyHost string) string {
return host
}
func (c *Config) ProxyWebHostPort() string {
return net.JoinHostPort(c.ProxyWebHost, strconv.Itoa(c.ProxyWebPort))
}
func (c *Config) ProxySSHHostPort() string {
return net.JoinHostPort(c.ProxySSHHost, strconv.Itoa(c.ProxySSHPort))
}
// ProxySpecified returns true if proxy has been specified
// ProxySpecified returns true if proxy has been specified.
func (c *Config) ProxySpecified() bool {
return len(c.ProxyWebHost) > 0
return c.WebProxyAddr != ""
}
// TeleportClient is a wrapper around SSH client with teleport specific
@ -629,7 +646,7 @@ func NewClient(c *Config) (tc *TeleportClient, err error) {
}
log.Infof("No teleport login given. defaulting to %s", c.Username)
}
if c.ProxyWebHost == "" {
if c.WebProxyAddr == "" {
return nil, trace.BadParameter("No proxy address specified, missed --proxy flag?")
}
if c.HostLogin == "" {
@ -678,7 +695,8 @@ func NewClient(c *Config) (tc *TeleportClient, err error) {
}
} else {
// initialize the local agent (auth agent which uses local SSH keys signed by the CA):
tc.localAgent, err = NewLocalAgent(c.KeysDir, tc.ProxyWebHost, c.Username)
webProxyHost, _ := tc.WebProxyHostPort()
tc.localAgent, err = NewLocalAgent(c.KeysDir, webProxyHost, c.Username)
if err != nil {
return nil, trace.Wrap(err)
}
@ -1326,7 +1344,7 @@ func (tc *TeleportClient) connectToProxy(ctx context.Context) (*ProxyClient, err
var err error
proxyPrincipal := tc.getProxySSHPrincipal()
proxyAddr := tc.Config.ProxySSHHostPort()
proxyAddr := tc.Config.SSHProxyAddr
sshConfig := &ssh.ClientConfig{
User: proxyPrincipal,
HostKeyCallback: tc.HostKeyCallback,
@ -1438,11 +1456,10 @@ func (tc *TeleportClient) LogoutAll() error {
// keystore (and into the ssh-agent) for future use.
//
func (tc *TeleportClient) Login(ctx context.Context, activateKey bool) (*Key, error) {
httpsProxyHostPort := tc.Config.ProxyWebHostPort()
certPool := loopbackPool(httpsProxyHostPort)
certPool := loopbackPool(tc.Config.WebProxyAddr)
// ping the endpoint to see if it's up and find the type of authentication supported
pr, err := Ping(httpsProxyHostPort, tc.InsecureSkipVerify, certPool, tc.AuthConnector)
pr, err := Ping(tc.Config.WebProxyAddr, tc.InsecureSkipVerify, certPool, tc.AuthConnector)
if err != nil {
return nil, trace.Wrap(err)
}
@ -1578,10 +1595,11 @@ func (tc *TeleportClient) applyProxySettings(proxySettings ProxySettings) error
}
tc.KubeProxyAddr = proxySettings.Kube.PublicAddr
} else if proxySettings.Kube.Enabled && tc.KubeProxyAddr == "" {
tc.KubeProxyAddr = fmt.Sprintf("%s:%d", tc.ProxyWebHost, defaults.KubeProxyListenPort)
webProxyHost, _ := tc.WebProxyHostPort()
tc.KubeProxyAddr = fmt.Sprintf("%s:%d", webProxyHost, defaults.KubeProxyListenPort)
}
// The hostname of the SSH proxy comes from public_addr.
// Read in settings for HTTP endpoint of the proxy.
if proxySettings.SSH.PublicAddr != "" {
addr, err := utils.ParseAddr(proxySettings.SSH.PublicAddr)
if err != nil {
@ -1589,9 +1607,18 @@ func (tc *TeleportClient) applyProxySettings(proxySettings ProxySettings) error
"failed to parse value received from the server: %q, contact your administrator for help",
proxySettings.SSH.PublicAddr)
}
tc.ProxySSHHost = addr.Host()
tc.WebProxyAddr = net.JoinHostPort(addr.Host(), strconv.Itoa(addr.Port(defaults.HTTPListenPort)))
// Update local agent (that reads/writes to ~/.tsh) with the new address
// of the web proxy. This will control where the keys are stored on disk
// after login.
tc.localAgent.UpdateProxyHost(addr.Host())
}
// The port of the SSH proxy comes from listen_addr.
// Read in settings for the SSH endpoint of the proxy.
//
// If listen_addr is set, take host from ProxyWebHost and port from what
// was set. This is to maintain backward compatibility when Teleport only
// supported public_addr.
if proxySettings.SSH.ListenAddr != "" {
addr, err := utils.ParseAddr(proxySettings.SSH.ListenAddr)
if err != nil {
@ -1599,7 +1626,18 @@ func (tc *TeleportClient) applyProxySettings(proxySettings ProxySettings) error
"failed to parse value received from the server: %q, contact your administrator for help",
proxySettings.SSH.ListenAddr)
}
tc.ProxySSHPort = addr.Port(defaults.SSHProxyListenPort)
webProxyHost, _ := tc.WebProxyHostPort()
tc.SSHProxyAddr = net.JoinHostPort(webProxyHost, strconv.Itoa(addr.Port(defaults.SSHProxyListenPort)))
}
// If ssh_public_addr is set, override settings from listen_addr.
if proxySettings.SSH.SSHPublicAddr != "" {
addr, err := utils.ParseAddr(proxySettings.SSH.SSHPublicAddr)
if err != nil {
return trace.BadParameter(
"failed to parse value received from the server: %q, contact your administrator for help",
proxySettings.SSH.ListenAddr)
}
tc.SSHProxyAddr = net.JoinHostPort(addr.Host(), strconv.Itoa(addr.Port(defaults.SSHProxyListenPort)))
}
return nil
@ -1654,8 +1692,7 @@ func (tc *TeleportClient) AddKey(host string, key *Key) (*agent.AddedKey, error)
func (tc *TeleportClient) directLogin(secondFactorType string, pub []byte) (*auth.SSHLoginResponse, error) {
var err error
httpsProxyHostPort := tc.Config.ProxyWebHostPort()
certPool := loopbackPool(httpsProxyHostPort)
certPool := loopbackPool(tc.Config.WebProxyAddr)
var password string
var otpToken string
@ -1675,7 +1712,7 @@ func (tc *TeleportClient) directLogin(secondFactorType string, pub []byte) (*aut
// ask the CA (via proxy) to sign our public key:
response, err := SSHAgentLogin(
httpsProxyHostPort,
tc.Config.WebProxyAddr,
tc.Config.Username,
password,
otpToken,
@ -1692,15 +1729,14 @@ func (tc *TeleportClient) directLogin(secondFactorType string, pub []byte) (*aut
func (tc *TeleportClient) ssoLogin(ctx context.Context, connectorID string, pub []byte, protocol string) (*auth.SSHLoginResponse, error) {
log.Debugf("samlLogin start")
// ask the CA (via proxy) to sign our public key:
webProxyAddr := tc.Config.ProxyWebHostPort()
response, err := SSHAgentSSOLogin(
ctx,
webProxyAddr,
tc.Config.WebProxyAddr,
connectorID,
pub,
tc.KeyTTL,
tc.InsecureSkipVerify,
loopbackPool(webProxyAddr),
loopbackPool(tc.Config.WebProxyAddr),
protocol,
tc.CertificateFormat)
return response, trace.Wrap(err)
@ -1714,8 +1750,7 @@ func (tc *TeleportClient) u2fLogin(pub []byte) (*auth.SSHLoginResponse, error) {
return nil, trace.Wrap(err)
}
httpsProxyHostPort := tc.Config.ProxyWebHostPort()
certPool := loopbackPool(httpsProxyHostPort)
certPool := loopbackPool(tc.Config.WebProxyAddr)
password, err := tc.AskPassword()
if err != nil {
@ -1723,7 +1758,7 @@ func (tc *TeleportClient) u2fLogin(pub []byte) (*auth.SSHLoginResponse, error) {
}
response, err := SSHAgentU2FLogin(
httpsProxyHostPort,
tc.Config.WebProxyAddr,
tc.Config.Username,
password,
pub,

View file

@ -40,39 +40,45 @@ func (s *APITestSuite) SetUpSuite(c *check.C) {
func (s *APITestSuite) TestConfig(c *check.C) {
var conf Config
c.Assert(conf.ProxySpecified(), check.Equals, false)
conf.ProxyHostPort = "example.org"
err := conf.ParseProxyHost("example.org")
c.Assert(err, check.IsNil)
c.Assert(conf.ProxySpecified(), check.Equals, true)
c.Assert(conf.ProxySSHHostPort(), check.Equals, "example.org:3023")
c.Assert(conf.ProxyWebHostPort(), check.Equals, "example.org:3080")
c.Assert(conf.SSHProxyAddr, check.Equals, "example.org:3023")
c.Assert(conf.WebProxyAddr, check.Equals, "example.org:3080")
conf.SetProxy("example.org", 100, 200)
c.Assert(conf.ProxyWebHostPort(), check.Equals, "example.org:100")
c.Assert(conf.ProxySSHHostPort(), check.Equals, "example.org:200")
conf.WebProxyAddr = "example.org:100"
conf.SSHProxyAddr = "example.org:200"
c.Assert(conf.WebProxyAddr, check.Equals, "example.org:100")
c.Assert(conf.SSHProxyAddr, check.Equals, "example.org:200")
conf.ProxyHostPort = "example.org:200"
c.Assert(conf.ProxyWebHostPort(), check.Equals, "example.org:200")
c.Assert(conf.ProxySSHHostPort(), check.Equals, "example.org:3023")
err = conf.ParseProxyHost("example.org:200")
c.Assert(err, check.IsNil)
c.Assert(conf.WebProxyAddr, check.Equals, "example.org:200")
c.Assert(conf.SSHProxyAddr, check.Equals, "example.org:3023")
conf.ProxyHostPort = "example.org:,200"
c.Assert(conf.ProxySSHHostPort(), check.Equals, "example.org:200")
c.Assert(conf.ProxyWebHostPort(), check.Equals, "example.org:3080")
conf.SetProxy("example.org", 100, 200)
c.Assert(conf.ProxyWebHostPort(), check.Equals, "example.org:100")
c.Assert(conf.ProxySSHHostPort(), check.Equals, "example.org:200")
err = conf.ParseProxyHost("example.org:,200")
c.Assert(err, check.IsNil)
c.Assert(conf.SSHProxyAddr, check.Equals, "example.org:200")
c.Assert(conf.WebProxyAddr, check.Equals, "example.org:3080")
conf.WebProxyAddr = "example.org:100"
conf.SSHProxyAddr = "example.org:200"
c.Assert(conf.WebProxyAddr, check.Equals, "example.org:100")
c.Assert(conf.SSHProxyAddr, check.Equals, "example.org:200")
}
func (s *APITestSuite) TestNew(c *check.C) {
conf := Config{
Host: "localhost",
HostLogin: "vincent",
HostPort: 22,
KeysDir: "/tmp",
Username: "localuser",
ProxyHostPort: "proxy",
SiteName: "site",
Host: "localhost",
HostLogin: "vincent",
HostPort: 22,
KeysDir: "/tmp",
Username: "localuser",
SiteName: "site",
}
err := conf.ParseProxyHost("proxy")
c.Assert(err, check.IsNil)
tc, err := NewClient(&conf)
c.Assert(err, check.IsNil)
c.Assert(tc, check.NotNil)

View file

@ -39,10 +39,12 @@ func (s *ClientTestSuite) TestHelperFunctions(c *check.C) {
func (s *ClientTestSuite) SetUpSuite(c *check.C) {
// create the client:
client, err := NewClient(&Config{
ProxyHostPort: "localhost:3023",
KeysDir: c.MkDir(),
})
config := &Config{
KeysDir: c.MkDir(),
}
err := config.ParseProxyHost("localhost")
c.Assert(err, check.IsNil)
client, err := NewClient(config)
c.Assert(err, check.IsNil)
c.Assert(client, check.NotNil)
s.client = client

View file

@ -110,6 +110,11 @@ func NewLocalAgent(keyDir string, proxyHost string, username string) (a *LocalKe
return a, nil
}
// UpdateProxyHost changes the proxy host that the local agent operates on.
func (a *LocalKeyAgent) UpdateProxyHost(proxyHost string) {
a.proxyHost = proxyHost
}
// LoadKey adds a key into the Teleport ssh agent as well as the system ssh
// agent.
func (a *LocalKeyAgent) LoadKey(key Key) (*agent.AddedKey, error) {

View file

@ -2,6 +2,7 @@ package client
import (
"io/ioutil"
"net"
"os"
"os/user"
"path/filepath"
@ -34,19 +35,13 @@ const CurrentProfileSymlink = "profile"
// type fewer CLI args.
//
type ClientProfile struct {
// ProxyWebHost is the address of the web proxy can be accessed at.
ProxyWebHost string `yaml:"proxy_host,omitempty"`
// WebProxyAddr is the host:port the web proxy can be accessed at.
WebProxyAddr string `yaml:"web_proxy_addr,omitempty"`
// ProxyWebPort is port the web proxy can be accessed at.
ProxyWebPort int `yaml:"proxy_port,omitempty"`
// SSHProxyAddr is the host:port the SSH proxy can be accessed at.
SSHProxyAddr string `yaml:"ssh_proxy_addr,omitempty"`
// ProxySSHHost is the host the SSH proxy can be accessed at.
ProxySSHHost string `yaml:"proxy_ssh_host,omitempty"`
// ProxySSHPort is the port the SSH proxy can be accessed at.
ProxySSHPort int `yaml:"proxy_ssh_port,omitempty"`
// KubeProxyAddr is a kubernetes address in host:port format
// KubeProxyAddr is the host:port the Kubernetes proxy can be accessed at.
KubeProxyAddr string `yaml:"kube_proxy_addr,omitempty"`
// Username is the Teleport username for the client.
@ -60,6 +55,27 @@ type ClientProfile struct {
// ForwardedPorts is the list of ports to forward to the target node.
ForwardedPorts []string `yaml:"forward_ports,omitempty"`
// DELETE IN: 3.1.0
// The following fields have been deprecated and replaced with
// "proxy_web_addr" and "proxy_ssh_addr".
ProxyHost string `yaml:"proxy_host,omitempty"`
ProxySSHPort int `yaml:"proxy_port,omitempty"`
ProxyWebPort int `yaml:"proxy_web_port,omitempty"`
}
// Name returns the name of the profile.
func (c *ClientProfile) Name() string {
if c.ProxyHost != "" {
return c.ProxyHost
}
addr, _, err := net.SplitHostPort(c.WebProxyAddr)
if err != nil {
return c.WebProxyAddr
}
return addr
}
// FullProfilePath returns the full path to the user profile directory.

View file

@ -31,9 +31,8 @@ var _ = check.Suite(&ProfileTestSuite{})
func (s *ProfileTestSuite) TestEverything(c *check.C) {
p := &ClientProfile{
ProxyHost: "proxy",
ProxySSHPort: 3023,
ProxyWebPort: 3088,
WebProxyAddr: "proxy:3088",
SSHProxyAddr: "proxy:3023",
Username: "testuser",
ForwardedPorts: []string{"8000:example.com:8000"},
}

View file

@ -314,8 +314,11 @@ type SSHProxySettings struct {
// connections on.
ListenAddr string `json:"listen_addr,omitempty"`
// PublicAddr is the public address the SSH proxy is accessible at.
// PublicAddr is the public address of the HTTP proxy.
PublicAddr string `json:"public_addr,omitempty"`
// SSHPublicAddr is the public address of the SSH proxy.
SSHPublicAddr string `json:"ssh_public_addr,omitempty"`
}
// PingResponse contains the form of authentication the auth server supports.
@ -516,7 +519,7 @@ func SSHAgentU2FLogin(proxyAddr, user, password string, pubKey []byte, ttl time.
// initClient creates and initializes HTTPS client for talking to teleport proxy HTTPS
// endpoint.
func initClient(proxyAddr string, insecure bool, pool *x509.CertPool) (*WebClient, *url.URL, error) {
log.Debugf("HTTPS client init(insecure=%v)", insecure)
log.Debugf("HTTPS client init(proxyAddr=%v, insecure=%v)", proxyAddr, insecure)
// validate proxyAddr:
host, port, err := net.SplitHostPort(proxyAddr)

View file

@ -315,6 +315,13 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error {
}
cfg.Proxy.PublicAddrs = addrs
}
if len(fc.Proxy.SSHPublicAddr) != 0 {
addrs, err := fc.Proxy.SSHPublicAddr.Addrs(defaults.SSHProxyListenPort)
if err != nil {
return trace.Wrap(err)
}
cfg.Proxy.SSHPublicAddrs = addrs
}
if fc.Proxy.KeyFile != "" {
if !fileExists(fc.Proxy.KeyFile) {
return trace.Errorf("https key does not exist: %s", fc.Proxy.KeyFile)

View file

@ -125,6 +125,7 @@ var (
"dynamic_config": false,
"seed_config": false,
"public_addr": false,
"ssh_public_addr": false,
"cache": true,
"ttl": false,
"issuer": false,
@ -722,8 +723,6 @@ type Proxy struct {
KeyFile string `yaml:"https_key_file,omitempty"`
// CertFile is a TLS Certificate file
CertFile string `yaml:"https_cert_file,omitempty"`
// PublicAddr is a publicly advertised address of the proxy
PublicAddr utils.Strings `yaml:"public_addr,omitempty"`
// ProxyProtocol turns on support for HAProxy proxy protocol
// this is the option that has be turned on only by administrator,
// as only admin knows whether service is in front of trusted load balancer
@ -731,6 +730,16 @@ type Proxy struct {
ProxyProtocol string `yaml:"proxy_protocol,omitempty"`
// Kube configures kubernetes protocol support of the proxy
Kube Kube `yaml:"kubernetes,omitempty"`
// PublicAddr sets the hostport the proxy advertises for the HTTP endpoint.
// The hosts in PublicAddr are included in the list of host principals
// on the SSH certificate.
PublicAddr utils.Strings `yaml:"public_addr,omitempty"`
// SSHPublicAddr sets the hostport the proxy advertises for the SSH endpoint.
// The hosts in PublicAddr are included in the list of host principals
// on the SSH certificate.
SSHPublicAddr utils.Strings `yaml:"ssh_public_addr,omitempty"`
}
// Kube is a `kubernetes_service`

View file

@ -278,10 +278,16 @@ type ProxyConfig struct {
Limiter limiter.LimiterConfig
// PublicAddrs is a list of the public addresses the Teleport UI can be accessed at,
// it also affects the SSH host principals and DNS names added to the SSH and TLS certs.
// PublicAddrs is a list of the public addresses the proxy advertises
// for the HTTP endpoint. The hosts in in PublicAddr are included in the
// list of host principals on the TLS and SSH certificate.
PublicAddrs []utils.NetAddr
// SSHPublicAddrs is a list of the public addresses the proxy advertises
// for the SSH endpoint. The hosts in in PublicAddr are included in the
// list of host principals on the TLS and SSH certificate.
SSHPublicAddrs []utils.NetAddr
// Kube specifies kubernetes proxy configuration
Kube KubeProxyConfig
}

View file

@ -1483,6 +1483,7 @@ func (process *TeleportProcess) getAdditionalPrincipals(role teleport.Role) ([]s
switch role {
case teleport.RoleProxy:
addrs = append(process.Config.Proxy.PublicAddrs, utils.NetAddr{Addr: reversetunnel.RemoteKubeProxy})
addrs = append(addrs, process.Config.Proxy.SSHPublicAddrs...)
addrs = append(addrs, process.Config.Proxy.Kube.PublicAddrs...)
case teleport.RoleAuth, teleport.RoleAdmin:
addrs = process.Config.Auth.PublicAddrs
@ -1760,6 +1761,9 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error {
if len(cfg.Proxy.PublicAddrs) > 0 {
proxySettings.SSH.PublicAddr = cfg.Proxy.PublicAddrs[0].String()
}
if len(cfg.Proxy.SSHPublicAddrs) > 0 {
proxySettings.SSH.SSHPublicAddr = cfg.Proxy.SSHPublicAddrs[0].String()
}
if len(cfg.Proxy.Kube.PublicAddrs) > 0 {
proxySettings.Kube.PublicAddr = cfg.Proxy.Kube.PublicAddrs[0].String()
}

View file

@ -417,7 +417,11 @@ func onLogin(cf *CLIConf) {
utils.FatalError(err)
}
// Print status to show information of the logged in user.
// Print status to show information of the logged in user. Update the
// command line flag (used to print status) for the proxy to make sure any
// advertised settings are picked up.
webProxyHost, _ := tc.WebProxyHostPort()
cf.Proxy = webProxyHost
onStatus(cf)
}

View file

@ -64,8 +64,8 @@ func (s *MainTestSuite) TestMakeClient(c *check.C) {
tc, err = makeClient(&conf, true)
c.Assert(err, check.IsNil)
c.Assert(tc, check.NotNil)
c.Assert(tc.Config.ProxySSHHostPort(), check.Equals, "proxy:3023")
c.Assert(tc.Config.ProxyWebHostPort(), check.Equals, "proxy:3080")
c.Assert(tc.Config.SSHProxyAddr, check.Equals, "proxy:3023")
c.Assert(tc.Config.WebProxyAddr, check.Equals, "proxy:3080")
localUser, err := client.Username()
c.Assert(err, check.IsNil)
c.Assert(tc.Config.HostLogin, check.Equals, localUser)