diff --git a/integration/integration_test.go b/integration/integration_test.go index ffbd4262627fb..e60496ab9c23d 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -1004,7 +1004,7 @@ func (s *IntSuite) TestTwoClusters(c *check.C) { c.Assert(outputA.String(), check.Equals, "hello world\n") // Update trusted CAs. - err = tc.UpdateTrustedCA(context.TODO()) + err = tc.UpdateTrustedCA(context.TODO(), a.Secrets.SiteName) c.Assert(err, check.IsNil) // The known_hosts file should have two certificates, the way bytes.Split diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 7574adb73b092..b42e16effb024 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -373,7 +373,7 @@ func (a *AuthWithRoles) NewWatcher(ctx context.Context, watch services.Watch) (s for _, kind := range watch.Kinds { switch kind { case services.KindCertAuthority: - if err := a.action(defaults.Namespace, services.KindCertAuthority, services.VerbRead); err != nil { + if err := a.action(defaults.Namespace, services.KindCertAuthority, services.VerbReadNoSecrets); err != nil { return nil, trace.Wrap(err) } default: diff --git a/lib/client/api.go b/lib/client/api.go index 3435844270937..2b052adad142c 100644 --- a/lib/client/api.go +++ b/lib/client/api.go @@ -911,7 +911,7 @@ func (tc *TeleportClient) Join(ctx context.Context, namespace string, sessionID return trace.Wrap(err) } defer proxyClient.Close() - site, err := proxyClient.ConnectToSite(ctx, false) + site, err := proxyClient.ConnectToCurrentCluster(ctx, false) if err != nil { return trace.Wrap(err) } @@ -985,7 +985,7 @@ func (tc *TeleportClient) Play(ctx context.Context, namespace, sessionId string) if err != nil { return trace.Wrap(err) } - site, err := proxyClient.ConnectToSite(ctx, false) + site, err := proxyClient.ConnectToCurrentCluster(ctx, false) if err != nil { return trace.Wrap(err) } @@ -1580,6 +1580,11 @@ func (tc *TeleportClient) Login(ctx context.Context, activateKey bool) (*Key, er key.Cert = response.Cert key.TLSCert = response.TLSCert + if len(response.HostSigners) <= 0 { + return nil, trace.BadParameter("bad response from the server: expected at least one certificate, got 0") + } + key.ClusterName = response.HostSigners[0].ClusterName + if activateKey { // save the list of CAs client trusts to ~/.tsh/known_hosts err = tc.localAgent.AddHostSignersToCache(response.HostSigners) @@ -1604,7 +1609,7 @@ func (tc *TeleportClient) Login(ctx context.Context, activateKey bool) (*Key, er // GetTrustedCA returns a list of host certificate authorities // trusted by the cluster client is authenticated with. -func (tc *TeleportClient) GetTrustedCA(ctx context.Context) ([]services.CertAuthority, error) { +func (tc *TeleportClient) GetTrustedCA(ctx context.Context, clusterName string) ([]services.CertAuthority, error) { // Connect to the proxy. if !tc.Config.ProxySpecified() { return nil, trace.BadParameter("proxy server is not specified") @@ -1616,7 +1621,7 @@ func (tc *TeleportClient) GetTrustedCA(ctx context.Context) ([]services.CertAuth defer proxyClient.Close() // Get a client to the Auth Server. - clt, err := proxyClient.ClusterAccessPoint(ctx, true) + clt, err := proxyClient.ClusterAccessPoint(ctx, clusterName, true) if err != nil { return nil, trace.Wrap(err) } @@ -1627,9 +1632,9 @@ func (tc *TeleportClient) GetTrustedCA(ctx context.Context) ([]services.CertAuth // UpdateTrustedCA connects to the Auth Server and fetches all host certificates // and updates ~/.tsh/keys/proxy/certs.pem and ~/.tsh/known_hosts. -func (tc *TeleportClient) UpdateTrustedCA(ctx context.Context) error { +func (tc *TeleportClient) UpdateTrustedCA(ctx context.Context, clusterName string) error { // Get the list of host certificates that this cluster knows about. - hostCerts, err := tc.GetTrustedCA(ctx) + hostCerts, err := tc.GetTrustedCA(ctx, clusterName) if err != nil { return trace.Wrap(err) } diff --git a/lib/client/client.go b/lib/client/client.go index aa7054c8bb82b..bef9f4ad56be5 100644 --- a/lib/client/client.go +++ b/lib/client/client.go @@ -116,7 +116,7 @@ func (proxy *ProxyClient) FindServersByLabels(ctx context.Context, namespace str return nil, trace.BadParameter(auth.MissingNamespaceError) } nodes := make([]services.Server, 0) - site, err := proxy.ClusterAccessPoint(ctx, false) + site, err := proxy.CurrentClusterAccessPoint(ctx, false) if err != nil { return nil, trace.Wrap(err) } @@ -135,35 +135,52 @@ func (proxy *ProxyClient) FindServersByLabels(ctx context.Context, namespace str return nodes, nil } -// ClusterAccessPoint returns cluster access point used for discovery +// CurrentClusterAccessPoint returns cluster access point to the currently +// selected cluster and is used for discovery // and could be cached based on the access policy -func (proxy *ProxyClient) ClusterAccessPoint(ctx context.Context, quiet bool) (auth.AccessPoint, error) { +func (proxy *ProxyClient) CurrentClusterAccessPoint(ctx context.Context, quiet bool) (auth.AccessPoint, error) { // get the current cluster: cluster, err := proxy.currentCluster() if err != nil { return nil, trace.Wrap(err) } - clt, err := proxy.ConnectToSite(ctx, quiet) + return proxy.ClusterAccessPoint(ctx, cluster.Name, quiet) +} + +// ClusterAccessPoint returns cluster access point used for discovery +// and could be cached based on the access policy +func (proxy *ProxyClient) ClusterAccessPoint(ctx context.Context, clusterName string, quiet bool) (auth.AccessPoint, error) { + if clusterName == "" { + return nil, trace.BadParameter("parameter clusterName is missing") + } + clt, err := proxy.ConnectToCluster(ctx, clusterName, quiet) if err != nil { return nil, trace.Wrap(err) } - return proxy.teleportClient.accessPoint(clt, proxy.proxyAddress, cluster.Name) + return proxy.teleportClient.accessPoint(clt, proxy.proxyAddress, clusterName) } -// ConnectToSite connects to the auth server of the given site via proxy. -// It returns connected and authenticated auth server client +// ConnectToCurrentCluster connects to the auth server of the currently selected +// cluster via proxy. It returns connected and authenticated auth server client // // if 'quiet' is set to true, no errors will be printed to stdout, otherwise // any connection errors are visible to a user. -func (proxy *ProxyClient) ConnectToSite(ctx context.Context, quiet bool) (auth.ClientI, error) { - // get the current cluster: - site, err := proxy.currentCluster() +func (proxy *ProxyClient) ConnectToCurrentCluster(ctx context.Context, quiet bool) (auth.ClientI, error) { + cluster, err := proxy.currentCluster() if err != nil { return nil, trace.Wrap(err) } + return proxy.ConnectToCluster(ctx, cluster.Name, quiet) +} +// ConnectToCluster connects to the auth server of the given cluster via proxy. +// It returns connected and authenticated auth server client +// +// if 'quiet' is set to true, no errors will be printed to stdout, otherwise +// any connection errors are visible to a user. +func (proxy *ProxyClient) ConnectToCluster(ctx context.Context, clusterName string, quiet bool) (auth.ClientI, error) { dialer := func(ctx context.Context, network, _ string) (net.Conn, error) { - return proxy.dialAuthServer(ctx, site.Name) + return proxy.dialAuthServer(ctx, clusterName) } if proxy.teleportClient.SkipLocalAuth { diff --git a/lib/client/interfaces.go b/lib/client/interfaces.go index 5afaa89ab1337..118612cebc574 100644 --- a/lib/client/interfaces.go +++ b/lib/client/interfaces.go @@ -52,6 +52,9 @@ type Key struct { // TrustedCA is a list of trusted certificate authorities TrustedCA []auth.TrustedCerts + + // ClusterName is a cluster name this key is associated with + ClusterName string } // TLSConfig returns client TLS configuration used diff --git a/tool/tsh/tsh.go b/tool/tsh/tsh.go index aa8bf9d0792bc..0924769614001 100644 --- a/tool/tsh/tsh.go +++ b/tool/tsh/tsh.go @@ -419,7 +419,7 @@ func onLogin(cf *CLIConf) { if err := setupNoninteractiveClient(tc, key); err != nil { utils.FatalError(err) } - authorities, err := tc.GetTrustedCA(cf.Context) + authorities, err := tc.GetTrustedCA(cf.Context, key.ClusterName) if err != nil { utils.FatalError(err) } @@ -439,7 +439,7 @@ func onLogin(cf *CLIConf) { tc.SaveProfile("") // Connect to the Auth Server and fetch the known hosts for this cluster. - err = tc.UpdateTrustedCA(cf.Context) + err = tc.UpdateTrustedCA(cf.Context, key.ClusterName) if err != nil { utils.FatalError(err) }