Skip to content

Commit

Permalink
[v13] Machine ID: GCP Delegated Joining support (#28762)
Browse files Browse the repository at this point in the history
* Add GCP joining support to tbot

* Comment SPAG

* Fix imports

* Actually fix imports
  • Loading branch information
strideynet committed Jul 6, 2023
1 parent 197ad56 commit c7ce1a0
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 43 deletions.
35 changes: 19 additions & 16 deletions lib/auth/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/google/uuid"
"github.com/gravitational/trace"
"golang.org/x/exp/slices"

"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
Expand Down Expand Up @@ -262,6 +263,18 @@ func (s *Server) getBotUsers(ctx context.Context) ([]types.User, error) {
return botUsers, nil
}

// supportedBotJoinMethods should match SupportedJoinMethods declared in
// lib/tbot/config
var supportedBotJoinMethods = []types.JoinMethod{
types.JoinMethodToken,
types.JoinMethodAzure,
types.JoinMethodCircleCI,
types.JoinMethodGCP,
types.JoinMethodGitHub,
types.JoinMethodGitLab,
types.JoinMethodIAM,
}

// checkOrCreateBotToken checks the existing token if given, or creates a new
// random dynamic provision token which allows bots to join with the given
// botName. Returns the token and any error.
Expand All @@ -286,24 +299,14 @@ func (s *Server) checkOrCreateBotToken(ctx context.Context, req *proto.CreateBot
return nil, trace.BadParameter("token %q is valid for bot with name %q, not %q",
req.TokenID, provisionToken.GetBotName(), botName)
}
switch provisionToken.GetJoinMethod() {
case types.JoinMethodToken,
types.JoinMethodIAM,
types.JoinMethodGitHub,
types.JoinMethodGitLab,
types.JoinMethodAzure,
types.JoinMethodCircleCI:
default:

if !slices.Contains(supportedBotJoinMethods, provisionToken.GetJoinMethod()) {
return nil, trace.BadParameter(
"token %q has join method %q which is not supported for bots. Supported join methods are %v",
req.TokenID, provisionToken.GetJoinMethod(), []types.JoinMethod{
types.JoinMethodToken,
types.JoinMethodIAM,
types.JoinMethodGitHub,
types.JoinMethodGitLab,
types.JoinMethodAzure,
types.JoinMethodCircleCI,
})
req.TokenID,
provisionToken.GetJoinMethod(),
supportedBotJoinMethods,
)
}
return provisionToken, nil
}
Expand Down
49 changes: 22 additions & 27 deletions lib/auth/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"strings"

"github.com/gravitational/trace"
"golang.org/x/exp/slices"

"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
Expand Down Expand Up @@ -180,39 +181,33 @@ func (a *Server) generateCertsBot(
// botResourceName must be set, enforced in CheckAndSetDefaults
botName := provisionToken.GetBotName()
joinMethod := provisionToken.GetJoinMethod()
// Append `bot-` to the bot name to derive its username.
botResourceName := BotResourceName(botName)

expires := a.GetClock().Now().Add(defaults.DefaultRenewableCertTTL)
if req.Expires != nil {
expires = *req.Expires
// Check this is a join method for bots we support.
if !slices.Contains(supportedBotJoinMethods, joinMethod) {
return nil, trace.BadParameter(
"unsupported join method %q for bot", joinMethod,
)
}

// Repeatable join methods (e.g IAM) should not produce renewable
// certificates. Ephemeral join methods (e.g Token) should produce
// renewable certificates, but the token should be deleted after use.
var renewable bool
var shouldDeleteToken bool
switch joinMethod {
case types.JoinMethodToken:
// Most join methods produce non-renewable certificates and join must be
// called again to fetch fresh certificates with a longer lifetime. These
// join methods do not delete the token after use.
renewable := false
shouldDeleteToken := false
if joinMethod == types.JoinMethodToken {
// The token join method is special and produces renewable certificates
// but the token is deleted after use.
shouldDeleteToken = true
renewable = true
case types.JoinMethodIAM,
types.JoinMethodGitHub,
types.JoinMethodGitLab,
types.JoinMethodCircleCI,
types.JoinMethodKubernetes,
types.JoinMethodAzure,
types.JoinMethodGCP:
shouldDeleteToken = false
renewable = false
default:
return nil, trace.BadParameter(
"unsupported join method %q for bot", joinMethod,
)
}

expires := a.GetClock().Now().Add(defaults.DefaultRenewableCertTTL)
if req.Expires != nil {
expires = *req.Expires
}

certs, err := a.generateInitialBotCerts(
ctx, botResourceName, req.PublicSSHKey, expires, renewable,
ctx, BotResourceName(botName), req.PublicSSHKey, expires, renewable,
)
if err != nil {
return nil, trace.Wrap(err)
Expand All @@ -237,7 +232,7 @@ func (a *Server) generateCertsBot(
Status: apievents.Status{
Success: true,
},
BotName: provisionToken.GetBotName(),
BotName: botName,
Method: string(joinMethod),
TokenName: provisionToken.GetSafeName(),
}
Expand Down
1 change: 1 addition & 0 deletions lib/tbot/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const (
var SupportedJoinMethods = []string{
string(types.JoinMethodAzure),
string(types.JoinMethodCircleCI),
string(types.JoinMethodGCP),
string(types.JoinMethodGitHub),
string(types.JoinMethodGitLab),
string(types.JoinMethodIAM),
Expand Down

0 comments on commit c7ce1a0

Please sign in to comment.