Skip to content

Commit

Permalink
Remove the legacy JSON API for requesting host certs
Browse files Browse the repository at this point in the history
In Teleport 8 we migrated all uses of this API to GRPC, but left
the JSON API in place so that Teleport 7 nodes could still join
the cluster.

In Teleport 9, the oldest nodes we support are v8, which use the
GRPC API, so we can safely remove the old API.
  • Loading branch information
zmb3 committed Feb 16, 2022
1 parent eb487ce commit e256170
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 81 deletions.
54 changes: 4 additions & 50 deletions lib/auth/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,7 @@ func NewAPIServer(config *APIConfig) (http.Handler, error) {
srv.DELETE("/:version/tunnelconnections/:cluster", srv.withAuth(srv.deleteTunnelConnections))
srv.DELETE("/:version/tunnelconnections", srv.withAuth(srv.deleteAllTunnelConnections))

// Server Credentials
srv.POST("/:version/server/credentials", srv.withAuth(srv.generateHostCerts))

// Remote clusters
srv.POST("/:version/remoteclusters", srv.withAuth(srv.createRemoteCluster))
srv.GET("/:version/remoteclusters/:cluster", srv.withAuth(srv.getRemoteCluster))
srv.GET("/:version/remoteclusters", srv.withAuth(srv.getRemoteClusters))
Expand Down Expand Up @@ -1031,6 +1029,9 @@ func (s *APIServer) registerUsingToken(auth ClientI, w http.ResponseWriter, r *h
return nil, trace.Wrap(err)
}

// Teleport 8 clients are still expecting the legacy JSON format.
// Teleport 9 clients handle both legacy and new.
// TODO(zmb3) return certs directly in Teleport 10
return LegacyCertsFromProto(certs), nil
}

Expand All @@ -1050,53 +1051,6 @@ func (s *APIServer) registerNewAuthServer(auth ClientI, w http.ResponseWriter, r
return message("ok"), nil
}

// DELETE IN 9.0 (zmb3)
type legacyHostCertsRequest struct {
HostID string `json:"host_id"`
NodeName string `json:"node_name"`
Roles types.SystemRoles `json:"roles"`
AdditionalPrincipals []string `json:"additional_principals,omitempty"`
DNSNames []string `json:"dns_names,omitempty"`
PublicTLSKey []byte `json:"public_tls_key"`
PublicSSHKey []byte `json:"public_ssh_key"`
RemoteAddr string `json:"remote_addr"`
Rotation *types.Rotation `json:"rotation,omitempty"`
}

// DELETE IN 9.0 (zmb3) now available in GRPC server)
func (s *APIServer) generateHostCerts(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (interface{}, error) {
// We can't use proto.HostCertsRequest here, because this old API expects
// a list of roles with exactly one element, rather than a single role.
var req legacyHostCertsRequest
if err := httplib.ReadJSON(r, &req); err != nil {
return nil, trace.Wrap(err)
}

if len(req.Roles) != 1 {
return nil, trace.BadParameter("expected exactly one system role")
}

// Pass along the remote address the request came from to the registration function.
req.RemoteAddr = r.RemoteAddr

certs, err := auth.GenerateHostCerts(r.Context(), &proto.HostCertsRequest{
HostID: req.HostID,
NodeName: req.NodeName,
Role: req.Roles[0],
AdditionalPrincipals: req.AdditionalPrincipals,
DNSNames: req.DNSNames,
PublicTLSKey: req.PublicTLSKey,
PublicSSHKey: req.PublicSSHKey,
RemoteAddr: req.RemoteAddr,
Rotation: req.Rotation,
})
if err != nil {
return nil, trace.Wrap(err)
}

return LegacyCertsFromProto(certs), nil
}

func (s *APIServer) rotateCertAuthority(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
var req RotateRequest
if err := httplib.ReadJSON(r, &req); err != nil {
Expand Down
12 changes: 12 additions & 0 deletions lib/auth/clt.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,18 @@ func (c *Client) RegisterUsingToken(ctx context.Context, req *types.RegisterUsin
return nil, trace.Wrap(err)
}

var certs proto.Certs
if err := json.Unmarshal(out.Bytes(), &certs); err != nil {
return nil, trace.Wrap(err)
}

// If we got certs, we're done, however, we may be talking to a Teleport 9 or earlier server,
// which still sends back the legacy JSON format.
if len(certs.SSH) > 0 && len(certs.TLS) > 0 {
return &certs, nil
}

// DELETE IN 10.0.0 (zmb3)
return UnmarshalLegacyCerts(out.Bytes())
}

Expand Down
29 changes: 0 additions & 29 deletions lib/auth/httpfallback.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,35 +655,6 @@ func (c *Client) ChangeUserAuthentication(ctx context.Context, req *proto.Change
}, nil
}

// GenerateHostCerts generates new host certificates (signed by the host CA).
// DELETE IN 9.0.0 (zmb3)
func (c *Client) GenerateHostCerts(ctx context.Context, req *proto.HostCertsRequest) (*proto.Certs, error) {
switch certs, err := c.APIClient.GenerateHostCerts(ctx, req); {
case err == nil: // GRPC version is available and succeeded
return certs, nil
case !trace.IsNotImplemented(err): // GRPC version available but failed
return nil, trace.Wrap(err)
}

// fallback to legacy JSON API
out, err := c.PostJSON(c.Endpoint("server", "credentials"), legacyHostCertsRequest{
HostID: req.HostID,
NodeName: req.NodeName,
Roles: types.SystemRoles{req.Role}, // old API requires a list of roles
AdditionalPrincipals: req.AdditionalPrincipals,
DNSNames: req.DNSNames,
PublicTLSKey: req.PublicTLSKey,
PublicSSHKey: req.PublicSSHKey,
RemoteAddr: req.RemoteAddr,
Rotation: req.Rotation,
})
if err != nil {
return nil, trace.Wrap(err)
}

return UnmarshalLegacyCerts(out.Bytes())
}

// DELETE IN 9.0.0, to remove fallback and grpc call is already defined in api/client/client.go
//
// CreateAuthenticateChallenge creates and returns MFA challenges for a users registered MFA devices.
Expand Down
4 changes: 2 additions & 2 deletions lib/auth/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ type LegacyCerts struct {
}

// LegacyCertsFromProto converts proto.Certs to LegacyCerts.
// DELETE in 9.0.0 (Joerger/zmb3)
// DELETE in 10.0.0 (Joerger/zmb3)
func LegacyCertsFromProto(c *proto.Certs) *LegacyCerts {
return &LegacyCerts{
SSHCert: c.SSH,
Expand All @@ -543,7 +543,7 @@ func LegacyCertsFromProto(c *proto.Certs) *LegacyCerts {
}

// UnmarshalLegacyCerts unmarshals the a legacy certs response as proto.Certs.
// DELETE in 9.0.0 (Joerger/zmb3)
// DELETE in 10.0.0 (Joerger/zmb3)
func UnmarshalLegacyCerts(bytes []byte) (*proto.Certs, error) {
var lc LegacyCerts
if err := json.Unmarshal(bytes, &lc); err != nil {
Expand Down
12 changes: 12 additions & 0 deletions lib/client/weblogin.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,5 +460,17 @@ func HostCredentials(ctx context.Context, proxyAddr string, insecure bool, req t
return nil, trace.Wrap(err)
}

var certs proto.Certs
if err := json.Unmarshal(resp.Bytes(), &certs); err != nil {
return nil, trace.Wrap(err)
}

// If we got certs, we're done, however, we may be talking to a Teleport 9 or earlier server,
// which still sends back the legacy JSON format.
if len(certs.SSH) > 0 && len(certs.TLS) > 0 {
return &certs, nil
}

// DELETE IN 10.0.0 (zmb3)
return auth.UnmarshalLegacyCerts(resp.Bytes())
}
3 changes: 3 additions & 0 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2341,6 +2341,9 @@ func (h *Handler) hostCredentials(w http.ResponseWriter, r *http.Request, p http
return nil, trace.Wrap(err)
}

// Teleport 8 clients are still expecting the legacy JSON format.
// Teleport 9 clients handle both legacy and new.
// TODO(zmb3) return certs directly in Teleport 10
return auth.LegacyCertsFromProto(certs), nil
}

Expand Down

0 comments on commit e256170

Please sign in to comment.