mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 09:44:51 +00:00
Fix tctl insecure flag when TLS Routing is enabled (#10297)
This commit is contained in:
parent
9039b71ca3
commit
84b64fe487
|
@ -278,7 +278,10 @@ func (a *Agent) connect() (conn *ssh.Client, err error) {
|
|||
a.reverseTunnelDetails = a.getReverseTunnelDetails()
|
||||
}
|
||||
|
||||
var opts []proxy.DialerOptionFunc
|
||||
opts := []proxy.DialerOptionFunc{
|
||||
proxy.WithInsecureSkipTLSVerify(lib.IsInsecureDevMode()),
|
||||
}
|
||||
|
||||
if a.reverseTunnelDetails != nil && a.reverseTunnelDetails.TLSRoutingEnabled {
|
||||
opts = append(opts, proxy.WithALPNDialer())
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import (
|
|||
apidefaults "github.com/gravitational/teleport/api/defaults"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/api/utils/sshutils"
|
||||
"github.com/gravitational/teleport/lib"
|
||||
"github.com/gravitational/teleport/lib/auth"
|
||||
"github.com/gravitational/teleport/lib/events"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
@ -61,6 +60,8 @@ type TunnelAuthDialerConfig struct {
|
|||
ClientConfig *ssh.ClientConfig
|
||||
// Log is used for logging.
|
||||
Log logrus.FieldLogger
|
||||
// InsecureSkipTLSVerify is whether to skip certificate validation.
|
||||
InsecureSkipTLSVerify bool
|
||||
}
|
||||
|
||||
func (c *TunnelAuthDialerConfig) CheckAndSetDefaults() error {
|
||||
|
@ -79,7 +80,9 @@ type TunnelAuthDialer struct {
|
|||
// DialContext dials auth server via SSH tunnel
|
||||
func (t *TunnelAuthDialer) DialContext(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
// Connect to the reverse tunnel server.
|
||||
var opts []proxy.DialerOptionFunc
|
||||
opts := []proxy.DialerOptionFunc{
|
||||
proxy.WithInsecureSkipTLSVerify(t.InsecureSkipTLSVerify),
|
||||
}
|
||||
|
||||
addr, err := t.Resolver()
|
||||
if err != nil {
|
||||
|
@ -88,7 +91,7 @@ func (t *TunnelAuthDialer) DialContext(ctx context.Context, _, _ string) (net.Co
|
|||
}
|
||||
|
||||
// Check if t.ProxyAddr is ProxyWebPort and remote Proxy supports TLS ALPNSNIListener.
|
||||
resp, err := webclient.Find(ctx, addr.Addr, lib.IsInsecureDevMode(), nil)
|
||||
resp, err := webclient.Find(ctx, addr.Addr, t.InsecureSkipTLSVerify, nil)
|
||||
if err != nil {
|
||||
// If TLS Routing is disabled the address is the proxy reverse tunnel
|
||||
// address thus the ping call will always fail.
|
||||
|
|
|
@ -23,9 +23,11 @@ import (
|
|||
|
||||
"github.com/coreos/go-semver/semver"
|
||||
"github.com/gravitational/roundtrip"
|
||||
"github.com/gravitational/teleport"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/gravitational/teleport"
|
||||
apiclient "github.com/gravitational/teleport/api/client"
|
||||
"github.com/gravitational/teleport/api/client/proto"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
|
@ -37,10 +39,6 @@ import (
|
|||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
"github.com/gravitational/teleport/lib/utils/interval"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// reconnectToAuthService continuously attempts to reconnect to the auth
|
||||
|
@ -890,9 +888,10 @@ func (process *TeleportProcess) newClientThroughTunnel(authServers []utils.NetAd
|
|||
}
|
||||
|
||||
dialer, err := reversetunnel.NewTunnelAuthDialer(reversetunnel.TunnelAuthDialerConfig{
|
||||
Resolver: resolver,
|
||||
ClientConfig: sshConfig,
|
||||
Log: process.log,
|
||||
Resolver: resolver,
|
||||
ClientConfig: sshConfig,
|
||||
Log: process.log,
|
||||
InsecureSkipTLSVerify: lib.IsInsecureDevMode(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
|
|
@ -52,7 +52,7 @@ type LocalProxyConfig struct {
|
|||
RemoteProxyAddr string
|
||||
// Protocol set for the upstream TLS connection.
|
||||
Protocol common.Protocol
|
||||
// Insecure turns off verification for x509 upstream ALPN proxy service certificate.
|
||||
// InsecureSkipTLSVerify turns off verification for x509 upstream ALPN proxy service certificate.
|
||||
InsecureSkipVerify bool
|
||||
// Listener is listener running on local machine.
|
||||
Listener net.Listener
|
||||
|
|
|
@ -30,7 +30,6 @@ import (
|
|||
|
||||
"github.com/gravitational/teleport"
|
||||
"github.com/gravitational/teleport/api/utils/sshutils"
|
||||
"github.com/gravitational/teleport/lib"
|
||||
alpncommon "github.com/gravitational/teleport/lib/srv/alpnproxy/common"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
|
@ -57,7 +56,7 @@ func dialWithDeadline(network string, addr string, config *ssh.ClientConfig) (*s
|
|||
// dialALPNWithDeadline allows connecting to Teleport in single-port mode. SSH protocol is wrapped into
|
||||
// TLS connection where TLS ALPN protocol is set to ProtocolReverseTunnel allowing ALPN Proxy to route the
|
||||
// incoming connection to ReverseTunnel proxy service.
|
||||
func dialALPNWithDeadline(network string, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
|
||||
func dialALPNWithDeadline(network string, addr string, config *ssh.ClientConfig, insecure bool) (*ssh.Client, error) {
|
||||
dialer := &net.Dialer{
|
||||
Timeout: config.Timeout,
|
||||
}
|
||||
|
@ -67,7 +66,7 @@ func dialALPNWithDeadline(network string, addr string, config *ssh.ClientConfig)
|
|||
}
|
||||
tlsConn, err := tls.DialWithDialer(dialer, network, addr, &tls.Config{
|
||||
NextProtos: []string{string(alpncommon.ProtocolReverseTunnel)},
|
||||
InsecureSkipVerify: lib.IsInsecureDevMode(),
|
||||
InsecureSkipVerify: insecure,
|
||||
ServerName: address.Host(),
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -86,13 +85,16 @@ type Dialer interface {
|
|||
}
|
||||
|
||||
type directDial struct {
|
||||
useTLS bool
|
||||
// tlsRoutingEnabled indicates that proxy is running in TLSRouting mode.
|
||||
tlsRoutingEnabled bool
|
||||
// insecure is whether to skip certificate validation.
|
||||
insecure bool
|
||||
}
|
||||
|
||||
// Dial calls ssh.Dial directly.
|
||||
func (d directDial) Dial(network string, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
|
||||
if d.useTLS {
|
||||
client, err := dialALPNWithDeadline(network, addr, config)
|
||||
if d.tlsRoutingEnabled {
|
||||
client, err := dialALPNWithDeadline(network, addr, config, d.insecure)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
@ -107,14 +109,14 @@ func (d directDial) Dial(network string, addr string, config *ssh.ClientConfig)
|
|||
|
||||
// DialTimeout acts like Dial but takes a timeout.
|
||||
func (d directDial) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
|
||||
if d.useTLS {
|
||||
if d.tlsRoutingEnabled {
|
||||
addr, err := utils.ParseAddr(address)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
tlsConn, err := tls.Dial("tcp", address, &tls.Config{
|
||||
NextProtos: []string{string(alpncommon.ProtocolReverseTunnel)},
|
||||
InsecureSkipVerify: lib.IsInsecureDevMode(),
|
||||
InsecureSkipVerify: d.insecure,
|
||||
ServerName: addr.Host(),
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -130,8 +132,12 @@ func (d directDial) DialTimeout(network, address string, timeout time.Duration)
|
|||
}
|
||||
|
||||
type proxyDial struct {
|
||||
// proxyHost is the HTTPS proxy address.
|
||||
proxyHost string
|
||||
useTLS bool
|
||||
// tlsRoutingEnabled indicates that proxy is running in TLSRouting mode.
|
||||
tlsRoutingEnabled bool
|
||||
// insecure is whether to skip certificate validation.
|
||||
insecure bool
|
||||
}
|
||||
|
||||
// DialTimeout acts like Dial but takes a timeout.
|
||||
|
@ -147,14 +153,14 @@ func (d proxyDial) DialTimeout(network, address string, timeout time.Duration) (
|
|||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if d.useTLS {
|
||||
if d.tlsRoutingEnabled {
|
||||
address, err := utils.ParseAddr(address)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
conn = tls.Client(conn, &tls.Config{
|
||||
NextProtos: []string{string(alpncommon.ProtocolReverseTunnel)},
|
||||
InsecureSkipVerify: lib.IsInsecureDevMode(),
|
||||
InsecureSkipVerify: d.insecure,
|
||||
ServerName: address.Host(),
|
||||
})
|
||||
}
|
||||
|
@ -172,14 +178,14 @@ func (d proxyDial) Dial(network string, addr string, config *ssh.ClientConfig) (
|
|||
if config.Timeout > 0 {
|
||||
pconn.SetReadDeadline(time.Now().Add(config.Timeout))
|
||||
}
|
||||
if d.useTLS {
|
||||
if d.tlsRoutingEnabled {
|
||||
address, err := utils.ParseAddr(addr)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
pconn = tls.Client(pconn, &tls.Config{
|
||||
NextProtos: []string{string(alpncommon.ProtocolReverseTunnel)},
|
||||
InsecureSkipVerify: lib.IsInsecureDevMode(),
|
||||
InsecureSkipVerify: d.insecure,
|
||||
ServerName: address.Host(),
|
||||
})
|
||||
}
|
||||
|
@ -196,7 +202,10 @@ func (d proxyDial) Dial(network string, addr string, config *ssh.ClientConfig) (
|
|||
}
|
||||
|
||||
type dialerOptions struct {
|
||||
dialTLS bool
|
||||
// tlsRoutingEnabled indicates that proxy is running in TLSRouting mode.
|
||||
tlsRoutingEnabled bool
|
||||
// insecureSkipTLSVerify is whether to skip certificate validation.
|
||||
insecureSkipTLSVerify bool
|
||||
}
|
||||
|
||||
// DialerOptionFunc allows setting options as functional arguments to DialerFromEnvironment
|
||||
|
@ -205,7 +214,14 @@ type DialerOptionFunc func(options *dialerOptions)
|
|||
// WithALPNDialer creates a dialer that allows to Teleport running in single-port mode.
|
||||
func WithALPNDialer() DialerOptionFunc {
|
||||
return func(options *dialerOptions) {
|
||||
options.dialTLS = true
|
||||
options.tlsRoutingEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithInsecureSkipTLSVerify skips the certs verifications.
|
||||
func WithInsecureSkipTLSVerify(insecure bool) DialerOptionFunc {
|
||||
return func(options *dialerOptions) {
|
||||
options.insecureSkipTLSVerify = insecure
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,10 +242,17 @@ func DialerFromEnvironment(addr string, opts ...DialerOptionFunc) Dialer {
|
|||
// otherwise return a proxy dialer.
|
||||
if proxyAddr == "" {
|
||||
log.Debugf("No proxy set in environment, returning direct dialer.")
|
||||
return directDial{useTLS: options.dialTLS}
|
||||
return directDial{
|
||||
tlsRoutingEnabled: options.tlsRoutingEnabled,
|
||||
insecure: options.insecureSkipTLSVerify,
|
||||
}
|
||||
}
|
||||
log.Debugf("Found proxy %q in environment, returning proxy dialer.", proxyAddr)
|
||||
return proxyDial{proxyHost: proxyAddr, useTLS: options.dialTLS}
|
||||
return proxyDial{
|
||||
proxyHost: proxyAddr,
|
||||
tlsRoutingEnabled: options.tlsRoutingEnabled,
|
||||
insecure: options.insecureSkipTLSVerify,
|
||||
}
|
||||
}
|
||||
|
||||
type DirectDialerOptFunc func(dial *directDial)
|
||||
|
|
|
@ -19,6 +19,7 @@ package common
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
@ -37,7 +38,30 @@ import (
|
|||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func runResourceCommand(t *testing.T, fc *config.FileConfig, args []string) (*bytes.Buffer, error) {
|
||||
type options struct {
|
||||
CertPool *x509.CertPool
|
||||
Insecure bool
|
||||
}
|
||||
|
||||
type optionsFunc func(o *options)
|
||||
|
||||
func withRootCertPool(pool *x509.CertPool) optionsFunc {
|
||||
return func(o *options) {
|
||||
o.CertPool = pool
|
||||
}
|
||||
}
|
||||
|
||||
func withInsecure(insecure bool) optionsFunc {
|
||||
return func(o *options) {
|
||||
o.Insecure = insecure
|
||||
}
|
||||
}
|
||||
|
||||
func runResourceCommand(t *testing.T, fc *config.FileConfig, args []string, opts ...optionsFunc) (*bytes.Buffer, error) {
|
||||
var options options
|
||||
for _, v := range opts {
|
||||
v(&options)
|
||||
}
|
||||
var stdoutBuff bytes.Buffer
|
||||
command := &ResourceCommand{
|
||||
stdout: &stdoutBuff,
|
||||
|
@ -52,10 +76,15 @@ func runResourceCommand(t *testing.T, fc *config.FileConfig, args []string) (*by
|
|||
|
||||
var ccf GlobalCLIFlags
|
||||
ccf.ConfigString = mustGetBase64EncFileConfig(t, fc)
|
||||
ccf.Insecure = options.Insecure
|
||||
|
||||
clientConfig, err := applyConfig(&ccf, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
if options.CertPool != nil {
|
||||
clientConfig.TLS.RootCAs = options.CertPool
|
||||
}
|
||||
|
||||
client, err := connectToAuthService(context.Background(), cfg, clientConfig)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package common
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
|
@ -284,6 +285,47 @@ func TestAppResource(t *testing.T) {
|
|||
))
|
||||
}
|
||||
|
||||
// TestCreateDatabaseInInsecureMode connects to auth server with --insecure mode and creates a DB resource.
|
||||
func TestCreateDatabaseInInsecureMode(t *testing.T) {
|
||||
fileConfig := &config.FileConfig{
|
||||
Global: config.Global{
|
||||
DataDir: t.TempDir(),
|
||||
},
|
||||
Databases: config.Databases{
|
||||
Service: config.Service{
|
||||
EnabledFlag: "true",
|
||||
},
|
||||
},
|
||||
Proxy: config.Proxy{
|
||||
Service: config.Service{
|
||||
EnabledFlag: "true",
|
||||
},
|
||||
WebAddr: mustGetFreeLocalListenerAddr(t),
|
||||
TunAddr: mustGetFreeLocalListenerAddr(t),
|
||||
},
|
||||
Auth: config.Auth{
|
||||
Service: config.Service{
|
||||
EnabledFlag: "true",
|
||||
ListenAddress: mustGetFreeLocalListenerAddr(t),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
makeAndRunTestAuthServer(t, withFileConfig(fileConfig))
|
||||
|
||||
// Create the databases yaml file.
|
||||
dbYAMLPath := filepath.Join(t.TempDir(), "db.yaml")
|
||||
require.NoError(t, ioutil.WriteFile(dbYAMLPath, []byte(dbYAML), 0644))
|
||||
|
||||
// Reset RootCertPool and run tctl command with --insecure flag.
|
||||
opts := []optionsFunc{
|
||||
withRootCertPool(x509.NewCertPool()),
|
||||
withInsecure(true),
|
||||
}
|
||||
_, err := runResourceCommand(t, fileConfig, []string{"create", dbYAMLPath}, opts...)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
const (
|
||||
dbYAML = `kind: db
|
||||
version: v3
|
||||
|
|
|
@ -226,9 +226,10 @@ func connectToAuthService(ctx context.Context, cfg *service.Config, clientConfig
|
|||
// reversetunnel.TunnelAuthDialer will take care of creating a net.Conn
|
||||
// within an SSH tunnel.
|
||||
dialer, err := reversetunnel.NewTunnelAuthDialer(reversetunnel.TunnelAuthDialerConfig{
|
||||
Resolver: reversetunnel.WebClientResolver(ctx, cfg.AuthServers, clientConfig.TLS.InsecureSkipVerify),
|
||||
ClientConfig: clientConfig.SSH,
|
||||
Log: cfg.Log,
|
||||
Resolver: reversetunnel.WebClientResolver(ctx, cfg.AuthServers, clientConfig.TLS.InsecureSkipVerify),
|
||||
ClientConfig: clientConfig.SSH,
|
||||
Log: cfg.Log,
|
||||
InsecureSkipTLSVerify: clientConfig.TLS.InsecureSkipVerify,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
|
Loading…
Reference in a new issue