diff --git a/lib/client/client.go b/lib/client/client.go index aa6a06cf015bd..76bfe1b238cb6 100644 --- a/lib/client/client.go +++ b/lib/client/client.go @@ -53,6 +53,7 @@ import ( "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/events" "github.com/gravitational/teleport/lib/sshutils/sftp" + "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" logutils "github.com/gravitational/teleport/lib/utils/log" "github.com/gravitational/teleport/lib/utils/socks" @@ -110,6 +111,18 @@ func (c *NodeClient) AddCancel(cancel context.CancelFunc) { })) } +// RouteToDatabaseToProto converts tlsca.RouteToDatabase to the proto version +// that is used for ReissueParams. +func RouteToDatabaseToProto(dbRoute tlsca.RouteToDatabase) proto.RouteToDatabase { + return proto.RouteToDatabase{ + ServiceName: dbRoute.ServiceName, + Protocol: dbRoute.Protocol, + Username: dbRoute.Username, + Database: dbRoute.Database, + Roles: dbRoute.Roles, + } +} + // ReissueParams encodes optional parameters for // user certificate reissue. type ReissueParams struct { diff --git a/lib/client/client_test.go b/lib/client/client_test.go index ffda5a6d2ee6a..fa103056e12e9 100644 --- a/lib/client/client_test.go +++ b/lib/client/client_test.go @@ -34,9 +34,11 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/ssh" + "github.com/gravitational/teleport/api/client/proto" tracessh "github.com/gravitational/teleport/api/observability/tracing/ssh" "github.com/gravitational/teleport/lib/observability/tracing" "github.com/gravitational/teleport/lib/sshutils" + "github.com/gravitational/teleport/lib/tlsca" ) func TestHelperFunctions(t *testing.T) { @@ -370,3 +372,21 @@ func TestLineLabeledWriter(t *testing.T) { }) } } + +func TestRouteToDatabaseToProto(t *testing.T) { + input := tlsca.RouteToDatabase{ + ServiceName: "db-service", + Database: "db-name", + Username: "db-user", + Protocol: "db-protocol", + Roles: []string{"db-role1", "db-role2"}, + } + expected := proto.RouteToDatabase{ + ServiceName: "db-service", + Database: "db-name", + Username: "db-user", + Protocol: "db-protocol", + Roles: []string{"db-role1", "db-role2"}, + } + require.Equal(t, expected, RouteToDatabaseToProto(input)) +} diff --git a/lib/client/local_proxy_middleware.go b/lib/client/local_proxy_middleware.go index 5c8b2e08555fe..4114efd03d779 100644 --- a/lib/client/local_proxy_middleware.go +++ b/lib/client/local_proxy_middleware.go @@ -94,9 +94,9 @@ func WithTTL(ttl time.Duration) CertCheckerOption { func NewDBCertChecker(tc *TeleportClient, dbRoute tlsca.RouteToDatabase, clock clockwork.Clock, opts ...CertCheckerOption) *CertChecker { opt := applyOptions(opts...) return NewCertChecker(&DBCertIssuer{ - Client: tc, - RouteToApp: dbRoute, - TTL: opt.ttl, + Client: tc, + RouteToDatabase: dbRoute, + TTL: opt.ttl, }, clock) } @@ -196,8 +196,8 @@ type CertIssuer interface { type DBCertIssuer struct { // Client is a TeleportClient used to issue certificates when necessary. Client *TeleportClient - // RouteToApp contains database routing information. - RouteToApp tlsca.RouteToDatabase + // RouteToDatabase contains database routing information. + RouteToDatabase tlsca.RouteToDatabase // TTL defines the maximum time-to-live for user certificates. // This variable sets the upper limit on the duration for which a certificate // remains valid. It's bounded by the `max_session_ttl` or `mfa_verification_interval` @@ -206,7 +206,7 @@ type DBCertIssuer struct { } func (c *DBCertIssuer) CheckCert(cert *x509.Certificate) error { - return alpnproxy.CheckDBCertSubject(cert, c.RouteToApp) + return alpnproxy.CheckDBCertSubject(cert, c.RouteToDatabase) } func (c *DBCertIssuer) IssueCert(ctx context.Context) (tls.Certificate, error) { @@ -220,16 +220,11 @@ func (c *DBCertIssuer) IssueCert(ctx context.Context) (tls.Certificate, error) { var keyRing *KeyRing if err := RetryWithRelogin(ctx, c.Client, func() error { dbCertParams := ReissueParams{ - RouteToCluster: c.Client.SiteName, - RouteToDatabase: proto.RouteToDatabase{ - ServiceName: c.RouteToApp.ServiceName, - Protocol: c.RouteToApp.Protocol, - Username: c.RouteToApp.Username, - Database: c.RouteToApp.Database, - }, - AccessRequests: accessRequests, - RequesterName: proto.UserCertsRequest_TSH_DB_LOCAL_PROXY_TUNNEL, - TTL: c.TTL, + RouteToCluster: c.Client.SiteName, + RouteToDatabase: RouteToDatabaseToProto(c.RouteToDatabase), + AccessRequests: accessRequests, + RequesterName: proto.UserCertsRequest_TSH_DB_LOCAL_PROXY_TUNNEL, + TTL: c.TTL, } clusterClient, err := c.Client.ConnectToCluster(ctx) @@ -256,7 +251,7 @@ func (c *DBCertIssuer) IssueCert(ctx context.Context) (tls.Certificate, error) { return tls.Certificate{}, trace.Wrap(err) } - dbCert, err := keyRing.DBTLSCert(c.RouteToApp.ServiceName) + dbCert, err := keyRing.DBTLSCert(c.RouteToDatabase.ServiceName) if err != nil { return tls.Certificate{}, trace.Wrap(err) } diff --git a/lib/teleterm/clusters/cluster_databases.go b/lib/teleterm/clusters/cluster_databases.go index 4c6ab08d1f12f..ff045116137c5 100644 --- a/lib/teleterm/clusters/cluster_databases.go +++ b/lib/teleterm/clusters/cluster_databases.go @@ -92,15 +92,11 @@ func (c *Cluster) reissueDBCerts(ctx context.Context, clusterClient *client.Clus } key, _, err := clusterClient.IssueUserCertsWithMFA(ctx, client.ReissueParams{ - RouteToCluster: c.clusterClient.SiteName, - RouteToDatabase: proto.RouteToDatabase{ - ServiceName: routeToDatabase.ServiceName, - Protocol: routeToDatabase.Protocol, - Username: routeToDatabase.Username, - }, - AccessRequests: c.status.ActiveRequests, - RequesterName: proto.UserCertsRequest_TSH_DB_LOCAL_PROXY_TUNNEL, - TTL: c.clusterClient.KeyTTL, + RouteToCluster: c.clusterClient.SiteName, + RouteToDatabase: client.RouteToDatabaseToProto(routeToDatabase), + AccessRequests: c.status.ActiveRequests, + RequesterName: proto.UserCertsRequest_TSH_DB_LOCAL_PROXY_TUNNEL, + TTL: c.clusterClient.KeyTTL, }) if err != nil { return tls.Certificate{}, trace.Wrap(err) diff --git a/tool/tsh/common/db.go b/tool/tsh/common/db.go index d6378ba1fbbbf..ff5fe4073653a 100644 --- a/tool/tsh/common/db.go +++ b/tool/tsh/common/db.go @@ -316,15 +316,9 @@ func databaseLogin(cf *CLIConf, tc *client.TeleportClient, dbInfo *databaseInfo) } else { if err = client.RetryWithRelogin(cf.Context, tc, func() error { keyRing, err = tc.IssueUserCertsWithMFA(cf.Context, client.ReissueParams{ - RouteToCluster: tc.SiteName, - RouteToDatabase: proto.RouteToDatabase{ - ServiceName: dbInfo.ServiceName, - Protocol: dbInfo.Protocol, - Username: dbInfo.Username, - Database: dbInfo.Database, - Roles: dbInfo.Roles, - }, - AccessRequests: profile.ActiveRequests, + RouteToCluster: tc.SiteName, + RouteToDatabase: client.RouteToDatabaseToProto(dbInfo.RouteToDatabase), + AccessRequests: profile.ActiveRequests, }) return trace.Wrap(err) }); err != nil {