diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 30228662844..5672f592d5d 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -326,32 +326,45 @@ func (s *AuthServer) RegisterUsingToken(token, hostID string, role teleport.Role if err := role.Check(); err != nil { return nil, trace.Wrap(err) } - // find the token: - tok, err := s.Provisioner.GetToken(token) - if err != nil { - log.Warningf("[AUTH] Node `%v` cannot join: token error. %v", hostID, err) - return nil, trace.Wrap(err) + // check against static tokens first: + foundStaticToken := false + for _, st := range s.StaticTokens { + if st.Value == token { + if st.Roles.Include(role) { + foundStaticToken = true + break + } + } } - // check token's role: - if !tok.Roles.Include(role) { - return nil, trace.BadParameter("token.Role: role does not match") - } - // check token TTL: - if tok.TTL > 0 { - now := s.clock.Now().UTC() - if tok.Created.Add(tok.TTL).Before(now) { - err = s.DeleteToken(token) - if err != nil { + // look for the generated token in the token storage: + if !foundStaticToken { + tok, err := s.Provisioner.GetToken(token) + if err != nil { + log.Warningf("[AUTH] Node `%v` cannot join: token error. %v", hostID, err) + return nil, trace.Wrap(err) + } + // check token's role: + if !tok.Roles.Include(role) { + return nil, trace.BadParameter("token.Role: role does not match") + } + // check token TTL: + if tok.TTL > 0 { + now := s.clock.Now().UTC() + if tok.Created.Add(tok.TTL).Before(now) { + err = s.DeleteToken(token) + if err != nil { + log.Error(err) + } + return nil, trace.Errorf("token expired") + } + // TTL==0? this is a single-use token: delete it + } else { + if err = s.DeleteToken(token); err != nil { log.Error(err) } - return nil, trace.Errorf("token expired") - } - // TTL==0? this is a single-use token: delete it - } else { - if err = s.DeleteToken(token); err != nil { - log.Error(err) } } + keys, err := s.GenerateServerKeys(hostID, teleport.Roles{role}) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/auth/auth_test.go b/lib/auth/auth_test.go index e5bb7fc47f1..2716173bd93 100644 --- a/lib/auth/auth_test.go +++ b/lib/auth/auth_test.go @@ -156,6 +156,13 @@ func (s *AuthSuite) TestTokensCRUD(c *C) { // expired token should be gone now err = s.a.DeleteToken(multiUseToken) c.Assert(trace.IsNotFound(err), Equals, true, Commentf("%#v", err)) + + // lets use static tokens now + s.a.StaticTokens = append(s.a.StaticTokens, StaticToken{Value: "static-token-value", Roles: teleport.Roles{teleport.RoleProxy}}) + _, err = s.a.RegisterUsingToken("static-token-value", "static.host", teleport.RoleProxy) + c.Assert(err, IsNil) + _, err = s.a.RegisterUsingToken("static-token-value", "wrong.role", teleport.RoleAuth) + c.Assert(err, NotNil) } func (s *AuthSuite) TestBadTokens(c *C) { diff --git a/tool/tctl/main.go b/tool/tctl/main.go index 1c02b35be10..0b3d2f5494d 100644 --- a/tool/tctl/main.go +++ b/tool/tctl/main.go @@ -132,7 +132,7 @@ func main() { nodes := app.Command("nodes", "Issue invites for other nodes to join the cluster") nodeAdd := nodes.Command("add", "Generates an invitation token. Use it to add a new node to the Teleport cluster") nodeAdd.Flag("roles", "Comma-separated list of roles for the new node to assume [node]").Default("node").StringVar(&cmdNodes.roles) - nodeAdd.Flag("ttl", "Time to live for a generated token [15m]").Default("15m").DurationVar(&cmdNodes.ttl) + nodeAdd.Flag("ttl", "Time to live for a generated token").DurationVar(&cmdNodes.ttl) nodeAdd.Flag("count", "add count tokens and output JSON with the list").Hidden().Default("1").IntVar(&cmdNodes.count) nodeAdd.Flag("format", "output format, 'text' or 'json'").Hidden().Default("text").StringVar(&cmdNodes.format) nodeAdd.Alias(AddNodeHelp) @@ -334,11 +334,6 @@ func (u *NodeCommand) Invite(client *auth.TunClient) error { if err != nil { return trace.Wrap(err) } - // parse --ttl flag - if u.ttl == time.Duration(0) { - u.ttl = defaults.MaxProvisioningTokenTTL - } - var tokens []string for i := 0; i < u.count; i++ { token, err := client.GenerateToken(roles, u.ttl) diff --git a/tool/tctl/usage.go b/tool/tctl/usage.go index 75a7649ef09..1eae4c0068d 100644 --- a/tool/tctl/usage.go +++ b/tool/tctl/usage.go @@ -31,12 +31,12 @@ Examples: > tctl nodes add Generates a token when can be used to add a regular SSH node to the cluster. - The token will be valid for 15 minutes. + The token genrated single-use token will be valid for 30 minutes. > tctl nodes add --roles=node,proxy --ttl=1h Generates a token when can be used to add an SSH node to the cluster which - will also be a proxy node. The token can be used multiple times within an + will also be a proxy node. This token can be used multiple times within an hour. ` ListNodesHelp = `Notes: