Skip to content

Commit

Permalink
Merge branch 'master' into trent/disable-port-forwarding
Browse files Browse the repository at this point in the history
  • Loading branch information
tcsc authored Jun 1, 2021
2 parents 58ace74 + 4ac06ba commit 164cf7b
Show file tree
Hide file tree
Showing 18 changed files with 424 additions and 88 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ rpm:
mkdir -p $(BUILDDIR)/
cp ./build.assets/build-package.sh $(BUILDDIR)/
chmod +x $(BUILDDIR)/build-package.sh
cp -a ./build.assets/rpm $(BUILDDIR)/
cp -a ./build.assets/rpm-sign $(BUILDDIR)/
cd $(BUILDDIR) && ./build-package.sh -t oss -v $(VERSION) -p rpm -a $(ARCH) $(RUNTIME_SECTION) $(TARBALL_PATH_SECTION)
if [ -f e/Makefile ]; then $(MAKE) -C e rpm; fi
Expand Down
9 changes: 6 additions & 3 deletions build.assets/build-package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ LINUX_CONFIG_DIR=/etc
LINUX_DATA_DIR=/var/lib/teleport

# extra package information for linux
MAINTAINER="info@gravitational.com"
MAINTAINER="info@goteleport.com"
LICENSE="Apache-2.0"
VENDOR="Gravitational"
DESCRIPTION="Gravitational Teleport is a gateway for managing access to clusters of Linux servers via SSH or the Kubernetes API"
DOCS_URL="https://gravitational.com/teleport/docs"
DESCRIPTION="Teleport is a gateway for managing access to clusters of Linux servers via SSH or the Kubernetes API"
DOCS_URL="https://goteleport.com/docs"

# signing IDs to use for mac (must be pre-loaded into the keychain on the build box)
DEVELOPER_ID_APPLICATION="Developer ID Application: Gravitational Inc." # used for signing binaries
Expand Down Expand Up @@ -249,6 +249,8 @@ else
if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
OUTPUT_FILENAME="${TAR_PATH}-${TELEPORT_VERSION}-1${OPTIONAL_RUNTIME_SECTION}.${ARCH}.rpm"
FILE_PERMISSIONS_STANZA="--rpm-user root --rpm-group root --rpm-use-file-permissions "
# the rpm/rpmmacros file suppresses the creation of .build-id files (see https://github.com/gravitational/teleport/issues/7040)
EXTRA_DOCKER_OPTIONS="-v $(pwd)/rpm/rpmmacros:/root/.rpmmacros"
# if we set this environment variable, don't sign RPMs (can be useful for building test RPMs
# without having the signing keys)
if [ "${UNSIGNED_RPM}" == "true" ]; then
Expand All @@ -257,6 +259,7 @@ else
# the GNUPG_DIR location here is assumed to contain a complete ~/.gnupg directory structure
# with pubring.kbx and trustdb.gpg files, plus a private-keys-v1.d directory with signing keys
# it needs to contain the "Gravitational, Inc" private key and signing key.
# we also use the rpm-sign/rpmmacros file instead which contains extra directives used for signing.
EXTRA_DOCKER_OPTIONS="-v $(pwd)/rpm-sign/rpmmacros:/root/.rpmmacros -v $(pwd)/rpm-sign/popt-override:/etc/popt.d/rpmsign-override -v ${GNUPG_DIR}:/root/.gnupg"
RPM_SIGN_STANZA="--rpm-sign"
fi
Expand Down
4 changes: 3 additions & 1 deletion build.assets/rpm-sign/rpmmacros
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
%_gpgbin /usr/bin/gpg
%_gpg_pass -
# Use SHA512 to sign RPMs
%__gpg_sign_cmd %{__gpg} gpg --no-verbose --no-armor --batch --pinentry-mode loopback --passphrase '' --no-secmem-warning -u "%{_gpg_name}" --digest-algo sha512 -sbo %{__signature_filename} %{__plaintext_filename}
%__gpg_sign_cmd %{__gpg} gpg --no-verbose --no-armor --batch --pinentry-mode loopback --passphrase '' --no-secmem-warning -u "%{_gpg_name}" --digest-algo sha512 -sbo %{__signature_filename} %{__plaintext_filename}
# Don't include build-id artifacts
%_build_id_links none
2 changes: 2 additions & 0 deletions build.assets/rpm/rpmmacros
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Don't include build-id artifacts
%_build_id_links none
90 changes: 88 additions & 2 deletions integration/db_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import (
"github.com/gravitational/teleport/lib/utils/testlog"

"github.com/jackc/pgconn"
"github.com/jonboulle/clockwork"
"github.com/pborman/uuid"
"github.com/siddontang/go-mysql/client"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -175,9 +177,88 @@ func TestDatabaseAccessMySQLLeafCluster(t *testing.T) {
require.NoError(t, err)
}

// TestRootLeafIdleTimeout tests idle client connection termination by proxy and DB services in
// trusted cluster setup.
func TestRootLeafIdleTimeout(t *testing.T) {
pack := setupDatabaseTest(t)
pack.waitForLeaf(t)

var (
rootAuthServer = pack.root.cluster.Process.GetAuthServer()
rootRole = pack.root.role
leafAuthServer = pack.leaf.cluster.Process.GetAuthServer()
leafRole = pack.leaf.role

idleTimeout = time.Minute
)

mkMySQLLeafDBClient := func(t *testing.T) *client.Conn {
// Connect to the database service in leaf cluster via root cluster.
client, err := mysql.MakeTestClient(common.TestClientConfig{
AuthClient: pack.root.cluster.GetSiteAPI(pack.root.cluster.Secrets.SiteName),
AuthServer: pack.root.cluster.Process.GetAuthServer(),
Address: net.JoinHostPort(Loopback, pack.root.cluster.GetPortMySQL()), // Connecting via root cluster.
Cluster: pack.leaf.cluster.Secrets.SiteName,
Username: pack.root.user.GetName(),
RouteToDatabase: tlsca.RouteToDatabase{
ServiceName: pack.leaf.mysqlService.Name,
Protocol: pack.leaf.mysqlService.Protocol,
Username: "root",
},
})
require.NoError(t, err)
return client
}

t.Run("root role without idle timeout", func(t *testing.T) {
client := mkMySQLLeafDBClient(t)
_, err := client.Execute("select 1")
require.NoError(t, err)

pack.clock.Advance(idleTimeout)
_, err = client.Execute("select 1")
require.NoError(t, err)
err = client.Close()
require.NoError(t, err)
})

t.Run("root role with idle timeout", func(t *testing.T) {
setRoleIdleTimeout(t, rootAuthServer, rootRole, idleTimeout)
client := mkMySQLLeafDBClient(t)
_, err := client.Execute("select 1")
require.NoError(t, err)

pack.clock.Advance(idleTimeout)
_, err = client.Execute("select 1")
require.Error(t, err)
setRoleIdleTimeout(t, rootAuthServer, rootRole, time.Hour)
})

t.Run("leaf role with idle timeout", func(t *testing.T) {
setRoleIdleTimeout(t, leafAuthServer, leafRole, idleTimeout)
client := mkMySQLLeafDBClient(t)
_, err := client.Execute("select 1")
require.NoError(t, err)

pack.clock.Advance(idleTimeout)
_, err = client.Execute("select 1")
require.Error(t, err)
setRoleIdleTimeout(t, leafAuthServer, leafRole, time.Hour)
})
}

func setRoleIdleTimeout(t *testing.T, authServer *auth.Server, role services.Role, idleTimout time.Duration) {
opts := role.GetOptions()
opts.ClientIdleTimeout = services.Duration(idleTimout)
role.SetOptions(opts)
err := authServer.UpsertRole(context.Background(), role)
require.NoError(t, err)
}

type databasePack struct {
root databaseClusterPack
leaf databaseClusterPack
root databaseClusterPack
leaf databaseClusterPack
clock clockwork.FakeClock
}

type databaseClusterPack struct {
Expand Down Expand Up @@ -207,6 +288,7 @@ func setupDatabaseTest(t *testing.T) *databasePack {
require.NoError(t, err)

p := &databasePack{
clock: clockwork.NewFakeClockAt(time.Now()),
root: databaseClusterPack{
postgresAddr: net.JoinHostPort("localhost", ports.Pop()),
mysqlAddr: net.JoinHostPort("localhost", ports.Pop()),
Expand Down Expand Up @@ -246,6 +328,7 @@ func setupDatabaseTest(t *testing.T) *databasePack {
rcConf.Auth.Preference.SetSecondFactor("off")
rcConf.Proxy.Enabled = true
rcConf.Proxy.DisableWebInterface = true
rcConf.Clock = p.clock

// Make leaf cluster config.
lcConf := service.MakeDefaultConfig()
Expand All @@ -254,6 +337,7 @@ func setupDatabaseTest(t *testing.T) *databasePack {
lcConf.Auth.Preference.SetSecondFactor("off")
lcConf.Proxy.Enabled = true
lcConf.Proxy.DisableWebInterface = true
lcConf.Clock = p.clock

// Establish trust b/w root and leaf.
err = p.root.cluster.CreateEx(p.leaf.cluster.Secrets.AsSlice(), rcConf)
Expand Down Expand Up @@ -311,6 +395,7 @@ func setupDatabaseTest(t *testing.T) *databasePack {
}
rdConf.Databases.Enabled = true
rdConf.Databases.Databases = []service.Database{p.root.postgresService, p.root.mysqlService}
rdConf.Clock = p.clock
p.root.dbProcess, p.root.dbAuthClient, err = p.root.cluster.StartDatabase(rdConf)
require.NoError(t, err)
t.Cleanup(func() {
Expand Down Expand Up @@ -339,6 +424,7 @@ func setupDatabaseTest(t *testing.T) *databasePack {
}
ldConf.Databases.Enabled = true
ldConf.Databases.Databases = []service.Database{p.leaf.postgresService, p.leaf.mysqlService}
ldConf.Clock = p.clock
p.leaf.dbProcess, p.leaf.dbAuthClient, err = p.leaf.cluster.StartDatabase(ldConf)
require.NoError(t, err)
t.Cleanup(func() {
Expand Down
2 changes: 1 addition & 1 deletion lib/events/dynamoevents/dynamoevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ func (l *Log) uploadBatch(writeRequests []*dynamodb.WriteRequest) error {
return trace.Wrap(err)
}

writeRequests := out.UnprocessedItems[l.Tablename]
writeRequests = out.UnprocessedItems[l.Tablename]
if len(writeRequests) == 0 {
return nil
}
Expand Down
50 changes: 8 additions & 42 deletions lib/kube/proxy/forwarder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1317,11 +1317,14 @@ func (s *clusterSession) monitorConn(conn net.Conn, err error) (net.Conn, error)
return conn, nil
}
ctx, cancel := context.WithCancel(s.parent.ctx)
tc := &trackingConn{
Conn: conn,
clock: s.parent.cfg.Clock,
ctx: ctx,
cancel: cancel,
tc, err := srv.NewTrackingReadConn(srv.TrackingReadConnConfig{
Conn: conn,
Clock: s.parent.cfg.Clock,
Context: s.parent.cfg.Context,
Cancel: cancel,
})
if err != nil {
return nil, trace.Wrap(err)
}

mon, err := srv.NewMonitor(srv.MonitorConfig{
Expand Down Expand Up @@ -1352,43 +1355,6 @@ func (s *clusterSession) DialWithContext(ctx context.Context, network, addr stri
return s.monitorConn(s.teleportCluster.DialWithContext(ctx, network, addr))
}

type trackingConn struct {
sync.RWMutex
net.Conn
clock clockwork.Clock
lastActive time.Time
ctx context.Context
cancel context.CancelFunc
}

// Read reads data from the connection.
// Read can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (t *trackingConn) Read(b []byte) (int, error) {
n, err := t.Conn.Read(b)
t.UpdateClientActivity()
return n, err
}

func (t *trackingConn) Close() error {
t.cancel()
return t.Conn.Close()
}

// GetClientLastActive returns time when client was last active
func (t *trackingConn) GetClientLastActive() time.Time {
t.RLock()
defer t.RUnlock()
return t.lastActive
}

// UpdateClientActivity sets last recorded client activity
func (t *trackingConn) UpdateClientActivity() {
t.Lock()
defer t.Unlock()
t.lastActive = t.clock.Now().UTC()
}

// TODO(awly): unit test this
func (f *Forwarder) newClusterSession(ctx authContext) (*clusterSession, error) {
if ctx.teleportCluster.isRemote {
Expand Down
2 changes: 1 addition & 1 deletion lib/reversetunnel/agentpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (cfg *AgentPoolConfig) CheckAndSetDefaults() error {
return nil
}

// NewAgentPool returns new isntance of the agent pool
// NewAgentPool returns new instance of the agent pool
func NewAgentPool(ctx context.Context, cfg AgentPoolConfig) (*AgentPool, error) {
if err := cfg.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
Expand Down
1 change: 1 addition & 0 deletions lib/service/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ func (process *TeleportProcess) initDatabaseService() (retErr error) {

// Create and start the database service.
dbService, err := db.New(process.ExitContext(), db.Config{
Clock: process.Clock,
DataDir: process.Config.DataDir,
AuthClient: conn.Client,
AccessPoint: accessPoint,
Expand Down
2 changes: 2 additions & 0 deletions lib/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,8 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error {
Authorizer: authorizer,
Tunnel: tsrv,
TLSConfig: tlsConfig,
Emitter: asyncEmitter,
Clock: process.Clock,
})
if err != nil {
return trace.Wrap(err)
Expand Down
11 changes: 8 additions & 3 deletions lib/srv/db/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ type testContext struct {
postgres map[string]testPostgres
// mysql is a collection of MySQL databases the test uses.
mysql map[string]testMySQL
// clock to override clock in tests.
clock clockwork.FakeClock
}

// testPostgres represents a single proxied Postgres database.
Expand Down Expand Up @@ -399,6 +401,7 @@ func setupTestContext(ctx context.Context, t *testing.T, withDatabases ...withDa
hostID: uuid.New(),
postgres: make(map[string]testPostgres),
mysql: make(map[string]testMySQL),
clock: clockwork.NewFakeClockAt(time.Now()),
}
t.Cleanup(func() { testCtx.Close() })

Expand Down Expand Up @@ -472,19 +475,21 @@ func setupTestContext(ctx context.Context, t *testing.T, withDatabases ...withDa
},
}

// Create test audit events emitter.
testCtx.emitter = newTestEmitter()

// Create database proxy server.
testCtx.proxyServer, err = NewProxyServer(ctx, ProxyServerConfig{
AuthClient: proxyAuthClient,
AccessPoint: proxyAuthClient,
Authorizer: proxyAuthorizer,
Tunnel: tunnel,
TLSConfig: tlsConfig,
Emitter: testCtx.emitter,
Clock: testCtx.clock,
})
require.NoError(t, err)

// Create test audit events emitter.
testCtx.emitter = newTestEmitter()

// Unauthenticated GCP IAM client so we don't try to initialize a real one.
gcpIAM, err := gcpcredentials.NewIamCredentialsClient(ctx,
option.WithGRPCDialOption(grpc.WithInsecure()), // Insecure must be set for unauth client.
Expand Down
7 changes: 4 additions & 3 deletions lib/srv/db/common/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ package common

import (
"context"
"io"
"net"

"github.com/gravitational/teleport/lib/auth"
)

// Proxy defines an interface a database proxy should implement.
Expand All @@ -32,9 +33,9 @@ type Proxy interface {
// Service defines an interface for connecting to a remote database service.
type Service interface {
// Connect is used to connect to remote database server over reverse tunnel.
Connect(ctx context.Context, user, database string) (net.Conn, error)
Connect(ctx context.Context, user, database string) (net.Conn, *auth.Context, error)
// Proxy starts proxying between client and service connections.
Proxy(ctx context.Context, clientConn, serviceConn io.ReadWriteCloser) error
Proxy(ctx context.Context, authContext *auth.Context, clientConn, serviceConn net.Conn) error
}

// Engine defines an interface for specific database protocol engine such
Expand Down
5 changes: 3 additions & 2 deletions lib/srv/db/mysql/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (p *Proxy) HandleConnection(ctx context.Context, clientConn net.Conn) (err
if err != nil {
return trace.Wrap(err)
}
serviceConn, err := p.Service.Connect(ctx, server.GetUser(), server.GetDatabase())
serviceConn, authContext, err := p.Service.Connect(ctx, server.GetUser(), server.GetDatabase())
if err != nil {
return trace.Wrap(err)
}
Expand All @@ -88,9 +88,10 @@ func (p *Proxy) HandleConnection(ctx context.Context, clientConn net.Conn) (err
if err != nil {
return trace.Wrap(err)
}

// Auth has completed, the client enters command phase, start proxying
// all messages back-and-forth.
err = p.Service.Proxy(ctx, tlsConn, serviceConn)
err = p.Service.Proxy(ctx, authContext, tlsConn, serviceConn)
if err != nil {
return trace.Wrap(err)
}
Expand Down
4 changes: 2 additions & 2 deletions lib/srv/db/postgres/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (p *Proxy) HandleConnection(ctx context.Context, clientConn net.Conn) (err
if err != nil {
return trace.Wrap(err)
}
serviceConn, err := p.Service.Connect(ctx, "", "")
serviceConn, authContext, err := p.Service.Connect(ctx, "", "")
if err != nil {
return trace.Wrap(err)
}
Expand All @@ -75,7 +75,7 @@ func (p *Proxy) HandleConnection(ctx context.Context, clientConn net.Conn) (err
if err != nil {
return trace.Wrap(err)
}
err = p.Service.Proxy(ctx, tlsConn, serviceConn)
err = p.Service.Proxy(ctx, authContext, tlsConn, serviceConn)
if err != nil {
return trace.Wrap(err)
}
Expand Down
Loading

0 comments on commit 164cf7b

Please sign in to comment.