diff --git a/lib/teleterm/clusters/cluster_databases.go b/lib/teleterm/clusters/cluster_databases.go index 1ef9096d52d9c..dda50b6204835 100644 --- a/lib/teleterm/clusters/cluster_databases.go +++ b/lib/teleterm/clusters/cluster_databases.go @@ -97,7 +97,17 @@ func (c *Cluster) ReissueDBCerts(ctx context.Context, user, dbName string, db ty return trace.BadParameter("please provide the database user name using --db-user flag") } + // Refresh the certs to account for clusterClient.SiteName pointing at a leaf cluster. err := c.clusterClient.ReissueUserCerts(ctx, client.CertCacheKeep, client.ReissueParams{ + RouteToCluster: c.clusterClient.SiteName, + AccessRequests: c.status.ActiveRequests.AccessRequests, + }) + if err != nil { + return trace.Wrap(err) + } + + // Fetch the certs for the database. + err = c.clusterClient.ReissueUserCerts(ctx, client.CertCacheKeep, client.ReissueParams{ RouteToCluster: c.clusterClient.SiteName, RouteToDatabase: proto.RouteToDatabase{ ServiceName: db.GetName(), diff --git a/lib/teleterm/clusters/cluster_gateways.go b/lib/teleterm/clusters/cluster_gateways.go index 58acee3470d68..286ac87e4bb15 100644 --- a/lib/teleterm/clusters/cluster_gateways.go +++ b/lib/teleterm/clusters/cluster_gateways.go @@ -58,7 +58,7 @@ func (c *Cluster) CreateGateway(ctx context.Context, params CreateGatewayParams) TargetSubresourceName: params.TargetSubresourceName, Protocol: db.GetProtocol(), KeyPath: c.status.KeyPath(), - CertPath: c.status.DatabaseCertPathForCluster("", db.GetName()), + CertPath: c.status.DatabaseCertPathForCluster(c.clusterClient.SiteName, db.GetName()), Insecure: c.clusterClient.InsecureSkipVerify, WebProxyAddr: c.clusterClient.WebProxyAddr, Log: c.Log.WithField("gateway", params.TargetURI), @@ -84,7 +84,14 @@ func buildCLICommand(c *Cluster, gw *gateway.Gateway) (*exec.Cmd, error) { Database: gw.TargetSubresourceName, } - cmd, err := dbcmd.NewCmdBuilder(c.clusterClient, &c.status, &routeToDb, c.GetActualName(), + cmd, err := dbcmd.NewCmdBuilder(c.clusterClient, &c.status, &routeToDb, + // TODO(ravicious): Pass the root cluster name here. GetActualName returns leaf name for leaf + // clusters. + // + // At this point it doesn't matter though, because this argument is used only for + // generating correct CA paths. But we use dbcmd.WithNoTLS here, which doesn't include CA paths + // in the returned CLI command. + c.GetActualName(), dbcmd.WithLogger(gw.Log), dbcmd.WithLocalProxy(gw.LocalAddress, gw.LocalPortInt(), ""), dbcmd.WithNoTLS(), diff --git a/lib/teleterm/clusters/storage.go b/lib/teleterm/clusters/storage.go index dfc0ab2694fb1..b196951bf2321 100644 --- a/lib/teleterm/clusters/storage.go +++ b/lib/teleterm/clusters/storage.go @@ -45,7 +45,7 @@ func (s *Storage) ReadAll() ([]*Cluster, error) { clusters := make([]*Cluster, 0, len(pfNames)) for _, name := range pfNames { - cluster, err := s.fromProfile(name) + cluster, err := s.fromProfile(name, "") if err != nil { return nil, trace.Wrap(err) } @@ -58,7 +58,7 @@ func (s *Storage) ReadAll() ([]*Cluster, error) { // GetByName returns a cluster by name func (s *Storage) GetByName(clusterName string) (*Cluster, error) { - cluster, err := s.fromProfile(clusterName) + cluster, err := s.fromProfile(clusterName, "") if err != nil { return nil, trace.Wrap(err) } @@ -72,17 +72,11 @@ func (s *Storage) GetByURI(clusterURI string) (*Cluster, error) { rootClusterName := URI.GetRootClusterName() leafClusterName := URI.GetLeafClusterName() - cluster, err := s.fromProfile(rootClusterName) + cluster, err := s.fromProfile(rootClusterName, leafClusterName) if err != nil { return nil, trace.Wrap(err) } - if leafClusterName != "" { - cluster.clusterClient.SiteName = leafClusterName - } - - cluster.URI = URI - return cluster, nil } @@ -161,20 +155,28 @@ func (s *Storage) addCluster(ctx context.Context, dir, webProxyAddress string) ( } // fromProfile creates a new cluster from its profile -func (s *Storage) fromProfile(clusterName string) (*Cluster, error) { - if clusterName == "" { +func (s *Storage) fromProfile(profileName, leafClusterName string) (*Cluster, error) { + if profileName == "" { return nil, trace.BadParameter("cluster name is missing") } + clusterNameForKey := profileName + clusterURI := uri.NewClusterURI(profileName) + cfg := client.MakeDefaultConfig() - if err := cfg.LoadProfile(s.Dir, clusterName); err != nil { + if err := cfg.LoadProfile(s.Dir, profileName); err != nil { return nil, trace.Wrap(err) } - cfg.KeysDir = s.Dir cfg.HomePath = s.Dir cfg.InsecureSkipVerify = s.InsecureSkipVerify + if leafClusterName != "" { + clusterNameForKey = leafClusterName + clusterURI = clusterURI.AppendLeafCluster(leafClusterName) + cfg.SiteName = leafClusterName + } + clusterClient, err := client.NewClient(cfg) if err != nil { return nil, trace.Wrap(err) @@ -183,13 +185,13 @@ func (s *Storage) fromProfile(clusterName string) (*Cluster, error) { status := &client.ProfileStatus{} // load profile status if key exists - _, err = clusterClient.LocalAgent().GetKey(clusterName) + _, err = clusterClient.LocalAgent().GetKey(clusterNameForKey) if err != nil { - s.Log.WithError(err).Infof("Unable to load the keys for cluster %v.", clusterName) + s.Log.WithError(err).Infof("Unable to load the keys for cluster %v.", clusterNameForKey) } if err == nil && cfg.Username != "" { - status, err = client.ReadProfileStatus(s.Dir, clusterName) + status, err = client.ReadProfileStatus(s.Dir, profileName) if err != nil { return nil, trace.Wrap(err) } @@ -202,10 +204,11 @@ func (s *Storage) fromProfile(clusterName string) (*Cluster, error) { return nil, trace.Wrap(err) } - clusterURI := uri.NewClusterURI(clusterName) return &Cluster{ - URI: clusterURI, - Name: clusterName, + URI: clusterURI, + // TODO(ravicious): This should probably use leafClusterName if available, but at this point I'm + // worried that changing it might break something else in the app. + Name: profileName, clusterClient: clusterClient, dir: s.Dir, clock: s.Clock,