diff --git a/api/client/client.go b/api/client/client.go index e5eedbdd9d536..169347a6c600e 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -4892,16 +4892,16 @@ func (c *Client) ResourceUsageClient() resourceusagepb.ResourceUsageServiceClien } // UpdateRemoteCluster updates remote cluster from the specified value. -// TODO(noah): In v17.0.0 this method should switch to call UpdateRemoteCluster -// on the presence service client. -func (c *Client) UpdateRemoteCluster(ctx context.Context, rc types.RemoteCluster) error { +func (c *Client) UpdateRemoteCluster(ctx context.Context, rc types.RemoteCluster) (types.RemoteCluster, error) { rcV3, ok := rc.(*types.RemoteClusterV3) if !ok { - return trace.BadParameter("unsupported remote cluster type %T", rcV3) + return nil, trace.BadParameter("unsupported remote cluster type %T", rcV3) } - _, err := c.grpc.UpdateRemoteCluster(ctx, rcV3) - return trace.Wrap(err) + res, err := c.PresenceServiceClient().UpdateRemoteCluster(ctx, &presencepb.UpdateRemoteClusterRequest{ + RemoteCluster: rcV3, + }) + return res, trace.Wrap(err) } // ListRemoteClusters returns a page of remote clusters. @@ -4935,3 +4935,21 @@ func (c *Client) GetRemoteCluster(ctx context.Context, name string) (types.Remot }) return rc, trace.Wrap(err) } + +// GetRemoteClusters returns all remote clusters. +// Deprecated: use ListRemoteClusters instead. +func (c *Client) GetRemoteClusters(ctx context.Context) ([]types.RemoteCluster, error) { + var rcs []types.RemoteCluster + pageToken := "" + for { + page, nextToken, err := c.ListRemoteClusters(ctx, 0, pageToken) + if err != nil { + return nil, trace.Wrap(err) + } + rcs = append(rcs, page...) + if nextToken == "" { + return rcs, nil + } + pageToken = nextToken + } +} diff --git a/lib/auth/apiserver.go b/lib/auth/apiserver.go index a853831ba5294..a6e82715e2480 100644 --- a/lib/auth/apiserver.go +++ b/lib/auth/apiserver.go @@ -136,12 +136,6 @@ func NewAPIServer(config *APIConfig) (http.Handler, error) { srv.DELETE("/:version/tunnelconnections/:cluster", srv.WithAuth(srv.deleteTunnelConnections)) srv.DELETE("/:version/tunnelconnections", srv.WithAuth(srv.deleteAllTunnelConnections)) - // Remote clusters - // TODO(noah): DELETE IN 17.0.0 - all these methods are now gRPC. - srv.GET("/:version/remoteclusters/:cluster", srv.WithAuth(srv.getRemoteCluster)) - srv.GET("/:version/remoteclusters", srv.WithAuth(srv.getRemoteClusters)) - srv.DELETE("/:version/remoteclusters/:cluster", srv.WithAuth(srv.deleteRemoteCluster)) - // Reverse tunnels srv.POST("/:version/reversetunnels", srv.WithAuth(srv.upsertReverseTunnel)) srv.GET("/:version/reversetunnels", srv.WithAuth(srv.getReverseTunnels)) @@ -927,41 +921,6 @@ func (s *APIServer) deleteAllTunnelConnections(auth *ServerWithRoles, w http.Res return message("ok"), nil } -// getRemoteClusters returns a list of remote clusters -func (s *APIServer) getRemoteClusters(auth *ServerWithRoles, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) { - clusters, err := auth.GetRemoteClusters(r.Context()) - if err != nil { - return nil, trace.Wrap(err) - } - items := make([]json.RawMessage, len(clusters)) - for i, cluster := range clusters { - data, err := services.MarshalRemoteCluster(cluster, services.WithVersion(version), services.PreserveRevision()) - if err != nil { - return nil, trace.Wrap(err) - } - items[i] = data - } - return items, nil -} - -// getRemoteCluster returns a remote cluster by name -func (s *APIServer) getRemoteCluster(auth *ServerWithRoles, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) { - cluster, err := auth.GetRemoteCluster(r.Context(), p.ByName("cluster")) - if err != nil { - return nil, trace.Wrap(err) - } - return rawMessage(services.MarshalRemoteCluster(cluster, services.WithVersion(version), services.PreserveRevision())) -} - -// deleteRemoteCluster deletes remote cluster by name -func (s *APIServer) deleteRemoteCluster(auth *ServerWithRoles, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) { - err := auth.DeleteRemoteCluster(r.Context(), p.ByName("cluster")) - if err != nil { - return nil, trace.Wrap(err) - } - return message("ok"), nil -} - func (s *APIServer) processKubeCSR(auth *ServerWithRoles, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) { var req authclient.KubeCSR diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 9b6ed728ed75d..b9e430eccb14a 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -61,7 +61,6 @@ import ( "github.com/gravitational/teleport/lib/services/local" "github.com/gravitational/teleport/lib/session" "github.com/gravitational/teleport/lib/tlsca" - "github.com/gravitational/teleport/lib/utils" ) // ServerWithRoles is a wrapper around auth service @@ -5161,60 +5160,6 @@ func (a *ServerWithRoles) DeleteAllTunnelConnections() error { return a.authServer.DeleteAllTunnelConnections() } -// Deprecated: use [presencev1.PresenceService.GetRemoteCluster] -// TODO(noah): DELETE IN 17.0.0 -func (a *ServerWithRoles) GetRemoteCluster(ctx context.Context, clusterName string) (types.RemoteCluster, error) { - if err := a.action(apidefaults.Namespace, types.KindRemoteCluster, types.VerbRead); err != nil { - return nil, trace.Wrap(err) - } - cluster, err := a.authServer.GetRemoteCluster(ctx, clusterName) - if err != nil { - return nil, utils.OpaqueAccessDenied(err) - } - if err := a.context.Checker.CheckAccessToRemoteCluster(cluster); err != nil { - return nil, utils.OpaqueAccessDenied(err) - } - return cluster, nil -} - -// Deprecated: use [presencev1.PresenceService.ListRemoteClusters] -// TODO(noah): DELETE IN 17.0.0 -func (a *ServerWithRoles) GetRemoteClusters(ctx context.Context) ([]types.RemoteCluster, error) { - if err := a.action(apidefaults.Namespace, types.KindRemoteCluster, types.VerbList); err != nil { - return nil, trace.Wrap(err) - } - remoteClusters, err := a.authServer.GetRemoteClusters(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - return a.filterRemoteClustersForUser(remoteClusters) -} - -// filterRemoteClustersForUser filters remote clusters based on what the current user is authorized to access -// TODO(noah): DELETE IN 17.0.0 -func (a *ServerWithRoles) filterRemoteClustersForUser(remoteClusters []types.RemoteCluster) ([]types.RemoteCluster, error) { - filteredClusters := make([]types.RemoteCluster, 0, len(remoteClusters)) - for _, rc := range remoteClusters { - if err := a.context.Checker.CheckAccessToRemoteCluster(rc); err != nil { - if trace.IsAccessDenied(err) { - continue - } - return nil, trace.Wrap(err) - } - filteredClusters = append(filteredClusters, rc) - } - return filteredClusters, nil -} - -// Deprecated: use [presencev1.PresenceService.DeleteRemoteCluster] -// TODO(noah): DELETE IN 17.0.0 -func (a *ServerWithRoles) DeleteRemoteCluster(ctx context.Context, clusterName string) error { - if err := a.action(apidefaults.Namespace, types.KindRemoteCluster, types.VerbDelete); err != nil { - return trace.Wrap(err) - } - return a.authServer.DeleteRemoteCluster(ctx, clusterName) -} - // AcquireSemaphore acquires lease with requested resources from semaphore. func (a *ServerWithRoles) AcquireSemaphore(ctx context.Context, params types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) { if err := a.action(apidefaults.Namespace, types.KindSemaphore, types.VerbCreate, types.VerbUpdate); err != nil { diff --git a/lib/auth/authclient/httpfallback.go b/lib/auth/authclient/httpfallback.go index c4cf0db634b14..7287e1ec923f6 100644 --- a/lib/auth/authclient/httpfallback.go +++ b/lib/auth/authclient/httpfallback.go @@ -18,166 +18,5 @@ package authclient -import ( - "context" - "encoding/json" - "net/url" - - "github.com/gravitational/trace" - - presencepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/presence/v1" - "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/lib/services" -) - // httpfallback.go holds endpoints that have been converted to gRPC // but still need http fallback logic in the old client. - -// TODO(Joerger): DELETE IN 16.0.0 -func (c *Client) RotateCertAuthority(ctx context.Context, req types.RotateRequest) error { - err := c.APIClient.RotateCertAuthority(ctx, req) - if trace.IsNotImplemented(err) { - // Fall back to HTTP implementation. - _, err := c.PostJSON(ctx, c.Endpoint("authorities", string(req.Type), "rotate"), req) - return trace.Wrap(err) - } - - return trace.Wrap(err) -} - -type rotateExternalCertAuthorityRawReq struct { - CA json.RawMessage `json:"ca"` -} - -// TODO(Joerger): DELETE IN 16.0.0 -func (c *Client) RotateExternalCertAuthority(ctx context.Context, ca types.CertAuthority) error { - err := c.APIClient.RotateExternalCertAuthority(ctx, ca) - if trace.IsNotImplemented(err) { - // Fall back to HTTP implementation. - data, err := services.MarshalCertAuthority(ca) - if err != nil { - return trace.Wrap(err) - } - _, err = c.PostJSON(ctx, c.Endpoint("authorities", string(ca.GetType()), "rotate", "external"), - &rotateExternalCertAuthorityRawReq{CA: data}) - return trace.Wrap(err) - } - - return trace.Wrap(err) -} - -func (c *Client) deleteRemoteClusterLegacy(ctx context.Context, clusterName string) error { - if clusterName == "" { - return trace.BadParameter("missing parameter cluster name") - } - _, err := c.Delete(ctx, c.Endpoint("remoteclusters", clusterName)) - return trace.Wrap(err) -} - -// DeleteRemoteCluster deletes remote cluster by name -// TODO(noah): DELETE IN 17.0.0 -func (c *Client) DeleteRemoteCluster(ctx context.Context, name string) error { - err := c.APIClient.DeleteRemoteCluster(ctx, name) - if err == nil { - return nil - } - if !trace.IsNotImplemented(err) { - return trace.Wrap(err) - } - return c.deleteRemoteClusterLegacy(ctx, name) -} - -func (c *Client) getRemoteClustersLegacy(ctx context.Context) ([]types.RemoteCluster, error) { - out, err := c.Get(ctx, c.Endpoint("remoteclusters"), url.Values{}) - if err != nil { - return nil, trace.Wrap(err) - } - var items []json.RawMessage - if err := json.Unmarshal(out.Bytes(), &items); err != nil { - return nil, trace.Wrap(err) - } - conns := make([]types.RemoteCluster, 0, len(items)) - for _, raw := range items { - conn, err := services.UnmarshalRemoteCluster(raw) - if err != nil { - return nil, trace.Wrap(err) - } - conns = append(conns, conn) - } - return conns, nil -} - -// GetRemoteClusters returns a list of remote clusters -// Prefer using ListRemoteClusters. -// TODO(noah): DELETE IN 17.0.0 -func (c *Client) GetRemoteClusters(ctx context.Context) ([]types.RemoteCluster, error) { - var rcs []types.RemoteCluster - pageToken := "" - for { - page, nextToken, err := c.APIClient.ListRemoteClusters(ctx, 0, pageToken) - if err != nil { - if trace.IsNotImplemented(err) { - return c.getRemoteClustersLegacy(ctx) - } - return nil, trace.Wrap(err) - } - rcs = append(rcs, page...) - if nextToken == "" { - return rcs, nil - } - pageToken = nextToken - } -} - -func (c *Client) getRemoteClusterLegacy(ctx context.Context, clusterName string) (types.RemoteCluster, error) { - if clusterName == "" { - return nil, trace.BadParameter("missing cluster name") - } - out, err := c.Get(ctx, c.Endpoint("remoteclusters", clusterName), url.Values{}) - if err != nil { - return nil, trace.Wrap(err) - } - return services.UnmarshalRemoteCluster(out.Bytes()) -} - -// GetRemoteCluster returns remote cluster by name -// TODO(noah): DELETE IN 17.0.0 -func (c *Client) GetRemoteCluster(ctx context.Context, name string) (types.RemoteCluster, error) { - res, err := c.APIClient.GetRemoteCluster(ctx, name) - if err == nil { - return res, nil - } - if !trace.IsNotImplemented(err) { - return nil, trace.Wrap(err) - } - return c.getRemoteClusterLegacy(ctx, name) -} - -// UpdateRemoteCluster updates a remote cluster. -// TODO(noah): DELETE IN 17.0.0 and update api/client.go to call new endpoint -func (c *Client) UpdateRemoteCluster(ctx context.Context, rc types.RemoteCluster) (types.RemoteCluster, error) { - rcV3, ok := rc.(*types.RemoteClusterV3) - if !ok { - return nil, trace.BadParameter("unsupported remote cluster type %T", rcV3) - } - out, err := c.APIClient.PresenceServiceClient().UpdateRemoteCluster(ctx, &presencepb.UpdateRemoteClusterRequest{ - RemoteCluster: rcV3, - }) - if err == nil { - return out, nil - } - if !trace.IsNotImplemented(err) { - return nil, trace.Wrap(err) - } - - // This is a little weird during the migration period of the old endpoints - // to grpc. Here, we need to call Update via gRPC and Get via HTTP. - if err := c.APIClient.UpdateRemoteCluster(ctx, rc); err != nil { - return nil, trace.Wrap(err) - } - fetchedRC, err := c.getRemoteClusterLegacy(ctx, rc.GetName()) - if err != nil { - return nil, trace.Wrap(err) - } - return fetchedRC, nil -} diff --git a/lib/auth/grpcserver.go b/lib/auth/grpcserver.go index c1394e9c4d6dd..4a658923547ea 100644 --- a/lib/auth/grpcserver.go +++ b/lib/auth/grpcserver.go @@ -1014,7 +1014,7 @@ func (g *GRPCServer) CreateAccessRequestV2(ctx context.Context, req *types.Acces return nil, trace.Wrap(err) } - if err := services.ValidateAccessRequestClusterNames(auth, req); err != nil { + if err := services.ValidateAccessRequestClusterNames(g.AuthServer, req); err != nil { return nil, trace.Wrap(err) } @@ -2039,17 +2039,6 @@ func (g *GRPCServer) DeleteAllWebTokens(ctx context.Context, _ *emptypb.Empty) ( return &emptypb.Empty{}, nil } -// UpdateRemoteCluster updates remote cluster -// Deprecated: use [presencev1.PresenceService.UpdateRemoteCluster] instead. -// TODO(noah): DELETE IN 17.0.0 -func (g *GRPCServer) UpdateRemoteCluster(ctx context.Context, req *types.RemoteClusterV3) (*emptypb.Empty, error) { - _, err := g.presenceService.UpdateRemoteCluster(ctx, &presencev1pb.UpdateRemoteClusterRequest{RemoteCluster: req}) - if err != nil { - return nil, trace.Wrap(err) - } - return &emptypb.Empty{}, nil -} - // UpsertKubernetesServer registers an kubernetes server. func (g *GRPCServer) UpsertKubernetesServer(ctx context.Context, req *authpb.UpsertKubernetesServerRequest) (*types.KeepAlive, error) { auth, err := g.authenticate(ctx) diff --git a/lib/auth/tls_test.go b/lib/auth/tls_test.go index d02de50fe7c0a..847789e76ccf1 100644 --- a/lib/auth/tls_test.go +++ b/lib/auth/tls_test.go @@ -1421,58 +1421,6 @@ func TestTunnelConnectionsCRUD(t *testing.T) { suite.TunnelConnectionsCRUD(t) } -func TestRemoteClustersCRUD(t *testing.T) { - t.Parallel() - ctx := context.Background() - - testSrv := newTestTLSServer(t) - clt, err := testSrv.NewClient(TestAdmin()) - require.NoError(t, err) - - clusterName := "example.com" - out, err := clt.GetRemoteClusters(ctx) - require.NoError(t, err) - require.Empty(t, out) - - rc, err := types.NewRemoteCluster(clusterName) - require.NoError(t, err) - rc.SetConnectionStatus(teleport.RemoteClusterStatusOffline) - - rc, err = testSrv.Auth().CreateRemoteCluster(ctx, rc) - require.NoError(t, err) - - out, err = clt.GetRemoteClusters(ctx) - require.NoError(t, err) - require.Len(t, out, 1) - require.Empty(t, cmp.Diff(out[0], rc)) - - update := rc.Clone() - update.SetConnectionStatus(teleport.RemoteClusterStatusOnline) - _, err = clt.UpdateRemoteCluster(ctx, update) - require.NoError(t, err) - updated, err := clt.GetRemoteCluster(ctx, rc.GetName()) - require.NoError(t, err) - require.Equal(t, teleport.RemoteClusterStatusOnline, updated.GetConnectionStatus()) - // Ensure other fields unchanged - require.Empty(t, - cmp.Diff( - rc, - updated, - cmpopts.IgnoreFields(types.Metadata{}, "Revision"), - cmpopts.IgnoreFields(types.RemoteClusterStatusV3{}, "Connection"), - ), - ) - - err = clt.DeleteRemoteCluster(ctx, clusterName) - require.NoError(t, err) - err = clt.DeleteRemoteCluster(ctx, clusterName) - require.True(t, trace.IsNotFound(err)) - - out, err = clt.GetRemoteClusters(ctx) - require.NoError(t, err) - require.Empty(t, out) -} - func TestServersCRUD(t *testing.T) { t.Parallel()