Adding postgres_public_addr and mysql_public_addr (#6426)

This commit is contained in:
Roman Tkachenko 2021-04-21 19:52:52 -07:00 committed by GitHub
parent 7ff9d9d5d6
commit d67e11ff2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 449 additions and 31 deletions

View file

@ -146,8 +146,12 @@ type SSHProxySettings struct {
// DBProxySettings contains database access specific proxy settings.
type DBProxySettings struct {
// PostgresPublicAddr is advertised to Postgres clients.
PostgresPublicAddr string `json:"postgres_public_addr,omitempty"`
// MySQLListenAddr is MySQL proxy listen address.
MySQLListenAddr string `json:"mysql_listen_addr,omitempty"`
// MySQLPublicAddr is advertised to MySQL clients.
MySQLPublicAddr string `json:"mysql_public_addr,omitempty"`
}
// PingResponse contains the form of authentication the auth server supports.

View file

@ -59,6 +59,9 @@ type Profile struct {
// KubeProxyAddr is the host:port the Kubernetes proxy can be accessed at.
KubeProxyAddr string `yaml:"kube_proxy_addr,omitempty"`
// PostgresProxyAddr is the host:port the Postgres proxy can be accessed at.
PostgresProxyAddr string `yaml:"postgres_proxy_addr,omitempty"`
// MySQLProxyAddr is the host:port the MySQL proxy can be accessed at.
MySQLProxyAddr string `yaml:"mysql_proxy_addr,omitempty"`

View file

@ -181,6 +181,9 @@ type Config struct {
// KubeProxyAddr is the host:port the Kubernetes proxy can be accessed at.
KubeProxyAddr string
// PostgresProxyAddr is the host:port the Postgres proxy can be accessed at.
PostgresProxyAddr string
// MySQLProxyAddr is the host:port the MySQL proxy can be accessed at.
MySQLProxyAddr string
@ -751,6 +754,7 @@ func (c *Config) LoadProfile(profileDir string, proxyName string) error {
c.KubeProxyAddr = cp.KubeProxyAddr
c.WebProxyAddr = cp.WebProxyAddr
c.SSHProxyAddr = cp.SSHProxyAddr
c.PostgresProxyAddr = cp.PostgresProxyAddr
c.MySQLProxyAddr = cp.MySQLProxyAddr
c.LocalForwardPorts, err = ParsePortForwardSpec(cp.ForwardedPorts)
@ -780,6 +784,7 @@ func (c *Config) SaveProfile(dir string, makeCurrent bool) error {
cp.WebProxyAddr = c.WebProxyAddr
cp.SSHProxyAddr = c.SSHProxyAddr
cp.KubeProxyAddr = c.KubeProxyAddr
cp.PostgresProxyAddr = c.PostgresProxyAddr
cp.MySQLProxyAddr = c.MySQLProxyAddr
cp.ForwardedPorts = c.LocalForwardPorts.String()
cp.SiteName = c.SiteName
@ -867,6 +872,12 @@ func (c *Config) WebProxyHostPort() (string, int) {
return "unknown", defaults.HTTPListenPort
}
// WebProxyHost returns the web proxy host without the port number.
func (c *Config) WebProxyHost() string {
host, _ := c.WebProxyHostPort()
return host
}
// WebProxyPort returns the port of the web proxy.
func (c *Config) WebProxyPort() int {
_, port := c.WebProxyHostPort()
@ -886,6 +897,17 @@ func (c *Config) SSHProxyHostPort() (string, int) {
return webProxyHost, defaults.SSHProxyListenPort
}
// PostgresProxyHostPort returns the host and port of Postgres proxy.
func (c *Config) PostgresProxyHostPort() (string, int) {
if c.PostgresProxyAddr != "" {
addr, err := utils.ParseAddr(c.PostgresProxyAddr)
if err == nil {
return addr.Host(), addr.Port(c.WebProxyPort())
}
}
return c.WebProxyHostPort()
}
// MySQLProxyHostPort returns the host and port of MySQL proxy.
func (c *Config) MySQLProxyHostPort() (string, int) {
if c.MySQLProxyAddr != "" {
@ -2423,16 +2445,36 @@ func (tc *TeleportClient) applyProxySettings(proxySettings webclient.ProxySettin
tc.SSHProxyAddr = net.JoinHostPort(addr.Host(), strconv.Itoa(addr.Port(defaults.SSHProxyListenPort)))
}
// Read Postgres proxy settings.
switch {
case proxySettings.DB.PostgresPublicAddr != "":
addr, err := utils.ParseAddr(proxySettings.DB.PostgresPublicAddr)
if err != nil {
return trace.BadParameter("failed to parse Postgres public address received from server: %q, contact your administrator for help",
proxySettings.DB.PostgresPublicAddr)
}
tc.PostgresProxyAddr = net.JoinHostPort(addr.Host(), strconv.Itoa(addr.Port(tc.WebProxyPort())))
default:
webProxyHost, webProxyPort := tc.WebProxyHostPort()
tc.PostgresProxyAddr = net.JoinHostPort(webProxyHost, strconv.Itoa(webProxyPort))
}
// Read MySQL proxy settings if enabled on the server.
if proxySettings.DB.MySQLListenAddr != "" {
switch {
case proxySettings.DB.MySQLPublicAddr != "":
addr, err := utils.ParseAddr(proxySettings.DB.MySQLPublicAddr)
if err != nil {
return trace.BadParameter("failed to parse MySQL public address received from server: %q, contact your administrator for help",
proxySettings.DB.MySQLPublicAddr)
}
tc.MySQLProxyAddr = net.JoinHostPort(addr.Host(), strconv.Itoa(addr.Port(defaults.MySQLListenPort)))
case proxySettings.DB.MySQLListenAddr != "":
addr, err := utils.ParseAddr(proxySettings.DB.MySQLListenAddr)
if err != nil {
return trace.BadParameter(
"failed to parse value received from the server: %q, contact your administrator for help",
return trace.BadParameter("failed to parse MySQL listen address received from server: %q, contact your administrator for help",
proxySettings.DB.MySQLListenAddr)
}
webProxyHost, _ := tc.WebProxyHostPort()
tc.MySQLProxyAddr = net.JoinHostPort(webProxyHost, strconv.Itoa(addr.Port(defaults.MySQLListenPort)))
tc.MySQLProxyAddr = net.JoinHostPort(tc.WebProxyHost(), strconv.Itoa(addr.Port(defaults.MySQLListenPort)))
}
return nil

View file

@ -20,6 +20,7 @@ import (
"os"
"testing"
"github.com/gravitational/teleport/api/client/webclient"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/utils"
@ -312,3 +313,83 @@ func TestWebProxyHostPort(t *testing.T) {
})
}
}
// TestApplyProxySettings validates that settings received from the proxy's
// ping endpoint are correctly applied to Teleport client.
func TestApplyProxySettings(t *testing.T) {
tests := []struct {
desc string
settingsIn webclient.ProxySettings
tcConfigIn Config
tcConfigOut Config
}{
{
desc: "Postgres public address unspecified, defaults to web proxy address",
settingsIn: webclient.ProxySettings{},
tcConfigIn: Config{
WebProxyAddr: "web.example.com:443",
},
tcConfigOut: Config{
WebProxyAddr: "web.example.com:443",
PostgresProxyAddr: "web.example.com:443",
},
},
{
desc: "MySQL enabled without public address, defaults to web proxy host and MySQL default port",
settingsIn: webclient.ProxySettings{
DB: webclient.DBProxySettings{
MySQLListenAddr: "0.0.0.0:3036",
},
},
tcConfigIn: Config{
WebProxyAddr: "web.example.com:443",
},
tcConfigOut: Config{
WebProxyAddr: "web.example.com:443",
PostgresProxyAddr: "web.example.com:443",
MySQLProxyAddr: "web.example.com:3036",
},
},
{
desc: "both Postgres and MySQL custom public addresses are specified",
settingsIn: webclient.ProxySettings{
DB: webclient.DBProxySettings{
PostgresPublicAddr: "postgres.example.com:5432",
MySQLListenAddr: "0.0.0.0:3036",
MySQLPublicAddr: "mysql.example.com:3306",
},
},
tcConfigIn: Config{
WebProxyAddr: "web.example.com:443",
},
tcConfigOut: Config{
WebProxyAddr: "web.example.com:443",
PostgresProxyAddr: "postgres.example.com:5432",
MySQLProxyAddr: "mysql.example.com:3306",
},
},
{
desc: "Postgres public address port unspecified, defaults to web proxy address port",
settingsIn: webclient.ProxySettings{
DB: webclient.DBProxySettings{
PostgresPublicAddr: "postgres.example.com",
},
},
tcConfigIn: Config{
WebProxyAddr: "web.example.com:443",
},
tcConfigOut: Config{
WebProxyAddr: "web.example.com:443",
PostgresProxyAddr: "postgres.example.com:443",
},
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
tc := &TeleportClient{Config: test.tcConfigIn}
err := tc.applyProxySettings(test.settingsIn)
require.NoError(t, err)
require.EqualValues(t, test.tcConfigOut, tc.Config)
})
}
}

View file

@ -44,24 +44,7 @@ func Add(tc *client.TeleportClient, db tlsca.RouteToDatabase, clientProfile clie
if err != nil {
return trace.Wrap(err)
}
// Postgres proxy listens on web proxy port while MySQL proxy listens on
// a separate port due to the specifics of the protocol.
host, port := tc.WebProxyHostPort()
if db.Protocol == defaults.ProtocolMySQL {
host, port = tc.MySQLProxyHostPort()
}
connectProfile := profile.ConnectProfile{
Name: profileName(tc.SiteName, db.ServiceName),
Host: host,
Port: port,
User: db.Username,
Database: db.Database,
Insecure: tc.InsecureSkipVerify,
CACertPath: clientProfile.CACertPath(),
CertPath: clientProfile.DatabaseCertPath(db.ServiceName),
KeyPath: clientProfile.KeyPath(),
}
err = profileFile.Upsert(connectProfile)
connectProfile, err := add(tc, db, clientProfile, profileFile)
if err != nil {
return trace.Wrap(err)
}
@ -77,6 +60,35 @@ func Add(tc *client.TeleportClient, db tlsca.RouteToDatabase, clientProfile clie
return nil
}
func add(tc *client.TeleportClient, db tlsca.RouteToDatabase, clientProfile client.ProfileStatus, profileFile profile.ConnectProfileFile) (*profile.ConnectProfile, error) {
var host string
var port int
switch db.Protocol {
case defaults.ProtocolPostgres:
host, port = tc.PostgresProxyHostPort()
case defaults.ProtocolMySQL:
host, port = tc.MySQLProxyHostPort()
default:
return nil, trace.BadParameter("unknown database protocol: %q", db)
}
connectProfile := profile.ConnectProfile{
Name: profileName(tc.SiteName, db.ServiceName),
Host: host,
Port: port,
User: db.Username,
Database: db.Database,
Insecure: tc.InsecureSkipVerify,
CACertPath: clientProfile.CACertPath(),
CertPath: clientProfile.DatabaseCertPath(db.ServiceName),
KeyPath: clientProfile.KeyPath(),
}
err := profileFile.Upsert(connectProfile)
if err != nil {
return nil, trace.Wrap(err)
}
return &connectProfile, nil
}
// Env returns environment variables for the specified database profile.
func Env(tc *client.TeleportClient, db tlsca.RouteToDatabase) (map[string]string, error) {
profileFile, err := load(db)

View file

@ -0,0 +1,142 @@
/*
Copyright 2021 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 db
import (
"testing"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/client/db/profile"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/trace"
"github.com/stretchr/testify/require"
)
// TestAddProfile verifies that connection profile is populated with correct
// proxy address.
func TestAddProfile(t *testing.T) {
tests := []struct {
desc string
webProxyAddrIn string
postgresProxyAddrIn string
mysqlProxyAddrIn string
protocolIn string
profileHostOut string
profilePortOut int
}{
{
desc: "postgres - web proxy host port",
webProxyAddrIn: "web.example.com:443",
protocolIn: defaults.ProtocolPostgres,
profileHostOut: "web.example.com",
profilePortOut: 443,
},
{
desc: "postgres - custom host",
webProxyAddrIn: "web.example.com:443",
postgresProxyAddrIn: "postgres.example.com",
protocolIn: defaults.ProtocolPostgres,
profileHostOut: "postgres.example.com",
profilePortOut: 443,
},
{
desc: "postgres - custom host port",
webProxyAddrIn: "web.example.com:443",
postgresProxyAddrIn: "postgres.example.com:5432",
protocolIn: defaults.ProtocolPostgres,
profileHostOut: "postgres.example.com",
profilePortOut: 5432,
},
{
desc: "mysql - web proxy host, default port",
webProxyAddrIn: "web.example.com:443",
protocolIn: defaults.ProtocolMySQL,
profileHostOut: "web.example.com",
profilePortOut: defaults.MySQLListenPort,
},
{
desc: "mysql - custom host",
webProxyAddrIn: "web.example.com:443",
mysqlProxyAddrIn: "mysql.example.com",
protocolIn: defaults.ProtocolMySQL,
profileHostOut: "mysql.example.com",
profilePortOut: defaults.MySQLListenPort,
},
{
desc: "mysql - custom host port",
webProxyAddrIn: "web.example.com:443",
mysqlProxyAddrIn: "mysql.example.com:3336",
protocolIn: defaults.ProtocolMySQL,
profileHostOut: "mysql.example.com",
profilePortOut: 3336,
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
tc := &client.TeleportClient{
Config: client.Config{
SiteName: "example.com",
WebProxyAddr: test.webProxyAddrIn,
PostgresProxyAddr: test.postgresProxyAddrIn,
MySQLProxyAddr: test.mysqlProxyAddrIn,
},
}
db := tlsca.RouteToDatabase{
ServiceName: "example",
Protocol: test.protocolIn,
}
ps := client.ProfileStatus{
Dir: t.TempDir(),
Name: "alice",
}
actual, err := add(tc, db, ps, &testProfileFile{profiles: make(map[string]profile.ConnectProfile)})
require.NoError(t, err)
require.EqualValues(t, &profile.ConnectProfile{
Name: profileName(tc.SiteName, db.ServiceName),
Host: test.profileHostOut,
Port: test.profilePortOut,
CACertPath: ps.CACertPath(),
CertPath: ps.DatabaseCertPath(db.ServiceName),
KeyPath: ps.KeyPath(),
}, actual)
})
}
}
// testProfileFile is the test implementation of connection profile file.
type testProfileFile struct {
profiles map[string]profile.ConnectProfile
}
// Upsert saves the provided connection profile.
func (p *testProfileFile) Upsert(profile profile.ConnectProfile) error {
p.profiles[profile.Name] = profile
return nil
}
// Env returns the specified connection profile as environment variables.
func (p *testProfileFile) Env(name string) (map[string]string, error) {
return nil, trace.NotImplemented("not implemented")
}
// Delete removes the specified connection profile.
func (p *testProfileFile) Delete(name string) error {
delete(p.profiles, name)
return nil
}

View file

@ -686,6 +686,34 @@ func applyProxyConfig(fc *FileConfig, cfg *service.Config) error {
}
cfg.Proxy.TunnelPublicAddrs = addrs
}
if len(fc.Proxy.PostgresPublicAddr) != 0 {
// Postgres proxy is multiplexed on the web proxy port. If the port is
// not specified here explicitly, prefer defaults in the following
// order, depending on what's set:
// 1. Web proxy public port
// 2. Web proxy listen port
// 3. Web proxy default listen port
defaultPort := cfg.Proxy.WebAddr.Port(defaults.HTTPListenPort)
if len(cfg.Proxy.PublicAddrs) != 0 {
defaultPort = cfg.Proxy.PublicAddrs[0].Port(defaults.HTTPListenPort)
}
addrs, err := utils.AddrsFromStrings(fc.Proxy.PostgresPublicAddr, defaultPort)
if err != nil {
return trace.Wrap(err)
}
cfg.Proxy.PostgresPublicAddrs = addrs
}
if len(fc.Proxy.MySQLPublicAddr) != 0 {
if fc.Proxy.MySQLAddr == "" {
return trace.BadParameter("mysql_listen_addr must be set when mysql_public_addr is set")
}
// MySQL proxy is listening on a separate port.
addrs, err := utils.AddrsFromStrings(fc.Proxy.MySQLPublicAddr, defaults.MySQLListenPort)
if err != nil {
return trace.Wrap(err)
}
cfg.Proxy.MySQLPublicAddrs = addrs
}
acme, err := fc.Proxy.ACME.Parse()
if err != nil {

View file

@ -21,8 +21,10 @@ import (
"encoding/base64"
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"strconv"
"testing"
"time"
@ -514,6 +516,11 @@ func TestApplyConfig(t *testing.T) {
require.True(t, cfg.Proxy.Enabled)
require.Equal(t, "tcp://webhost:3080", cfg.Proxy.WebAddr.FullAddress())
require.Equal(t, "tcp://tunnelhost:1001", cfg.Proxy.ReverseTunnelListenAddr.FullAddress())
require.Equal(t, "tcp://webhost:3336", cfg.Proxy.MySQLAddr.FullAddress())
require.Len(t, cfg.Proxy.PostgresPublicAddrs, 1)
require.Equal(t, "tcp://postgres.example:5432", cfg.Proxy.PostgresPublicAddrs[0].FullAddress())
require.Len(t, cfg.Proxy.MySQLPublicAddrs, 1)
require.Equal(t, "tcp://mysql.example:3306", cfg.Proxy.MySQLPublicAddrs[0].FullAddress())
u2fCAFromFile, err := ioutil.ReadFile("testdata/u2f_attestation_ca.pem")
require.NoError(t, err)
@ -569,13 +576,75 @@ func TestApplyConfigNoneEnabled(t *testing.T) {
require.NoError(t, err)
require.False(t, cfg.Auth.Enabled)
require.Len(t, cfg.Auth.PublicAddrs, 0)
require.Empty(t, cfg.Auth.PublicAddrs)
require.False(t, cfg.Proxy.Enabled)
require.Len(t, cfg.Proxy.PublicAddrs, 0)
require.Empty(t, cfg.Proxy.PublicAddrs)
require.False(t, cfg.SSH.Enabled)
require.Len(t, cfg.SSH.PublicAddrs, 0)
require.Empty(t, cfg.SSH.PublicAddrs)
require.False(t, cfg.Apps.Enabled)
require.False(t, cfg.Databases.Enabled)
require.Empty(t, cfg.Proxy.PostgresPublicAddrs)
require.Empty(t, cfg.Proxy.MySQLPublicAddrs)
}
// TestPostgresPublicAddr makes sure Postgres proxy public address default
// port logic works correctly.
func TestPostgresPublicAddr(t *testing.T) {
tests := []struct {
desc string
fc *FileConfig
out []string
}{
{
desc: "postgres public address with port set",
fc: &FileConfig{
Proxy: Proxy{
WebAddr: "0.0.0.0:8080",
PublicAddr: []string{"web.example.com:443"},
PostgresPublicAddr: []string{"postgres.example.com:5432"},
},
},
out: []string{"postgres.example.com:5432"},
},
{
desc: "when port not set, defaults to web proxy public port",
fc: &FileConfig{
Proxy: Proxy{
WebAddr: "0.0.0.0:8080",
PublicAddr: []string{"web.example.com:443"},
PostgresPublicAddr: []string{"postgres.example.com"},
},
},
out: []string{"postgres.example.com:443"},
},
{
desc: "when port and public addr not set, defaults to web proxy listen port",
fc: &FileConfig{
Proxy: Proxy{
WebAddr: "0.0.0.0:8080",
PostgresPublicAddr: []string{"postgres.example.com"},
},
},
out: []string{"postgres.example.com:8080"},
},
{
desc: "when port and listen/public addrs not set, defaults to web proxy default port",
fc: &FileConfig{
Proxy: Proxy{
PostgresPublicAddr: []string{"postgres.example.com"},
},
},
out: []string{net.JoinHostPort("postgres.example.com", strconv.Itoa(defaults.HTTPListenPort))},
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
cfg := service.MakeDefaultConfig()
err := applyProxyConfig(test.fc, cfg)
require.NoError(t, err)
require.EqualValues(t, test.out, utils.NetAddrsToStrings(cfg.Proxy.PostgresPublicAddrs))
})
}
}
func TestBackendDefaults(t *testing.T) {

View file

@ -841,6 +841,12 @@ type Proxy struct {
// MySQLAddr is MySQL proxy listen address.
MySQLAddr string `yaml:"mysql_listen_addr,omitempty"`
// MySQLPublicAddr is the hostport the proxy advertises for MySQL
// client connections.
MySQLPublicAddr utils.Strings `yaml:"mysql_public_addr,omitempty"`
// PostgresPublicAddr is the hostport the proxy advertises for Postgres
// client connections.
PostgresPublicAddr utils.Strings `yaml:"postgres_public_addr,omitempty"`
}
// ACME configures ACME protocol - automatic X.509 certificates

View file

@ -158,6 +158,9 @@ proxy_service:
web_listen_addr: webhost
tunnel_listen_addr: tunnelhost:1001
public_addr: web3:443
postgres_public_addr: postgres.example:5432
mysql_listen_addr: webhost:3336
mysql_public_addr: mysql.example:3306
`
// NoServicesConfigString is a configuration file with no services enabled

View file

@ -361,6 +361,14 @@ type ProxyConfig struct {
// list of host principals on the TLS and SSH certificate.
TunnelPublicAddrs []utils.NetAddr
// PostgresPublicAddrs is a list of the public addresses the proxy
// advertises for Postgres clients.
PostgresPublicAddrs []utils.NetAddr
// MySQLPublicAddrs is a list of the public addresses the proxy
// advertises for MySQL clients.
MySQLPublicAddrs []utils.NetAddr
// Kube specifies kubernetes proxy configuration
Kube KubeProxyConfig

View file

@ -2099,6 +2099,8 @@ func (process *TeleportProcess) getAdditionalPrincipals(role teleport.Role) ([]s
)
addrs = append(addrs, process.Config.Proxy.SSHPublicAddrs...)
addrs = append(addrs, process.Config.Proxy.TunnelPublicAddrs...)
addrs = append(addrs, process.Config.Proxy.PostgresPublicAddrs...)
addrs = append(addrs, process.Config.Proxy.MySQLPublicAddrs...)
addrs = append(addrs, process.Config.Proxy.Kube.PublicAddrs...)
// Automatically add wildcards for every proxy public address for k8s SNI routing
if process.Config.Proxy.Kube.Enabled {
@ -2510,9 +2512,15 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error {
if len(cfg.Proxy.Kube.PublicAddrs) > 0 {
proxySettings.Kube.PublicAddr = cfg.Proxy.Kube.PublicAddrs[0].String()
}
if len(cfg.Proxy.PostgresPublicAddrs) > 0 {
proxySettings.DB.PostgresPublicAddr = cfg.Proxy.PostgresPublicAddrs[0].String()
}
if !cfg.Proxy.MySQLAddr.IsEmpty() {
proxySettings.DB.MySQLListenAddr = cfg.Proxy.MySQLAddr.String()
}
if len(cfg.Proxy.MySQLPublicAddrs) > 0 {
proxySettings.DB.MySQLPublicAddr = cfg.Proxy.MySQLPublicAddrs[0].String()
}
var fs http.FileSystem
if !process.Config.Proxy.DisableWebInterface {
fs, err = newHTTPFileSystem()

View file

@ -297,9 +297,11 @@ func TestGetAdditionalPrincipals(t *testing.T) {
HostUUID: "global-uuid",
AdvertiseIP: "1.2.3.4",
Proxy: ProxyConfig{
PublicAddrs: utils.MustParseAddrList("proxy-public-1", "proxy-public-2"),
SSHPublicAddrs: utils.MustParseAddrList("proxy-ssh-public-1", "proxy-ssh-public-2"),
TunnelPublicAddrs: utils.MustParseAddrList("proxy-tunnel-public-1", "proxy-tunnel-public-2"),
PublicAddrs: utils.MustParseAddrList("proxy-public-1", "proxy-public-2"),
SSHPublicAddrs: utils.MustParseAddrList("proxy-ssh-public-1", "proxy-ssh-public-2"),
TunnelPublicAddrs: utils.MustParseAddrList("proxy-tunnel-public-1", "proxy-tunnel-public-2"),
PostgresPublicAddrs: utils.MustParseAddrList("proxy-postgres-public-1", "proxy-postgres-public-2"),
MySQLPublicAddrs: utils.MustParseAddrList("proxy-mysql-public-1", "proxy-mysql-public-2"),
Kube: KubeProxyConfig{
Enabled: true,
PublicAddrs: utils.MustParseAddrList("proxy-kube-public-1", "proxy-kube-public-2"),
@ -335,6 +337,10 @@ func TestGetAdditionalPrincipals(t *testing.T) {
"proxy-ssh-public-2",
"proxy-tunnel-public-1",
"proxy-tunnel-public-2",
"proxy-postgres-public-1",
"proxy-postgres-public-2",
"proxy-mysql-public-1",
"proxy-mysql-public-2",
"proxy-kube-public-1",
"proxy-kube-public-2",
},

View file

@ -238,9 +238,15 @@ func onDatabaseConfig(cf *CLIConf) error {
}
// Postgres proxy listens on web proxy port while MySQL proxy listens on
// a separate port due to the specifics of the protocol.
host, port := tc.WebProxyHostPort()
if database.Protocol == defaults.ProtocolMySQL {
var host string
var port int
switch database.Protocol {
case defaults.ProtocolPostgres:
host, port = tc.PostgresProxyHostPort()
case defaults.ProtocolMySQL:
host, port = tc.MySQLProxyHostPort()
default:
return trace.BadParameter("unknown database protocol: %q", database)
}
fmt.Printf(`Name: %v
Host: %v