mirror of
https://github.com/gravitational/teleport
synced 2024-10-19 08:43:58 +00:00
Adding postgres_public_addr and mysql_public_addr (#6426)
This commit is contained in:
parent
7ff9d9d5d6
commit
d67e11ff2d
|
@ -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.
|
||||
|
|
|
@ -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"`
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
142
lib/client/db/profile_test.go
Normal file
142
lib/client/db/profile_test.go
Normal 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
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue