Skip to content

Commit

Permalink
refactor remote access point creation
Browse files Browse the repository at this point in the history
  • Loading branch information
rosstimothy committed Apr 25, 2022
1 parent d12095f commit ac35e46
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 38 deletions.
11 changes: 6 additions & 5 deletions lib/reversetunnel/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,16 +354,17 @@ func (a *Agent) handleGlobalRequests(ctx context.Context, requestCh <-chan *ssh.

switch r.Type {
case versionRequest:
version := teleport.Version

// reply with the auth server version
pong, err := a.Client.Ping(ctx)
if err != nil {
a.log.WithError(err).Debugf("Failed to ping auth server.")
} else {
version = pong.ServerVersion
if err := r.Reply(false, []byte("Failed to retrieve auth version")); err != nil {
a.log.Debugf("Failed to reply to %version request: %v.", err)
continue
}
}

if err := r.Reply(true, []byte(version)); err != nil {
if err := r.Reply(true, []byte(pong.ServerVersion)); err != nil {
a.log.WithError(err).Debugf("Failed to reply to version request")
continue
}
Expand Down
55 changes: 22 additions & 33 deletions lib/reversetunnel/srv.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ import (
"github.com/gravitational/teleport/lib/sshca"
"github.com/gravitational/teleport/lib/sshutils"
"github.com/gravitational/teleport/lib/utils"

"github.com/coreos/go-semver/semver"
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -1062,25 +1060,12 @@ func newRemoteSite(srv *server, domainName string, sconn ssh.Conn) (*remoteSite,
}
remoteSite.remoteClient = clt

// Check if the cluster that is connecting is a pre-v8 cluster. If it is,
// don't assume the newer organization of cluster configuration resources
// (RFD 28) because older proxy servers will reject that causing the cache
// to go into a re-sync loop.
var accessPointFunc auth.NewRemoteProxyCachingAccessPoint
ok, version, err := isPreV8Cluster(closeContext, sconn)
remoteVersion, err := getRemoteAuthVersion(closeContext, sconn)
if err != nil {
return nil, trace.Wrap(err)
}
if ok {
srv.log.Debugf("cluster %q running %q connecting, loading old cache policy.", domainName, version)
accessPointFunc = srv.Config.NewCachingAccessPointOldProxy
} else {
accessPointFunc = srv.newAccessPoint
}

// Configure access to the cached subset of the Auth Server API of the remote
// cluster this remote site provides access to.
accessPoint, err := accessPointFunc(clt, []string{"reverse", domainName})
accessPoint, err := createRemoteAccessPoint(srv, clt, remoteVersion, domainName)
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down Expand Up @@ -1125,31 +1110,35 @@ func newRemoteSite(srv *server, domainName string, sconn ssh.Conn) (*remoteSite,
return remoteSite, nil
}

// isPreV8Cluster checks if the cluster is older than 8.0.0.
func isPreV8Cluster(ctx context.Context, conn ssh.Conn) (bool, string, error) {
version, err := sendVersionRequest(ctx, conn)
// createRemoteAccessPoint creates a new access point for the remote cluster.
// Checks if the cluster that is connecting is a pre-v8 cluster. If it is,
// don't assume the newer organization of cluster configuration resources
// (RFD 28) because older proxy servers will reject that causing the cache
// to go into a re-sync loop.
func createRemoteAccessPoint(srv *server, clt auth.ClientI, version, domainName string) (auth.RemoteProxyAccessPoint, error) {
ok, err := utils.MinVerWithoutPreRelease(version, utils.VersionBeforeAlpha("8.0.0"))
if err != nil {
return false, "", trace.Wrap(err)
return nil, trace.Wrap(err)
}

remoteClusterVersion, err := semver.NewVersion(version)
if err != nil {
return false, "", trace.Wrap(err)
accessPointFunc := srv.Config.NewCachingAccessPoint
if !ok {
srv.log.Debugf("cluster %q running %q is connecting, loading old cache policy.", domainName, version)
accessPointFunc = srv.Config.NewCachingAccessPointOldProxy
}
minClusterVersion, err := semver.NewVersion(utils.VersionBeforeAlpha("8.0.0"))

// Configure access to the cached subset of the Auth Server API of the remote
// cluster this remote site provides access to.
accessPoint, err := accessPointFunc(clt, []string{"reverse", domainName})
if err != nil {
return false, "", trace.Wrap(err)
}
// Return true if the version is older than 8.0.0
if remoteClusterVersion.LessThan(*minClusterVersion) {
return true, version, nil
return nil, trace.Wrap(err)
}

return false, version, nil
return accessPoint, nil
}

// sendVersionRequest sends a request for the version remote Teleport cluster.
func sendVersionRequest(ctx context.Context, sconn ssh.Conn) (string, error) {
// getRemoteAuthVersion sends a version request to the remote agent.
func getRemoteAuthVersion(ctx context.Context, sconn ssh.Conn) (string, error) {
errorCh := make(chan error, 1)
versionCh := make(chan string, 1)

Expand Down
68 changes: 68 additions & 0 deletions lib/reversetunnel/srv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package reversetunnel

import (
"context"
"errors"
"net"
"testing"
"time"
Expand Down Expand Up @@ -159,3 +160,70 @@ type mockAccessPoint struct {
func (ap mockAccessPoint) GetCertAuthority(ctx context.Context, id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) {
return ap.ca, nil
}

func TestCreateRemoteAccessPoint(t *testing.T) {
cases := []struct {
name string
version string
assertion require.ErrorAssertionFunc
oldRemoteProxy bool
}{
{
name: "invalid version",
assertion: require.Error,
},
{
name: "remote running 9.0.0",
assertion: require.NoError,
version: "9.0.0",
},
{
name: "remote running 8.0.0",
assertion: require.NoError,
version: "8.0.0",
},
{
name: "remote running 7.0.0",
assertion: require.NoError,
version: "7.0.0",
oldRemoteProxy: true,
},
{
name: "remote running 6.0.0",
assertion: require.NoError,
version: "6.0.0",
oldRemoteProxy: true,
},
}

for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
newProxyFn := func(clt auth.ClientI, cacheName []string) (auth.RemoteProxyAccessPoint, error) {
if tt.oldRemoteProxy {
return nil, errors.New("expected to create an old remote proxy")
}

return nil, nil
}

oldProxyFn := func(clt auth.ClientI, cacheName []string) (auth.RemoteProxyAccessPoint, error) {
if !tt.oldRemoteProxy {
return nil, errors.New("expected to create an new remote proxy")
}

return nil, nil
}

clt := &mockAuthClient{}
srv := &server{
log: utils.NewLoggerForTests(),
Config: Config{
NewCachingAccessPoint: newProxyFn,
NewCachingAccessPointOldProxy: oldProxyFn,
},
}
_, err := createRemoteAccessPoint(srv, clt, tt.version, "test")
tt.assertion(t, err)
})
}
}

0 comments on commit ac35e46

Please sign in to comment.