Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API client connection overhaul #5625

Merged
merged 28 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e4bf696
API client connection overhaul
Joerger Mar 6, 2021
4dd796c
Small tweaks.
Joerger Mar 6, 2021
07f07e4
Apply changes from code review; fix cltChan logic; Improve client.New…
Joerger Mar 10, 2021
1259daf
Add DialInBackground client.Config option which uses its own non-conc…
Joerger Mar 10, 2021
ab0b2bc
Add web client with Ping endpoint for tunnel addr discovery.
Joerger Mar 11, 2021
2025350
Fix bugs.
Joerger Mar 11, 2021
c576f45
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 11, 2021
d899756
Fix bugs and change Ping endpoint to insecure only.
Joerger Mar 12, 2021
32f8852
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 12, 2021
598463e
Update clt.go Client with new comments and background dialing.
Joerger Mar 12, 2021
172a6e6
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 12, 2021
46fc6a5
Resolve comments, clean up.
Joerger Mar 15, 2021
0cad81b
Merge branch 'joerger/api-proxy-dialer' of github.com:gravitational/t…
Joerger Mar 15, 2021
d769fec
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 15, 2021
c2781a2
Fix leaky goroutines.
Joerger Mar 16, 2021
9153d92
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 16, 2021
1dd1bc1
Resolve simple comments.
Joerger Mar 16, 2021
f56df44
Replace lib/client/weblogin Find with api/client Find, refactor surro…
Joerger Mar 16, 2021
88be61e
Remove NewAddrsDialer which does not work properly in gRPC; refactor …
Joerger Mar 17, 2021
1053488
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 17, 2021
3839edd
Fix background connection bug.
Joerger Mar 17, 2021
3f26775
Merge branch 'joerger/api-proxy-dialer' of github.com:gravitational/t…
Joerger Mar 17, 2021
077418a
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 17, 2021
ea5ccfc
Resolve comments; Move Ping to /api; Add load method to IdentityCreds.
Joerger Mar 19, 2021
d403ca4
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 19, 2021
0b091ce
Move sshutils under utils directory.
Joerger Mar 22, 2021
87546dd
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 22, 2021
3ca7ad3
Merge branch 'master' into joerger/api-proxy-dialer
Joerger Mar 23, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
346 changes: 243 additions & 103 deletions api/client/client.go

Large diffs are not rendered by default.

48 changes: 33 additions & 15 deletions api/client/contextdialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ import (
"net"
"time"

"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/utils/sshutils"

"github.com/gravitational/trace"
"golang.org/x/crypto/ssh"
)

// ContextDialer represents network dialer interface that uses context
Expand All @@ -38,23 +42,37 @@ func (f ContextDialerFunc) DialContext(ctx context.Context, network, addr string
return f(ctx, network, addr)
}

// NewAddrDialer makes a new dialer from a list of addresses
func NewAddrDialer(addrs []string, keepAliveInterval, dialTimeout time.Duration) (ContextDialer, error) {
if len(addrs) == 0 {
return nil, trace.BadParameter("no addreses to dial")
}
dialer := net.Dialer{
// NewDialer makes a new dialer.
func NewDialer(keepAliveInterval, dialTimeout time.Duration) ContextDialer {
return &net.Dialer{
Timeout: dialTimeout,
KeepAlive: keepAliveInterval,
}
return ContextDialerFunc(func(ctx context.Context, network, _ string) (conn net.Conn, err error) {
for _, addr := range addrs {
conn, err = dialer.DialContext(ctx, network, addr)
if err == nil {
return conn, nil
}
}

// NewTunnelDialer make a new ssh tunnel dialer
func NewTunnelDialer(ssh ssh.ClientConfig, keepAliveInterval, dialTimeout time.Duration) ContextDialer {
dialer := NewDialer(keepAliveInterval, dialTimeout)
return ContextDialerFunc(func(ctx context.Context, network, addr string) (conn net.Conn, err error) {
conn, err = dialer.DialContext(ctx, network, addr)
if err != nil {
return nil, trace.Wrap(err)
}

ssh.Timeout = dialTimeout
sconn, err := sshutils.NewClientConnWithDeadline(conn, addr, &ssh)
if err != nil {
return nil, trace.NewAggregate(err, conn.Close())
}

// Build a net.Conn over the tunnel. Make this an exclusive connection:
// close the net.Conn as well as the channel upon close.
conn, _, err = sshutils.ConnectProxyTransport(sconn.Conn, &sshutils.DialReq{
Address: constants.RemoteAuthServer,
}, true)
if err != nil {
return nil, trace.NewAggregate(err, sconn.Close())
}
// not wrapping on purpose to preserve the original error
return nil, err
}), nil
return conn, nil
})
}
68 changes: 55 additions & 13 deletions api/client/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,20 @@ import (
"io/ioutil"

"github.com/gravitational/teleport/api/constants"

"github.com/gravitational/trace"
"golang.org/x/crypto/ssh"
"golang.org/x/net/http2"
)

// Credentials are used to authenticate to Auth.
type Credentials interface {
// Dialer is used to dial a connection to Auth.
Dialer() (ContextDialer, error)
// Config returns TLS configuration used to connect to Auth.
Config() (*tls.Config, error)
// TLSConfig returns TLS configuration used to connect to Auth.
TLSConfig() (*tls.Config, error)
// SSHClientConfig returns SSH configuration used to connect to Proxy through tunnel.
SSHClientConfig() (*ssh.ClientConfig, error)
}

// LoadTLS is used to load credentials directly from another *tls.Config.
Expand All @@ -52,11 +56,19 @@ func (c *TLSConfigCreds) Dialer() (ContextDialer, error) {
return nil, trace.NotImplemented("no dialer")
}

// Config returns TLS configuration used to connect to Auth.
func (c *TLSConfigCreds) Config() (*tls.Config, error) {
// TLSConfig returns TLS configuration used to connect to Auth.
func (c *TLSConfigCreds) TLSConfig() (*tls.Config, error) {
if c.tlsConfig == nil {
return nil, trace.BadParameter("tls config is nil")
}
return configure(c.tlsConfig), nil
}

// SSHClientConfig returns SSH configuration used to connect to Proxy.
func (c *TLSConfigCreds) SSHClientConfig() (*ssh.ClientConfig, error) {
return nil, trace.NotImplemented("no ssh config")
}

// LoadKeyPair is used to load credentials from files on disk.
func LoadKeyPair(certFile string, keyFile string, caFile string) *KeyPairCreds {
return &KeyPairCreds{
Expand All @@ -79,8 +91,8 @@ func (c *KeyPairCreds) Dialer() (ContextDialer, error) {
return nil, trace.NotImplemented("no dialer")
}

// Config returns TLS configuration used to connect to Auth.
func (c *KeyPairCreds) Config() (*tls.Config, error) {
// TLSConfig returns TLS configuration used to connect to Auth.
func (c *KeyPairCreds) TLSConfig() (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(c.certFile, c.keyFile)
if err != nil {
return nil, trace.Wrap(err)
Expand All @@ -102,6 +114,11 @@ func (c *KeyPairCreds) Config() (*tls.Config, error) {
}), nil
}

// SSHClientConfig returns SSH configuration used to connect to Proxy.
func (c *KeyPairCreds) SSHClientConfig() (*ssh.ClientConfig, error) {
return nil, trace.NotImplemented("no ssh config")
}

// LoadIdentityFile is used to load credentials from an identity file on disk.
func LoadIdentityFile(path string) *IdentityCreds {
return &IdentityCreds{
Expand All @@ -112,29 +129,54 @@ func LoadIdentityFile(path string) *IdentityCreds {
// IdentityCreds are used to authenticate the client
// with an identity file generated in the given file path.
type IdentityCreds struct {
path string
path string
identityFile *IdentityFile
}

// Dialer is used to dial a connection to Auth.
func (c *IdentityCreds) Dialer() (ContextDialer, error) {
return nil, trace.NotImplemented("no dialer")
}

// Config returns TLS configuration used to connect to Auth.
func (c *IdentityCreds) Config() (*tls.Config, error) {
identityFile, err := ReadIdentityFile(c.path)
if err != nil {
return nil, trace.BadParameter("identity file could not be decoded: %v", err)
// TLSConfig returns TLS configuration used to connect to Auth.
func (c *IdentityCreds) TLSConfig() (*tls.Config, error) {
if err := c.load(); err != nil {
return nil, trace.Wrap(err)
}

tlsConfig, err := identityFile.TLS()
tlsConfig, err := c.identityFile.TLSConfig()
if err != nil {
return nil, trace.Wrap(err)
}

return configure(tlsConfig), nil
}

// SSHClientConfig returns SSH configuration used to connect to Proxy.
func (c *IdentityCreds) SSHClientConfig() (*ssh.ClientConfig, error) {
if err := c.load(); err != nil {
return nil, trace.Wrap(err)
}

sshConfig, err := c.identityFile.SSHClientConfig()
if err != nil {
return nil, trace.Wrap(err)
}

return sshConfig, nil
}

func (c *IdentityCreds) load() error {
if c.identityFile != nil {
return nil
}
var err error
if c.identityFile, err = ReadIdentityFile(c.path); err != nil {
return trace.BadParameter("identity file could not be decoded: %v", err)
}
return nil
}

func configure(c *tls.Config) *tls.Config {
tlsConfig := c.Clone()

Expand Down
Loading