mirror of
https://github.com/gravitational/teleport.git
synced 2026-09-24 16:17:11 +08:00
Convert GenerateToken to gRPC. (#9024)
This commit is contained in:
@@ -1842,6 +1842,14 @@ func (c *Client) UpsertToken(ctx context.Context, token types.ProvisionToken) er
|
||||
return trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
// GenerateToken generates a new auth token for the given service roles.
|
||||
// This token can be used by corresponding services to authenticate with
|
||||
// the Auth server and get a signed certificate and private key.
|
||||
func (c *Client) GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (string, error) {
|
||||
resp, err := c.grpc.GenerateToken(ctx, req, c.callOpts...)
|
||||
return resp.Token, trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
// DeleteToken deletes a provision token by name.
|
||||
func (c *Client) DeleteToken(ctx context.Context, name string) error {
|
||||
if name == "" {
|
||||
|
||||
+1309
-643
File diff suppressed because it is too large
Load Diff
@@ -1729,6 +1729,28 @@ message GetClusterCACertResponse {
|
||||
bytes TLSCA = 1 [ (gogoproto.jsontag) = "tls_ca" ];
|
||||
}
|
||||
|
||||
// GenerateTokenRequest is a request to generate auth token.
|
||||
message GenerateTokenRequest {
|
||||
// Token sets the token value. If not set, it will be auto generated.
|
||||
string Token = 1 [ (gogoproto.jsontag) = "token" ];
|
||||
// Roles is a list of roles this token authenticates as.
|
||||
repeated string Roles = 2 [
|
||||
(gogoproto.jsontag) = "roles",
|
||||
(gogoproto.casttype) = "github.com/gravitational/teleport/api/types.SystemRole"
|
||||
];
|
||||
// TTL specifies how long the generated token will be valid for.
|
||||
// Defaults to 30 minutes if not set.
|
||||
int64 TTL = 3 [ (gogoproto.jsontag) = "ttl", (gogoproto.casttype) = "Duration" ];
|
||||
// Labels is a label-based matcher if non-empty.
|
||||
map<string, string> Labels = 4 [ (gogoproto.jsontag) = "labels" ];
|
||||
}
|
||||
|
||||
// GenerateTokenResponse contains a generated auth token.
|
||||
message GenerateTokenResponse {
|
||||
// Token is the generated auth token.
|
||||
string Token = 1 [ (gogoproto.jsontag) = "token" ];
|
||||
}
|
||||
|
||||
// GetOIDCAuthRequestRequest is a request for GetOIDCAuthRequest.
|
||||
message GetOIDCAuthRequestRequest {
|
||||
// StateToken is an oidc auth request state token.
|
||||
@@ -2104,6 +2126,8 @@ service AuthService {
|
||||
rpc GetTokens(google.protobuf.Empty) returns (types.ProvisionTokenV2List);
|
||||
// UpsertToken upserts a token in a backend.
|
||||
rpc UpsertToken(types.ProvisionTokenV2) returns (google.protobuf.Empty);
|
||||
// GenerateToken generates a new auth token.
|
||||
rpc GenerateToken(GenerateTokenRequest) returns (GenerateTokenResponse);
|
||||
// DeleteToken deletes an existing token in a backend described by the given request.
|
||||
rpc DeleteToken(types.ResourceRequest) returns (google.protobuf.Empty);
|
||||
|
||||
|
||||
@@ -733,12 +733,13 @@ func (s *APIServer) generateHostCert(auth ClientI, w http.ResponseWriter, r *htt
|
||||
return string(cert), nil
|
||||
}
|
||||
|
||||
// DELETE IN 11.0.0
|
||||
func (s *APIServer) generateToken(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (interface{}, error) {
|
||||
var req GenerateTokenRequest
|
||||
var req proto.GenerateTokenRequest
|
||||
if err := httplib.ReadJSON(r, &req); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
token, err := auth.GenerateToken(r.Context(), req)
|
||||
token, err := auth.GenerateToken(r.Context(), &req)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
+10
-32
@@ -1970,46 +1970,24 @@ func (a *Server) CreateWebSession(user string) (types.WebSession, error) {
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// GenerateTokenRequest is a request to generate auth token
|
||||
type GenerateTokenRequest struct {
|
||||
// Token if provided sets the token value, otherwise will be auto generated
|
||||
Token string `json:"token"`
|
||||
// Roles is a list of roles this token authenticates as
|
||||
Roles types.SystemRoles `json:"roles"`
|
||||
// TTL is a time to live for token
|
||||
TTL time.Duration `json:"ttl"`
|
||||
// Labels sets token labels, e.g. {env: prod, region: us-west}.
|
||||
// Labels are later passed to resources that are joining
|
||||
// e.g. remote clusters and in the future versions, nodes and proxies.
|
||||
Labels map[string]string `json:"labels"`
|
||||
}
|
||||
// GenerateToken generates multi-purpose authentication token.
|
||||
func (a *Server) GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (string, error) {
|
||||
expires := a.clock.Now().UTC()
|
||||
if req.TTL != 0 {
|
||||
expires.Add(req.TTL.Get())
|
||||
} else {
|
||||
expires.Add(defaults.ProvisioningTokenTTL)
|
||||
}
|
||||
|
||||
// CheckAndSetDefaults checks and sets default values of request
|
||||
func (req *GenerateTokenRequest) CheckAndSetDefaults() error {
|
||||
for _, role := range req.Roles {
|
||||
if err := role.Check(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
if req.TTL == 0 {
|
||||
req.TTL = defaults.ProvisioningTokenTTL
|
||||
}
|
||||
if req.Token == "" {
|
||||
token, err := utils.CryptoRandomHex(TokenLenBytes)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
req.Token = token
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateToken generates multi-purpose authentication token.
|
||||
func (a *Server) GenerateToken(ctx context.Context, req GenerateTokenRequest) (string, error) {
|
||||
if err := req.CheckAndSetDefaults(); err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
token, err := types.NewProvisionToken(req.Token, req.Roles, a.clock.Now().UTC().Add(req.TTL))
|
||||
token, err := types.NewProvisionToken(req.Token, req.Roles, expires)
|
||||
if err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
|
||||
@@ -561,7 +561,7 @@ func TestTokensCRUD(t *testing.T) {
|
||||
require.Empty(t, btokens, 0)
|
||||
|
||||
// generate persistent token
|
||||
tokenName, err := s.a.GenerateToken(ctx, GenerateTokenRequest{Roles: types.SystemRoles{types.RoleNode}})
|
||||
tokenName, err := s.a.GenerateToken(ctx, &proto.GenerateTokenRequest{Roles: types.SystemRoles{types.RoleNode}})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tokenName, 2*TokenLenBytes)
|
||||
tokens, err := s.a.GetTokens(ctx)
|
||||
@@ -577,7 +577,7 @@ func TestTokensCRUD(t *testing.T) {
|
||||
|
||||
// generate predefined token
|
||||
customToken := "custom-token"
|
||||
tokenName, err = s.a.GenerateToken(ctx, GenerateTokenRequest{Roles: types.SystemRoles{types.RoleNode}, Token: customToken})
|
||||
tokenName, err = s.a.GenerateToken(ctx, &proto.GenerateTokenRequest{Roles: types.SystemRoles{types.RoleNode}, Token: customToken})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tokenName, customToken)
|
||||
|
||||
@@ -629,7 +629,7 @@ func TestBadTokens(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
|
||||
// tampered
|
||||
tok, err := s.a.GenerateToken(ctx, GenerateTokenRequest{Roles: types.SystemRoles{types.RoleAuth}})
|
||||
tok, err := s.a.GenerateToken(ctx, &proto.GenerateTokenRequest{Roles: types.SystemRoles{types.RoleAuth}})
|
||||
require.NoError(t, err)
|
||||
|
||||
tampered := string(tok[0]+1) + tok[1:]
|
||||
@@ -643,13 +643,13 @@ func TestGenerateTokenEventsEmitted(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
// test trusted cluster token emit
|
||||
_, err := s.a.GenerateToken(ctx, GenerateTokenRequest{Roles: types.SystemRoles{types.RoleTrustedCluster}})
|
||||
_, err := s.a.GenerateToken(ctx, &proto.GenerateTokenRequest{Roles: types.SystemRoles{types.RoleTrustedCluster}})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, s.mockEmitter.LastEvent().GetType(), events.TrustedClusterTokenCreateEvent)
|
||||
s.mockEmitter.Reset()
|
||||
|
||||
// test emit with multiple roles
|
||||
_, err = s.a.GenerateToken(ctx, GenerateTokenRequest{Roles: types.SystemRoles{
|
||||
_, err = s.a.GenerateToken(ctx, &proto.GenerateTokenRequest{Roles: types.SystemRoles{
|
||||
types.RoleNode,
|
||||
types.RoleTrustedCluster,
|
||||
types.RoleAuth,
|
||||
|
||||
@@ -570,7 +570,7 @@ func (a *ServerWithRoles) DeactivateCertAuthority(id types.CertAuthID) error {
|
||||
}
|
||||
|
||||
// GenerateToken generates multi-purpose authentication token.
|
||||
func (a *ServerWithRoles) GenerateToken(ctx context.Context, req GenerateTokenRequest) (string, error) {
|
||||
func (a *ServerWithRoles) GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (string, error) {
|
||||
if err := a.action(apidefaults.Namespace, types.KindToken, types.VerbCreate); err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
|
||||
+1
-21
@@ -464,26 +464,6 @@ func (c *Client) DeactivateCertAuthority(id types.CertAuthID) error {
|
||||
return trace.NotImplemented(notImplementedMessage)
|
||||
}
|
||||
|
||||
// GenerateToken creates a special provisioning token for a new SSH server
|
||||
// that is valid for ttl period seconds.
|
||||
//
|
||||
// This token is used by SSH server to authenticate with Auth server
|
||||
// and get signed certificate and private key from the auth server.
|
||||
//
|
||||
// If token is not supplied, it will be auto generated and returned.
|
||||
// If TTL is not supplied, token will be valid until removed.
|
||||
func (c *Client) GenerateToken(ctx context.Context, req GenerateTokenRequest) (string, error) {
|
||||
out, err := c.PostJSON(ctx, c.Endpoint("tokens"), req)
|
||||
if err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
var token string
|
||||
if err := json.Unmarshal(out.Bytes(), &token); err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// RegisterUsingToken calls the auth service API to register a new node using a registration token
|
||||
// which was previously issued via GenerateToken.
|
||||
func (c *Client) RegisterUsingToken(ctx context.Context, req *types.RegisterUsingTokenRequest) (*proto.Certs, error) {
|
||||
@@ -1573,7 +1553,7 @@ type IdentityService interface {
|
||||
//
|
||||
// If token is not supplied, it will be auto generated and returned.
|
||||
// If TTL is not supplied, token will be valid until removed.
|
||||
GenerateToken(ctx context.Context, req GenerateTokenRequest) (string, error)
|
||||
GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (string, error)
|
||||
|
||||
// GenerateHostCert takes the public key in the Open SSH ``authorized_keys``
|
||||
// plain text format, signs it using Host Certificate Authority private key and returns the
|
||||
|
||||
@@ -2788,6 +2788,21 @@ func (g *GRPCServer) UpsertToken(ctx context.Context, token *types.ProvisionToke
|
||||
return &empty.Empty{}, nil
|
||||
}
|
||||
|
||||
// GenerateToken generates a new auth token.
|
||||
func (g *GRPCServer) GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (*proto.GenerateTokenResponse, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
token, err := auth.ServerWithRoles.GenerateToken(ctx, req)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return &proto.GenerateTokenResponse{Token: token}, nil
|
||||
}
|
||||
|
||||
// DeleteToken deletes a token by name.
|
||||
func (g *GRPCServer) DeleteToken(ctx context.Context, req *types.ResourceRequest) (*empty.Empty, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
|
||||
@@ -75,6 +75,30 @@ func (c *Client) GetClusterCACert(ctx context.Context) (*proto.GetClusterCACertR
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DELETE IN 11.0.0, to remove fallback and grpc call is already defined in api/client/client.go
|
||||
//
|
||||
// GenerateToken generates a new auth token for the given service roles.
|
||||
// This token can be used by corresponding services to authenticate with
|
||||
// the Auth server and get a signed certificate and private key.
|
||||
func (c *Client) GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (string, error) {
|
||||
switch resp, err := c.APIClient.GenerateToken(ctx, req); {
|
||||
case err == nil:
|
||||
return resp, nil
|
||||
case !trace.IsNotImplemented(err):
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
|
||||
out, err := c.PostJSON(ctx, c.Endpoint("tokens"), req)
|
||||
if err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
var token string
|
||||
if err := json.Unmarshal(out.Bytes(), &token); err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// CreateOIDCAuthRequest creates OIDCAuthRequest.
|
||||
// DELETE IN 11.0.0
|
||||
func (c *Client) CreateOIDCAuthRequest(ctx context.Context, req types.OIDCAuthRequest) (*types.OIDCAuthRequest, error) {
|
||||
|
||||
@@ -52,9 +52,9 @@ func TestAuth_RegisterUsingToken(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a dynamic token
|
||||
dynamicToken, err := a.GenerateToken(ctx, GenerateTokenRequest{
|
||||
dynamicToken, err := a.GenerateToken(ctx, &proto.GenerateTokenRequest{
|
||||
Roles: types.SystemRoles{types.RoleNode},
|
||||
TTL: time.Hour,
|
||||
TTL: proto.Duration(time.Hour),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, dynamicToken)
|
||||
|
||||
@@ -1074,7 +1074,7 @@ func (s *TLSSuite) TestTokens(c *check.C) {
|
||||
clt, err := s.server.NewClient(TestAdmin())
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
out, err := clt.GenerateToken(ctx, GenerateTokenRequest{Roles: types.SystemRoles{types.RoleNode}})
|
||||
out, err := clt.GenerateToken(ctx, &proto.GenerateTokenRequest{Roles: types.SystemRoles{types.RoleNode}})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(len(out), check.Not(check.Equals), 0)
|
||||
}
|
||||
@@ -2301,11 +2301,11 @@ func (s *TLSSuite) TestTLSFailover(c *check.C) {
|
||||
func (s *TLSSuite) TestRegisterCAPin(c *check.C) {
|
||||
ctx := context.Background()
|
||||
// Generate a token to use.
|
||||
token, err := s.server.AuthServer.AuthServer.GenerateToken(ctx, GenerateTokenRequest{
|
||||
token, err := s.server.AuthServer.AuthServer.GenerateToken(ctx, &proto.GenerateTokenRequest{
|
||||
Roles: types.SystemRoles{
|
||||
types.RoleProxy,
|
||||
},
|
||||
TTL: time.Hour,
|
||||
TTL: proto.Duration(time.Hour),
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
@@ -2436,11 +2436,11 @@ func (s *TLSSuite) TestRegisterCAPin(c *check.C) {
|
||||
func (s *TLSSuite) TestRegisterCAPath(c *check.C) {
|
||||
ctx := context.Background()
|
||||
// Generate a token to use.
|
||||
token, err := s.server.AuthServer.AuthServer.GenerateToken(ctx, GenerateTokenRequest{
|
||||
token, err := s.server.AuthServer.AuthServer.GenerateToken(ctx, &proto.GenerateTokenRequest{
|
||||
Roles: types.SystemRoles{
|
||||
types.RoleProxy,
|
||||
},
|
||||
TTL: time.Hour,
|
||||
TTL: proto.Duration(time.Hour),
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
||||
@@ -223,9 +223,9 @@ func (h *Handler) getAppJoinScriptHandle(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
|
||||
func createJoinToken(ctx context.Context, m nodeAPIGetter, roles types.SystemRoles) (*nodeJoinToken, error) {
|
||||
req := auth.GenerateTokenRequest{
|
||||
req := &proto.GenerateTokenRequest{
|
||||
Roles: roles,
|
||||
TTL: defaults.NodeJoinTokenTTL,
|
||||
TTL: proto.Duration(defaults.NodeJoinTokenTTL),
|
||||
}
|
||||
|
||||
token, err := m.GenerateToken(ctx, req)
|
||||
@@ -372,7 +372,7 @@ type nodeAPIGetter interface {
|
||||
//
|
||||
// If token is not supplied, it will be auto generated and returned.
|
||||
// If TTL is not supplied, token will be valid until removed.
|
||||
GenerateToken(ctx context.Context, req auth.GenerateTokenRequest) (string, error)
|
||||
GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (string, error)
|
||||
|
||||
// GetClusterCACert returns the CAs for the local cluster without signing keys.
|
||||
GetClusterCACert(ctx context.Context) (*proto.GetClusterCACertResponse, error)
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
|
||||
"github.com/gravitational/teleport/api/client/proto"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/lib/auth"
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/fixtures"
|
||||
"github.com/gravitational/trace"
|
||||
@@ -33,7 +32,7 @@ import (
|
||||
|
||||
func TestCreateNodeJoinToken(t *testing.T) {
|
||||
m := &mockedNodeAPIGetter{}
|
||||
m.mockGenerateToken = func(ctx context.Context, req auth.GenerateTokenRequest) (string, error) {
|
||||
m.mockGenerateToken = func(ctx context.Context, req *proto.GenerateTokenRequest) (string, error) {
|
||||
return "some-token-id", nil
|
||||
}
|
||||
|
||||
@@ -620,12 +619,12 @@ func TestIsSameRuleSet(t *testing.T) {
|
||||
}
|
||||
|
||||
type mockedNodeAPIGetter struct {
|
||||
mockGenerateToken func(ctx context.Context, req auth.GenerateTokenRequest) (string, error)
|
||||
mockGenerateToken func(ctx context.Context, req *proto.GenerateTokenRequest) (string, error)
|
||||
mockGetProxyServers func() ([]types.Server, error)
|
||||
mockGetClusterCACert func(ctx context.Context) (*proto.GetClusterCACertResponse, error)
|
||||
}
|
||||
|
||||
func (m *mockedNodeAPIGetter) GenerateToken(ctx context.Context, req auth.GenerateTokenRequest) (string, error) {
|
||||
func (m *mockedNodeAPIGetter) GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (string, error) {
|
||||
if m.mockGenerateToken != nil {
|
||||
return m.mockGenerateToken(ctx, req)
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ func (c *NodeCommand) Invite(ctx context.Context, client auth.ClientI) error {
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
token, err := client.GenerateToken(ctx, auth.GenerateTokenRequest{Roles: roles, TTL: c.ttl, Token: c.token})
|
||||
token, err := client.GenerateToken(ctx, &proto.GenerateTokenRequest{Roles: roles, TTL: proto.Duration(c.ttl), Token: c.token})
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/gravitational/teleport"
|
||||
"github.com/gravitational/teleport/api/client/proto"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/lib/asciitable"
|
||||
"github.com/gravitational/teleport/lib/auth"
|
||||
@@ -157,9 +158,9 @@ func (c *TokensCommand) Add(ctx context.Context, client auth.ClientI) error {
|
||||
}
|
||||
|
||||
// Generate token.
|
||||
token, err := client.GenerateToken(ctx, auth.GenerateTokenRequest{
|
||||
token, err := client.GenerateToken(ctx, &proto.GenerateTokenRequest{
|
||||
Roles: roles,
|
||||
TTL: c.ttl,
|
||||
TTL: proto.Duration(c.ttl),
|
||||
Token: c.value,
|
||||
Labels: labels,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user