Skip to content

Commit

Permalink
Reorganize tctl commands to not require an auth client by default (#4…
Browse files Browse the repository at this point in the history
…8894)

* Reorganize tctl commands to have commands not required auth client

* Replace auth client with lazy loading approach

* Fix linter warning

* Replace camel case in import alias
Replace logrus to use slog

* Rename close function

* Refactor plugin commands to use interface of auth client and plugin client
Code review changes

* Refactor workload identity commands

* Add access to global config for the commands

* Add test checking all tctl commands match process

* Fix golangci-lint warnings
  • Loading branch information
vapopov authored Dec 17, 2024
1 parent 17ffecc commit 45f29a8
Show file tree
Hide file tree
Showing 49 changed files with 1,122 additions and 577 deletions.
4 changes: 2 additions & 2 deletions integration/tctl_terraform_env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func TestTCTLTerraformCommand_ProxyJoin(t *testing.T) {
tctlCommand := common.TerraformCommand{}

app := kingpin.New("test", "test")
tctlCommand.Initialize(app, tctlCfg)
tctlCommand.Initialize(app, nil, tctlCfg)
_, err = app.Parse([]string{"terraform", "env"})
require.NoError(t, err)
// Create io buffer writer
Expand Down Expand Up @@ -179,7 +179,7 @@ func TestTCTLTerraformCommand_AuthJoin(t *testing.T) {
tctlCommand := common.TerraformCommand{}

app := kingpin.New("test", "test")
tctlCommand.Initialize(app, tctlCfg)
tctlCommand.Initialize(app, nil, tctlCfg)
_, err = app.Parse([]string{"terraform", "env"})
require.NoError(t, err)
// Create io buffer writer
Expand Down
31 changes: 21 additions & 10 deletions tool/tctl/common/access_request_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import (
"github.com/gravitational/teleport/lib/service/servicecfg"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/tlsca"
commonclient "github.com/gravitational/teleport/tool/tctl/common/client"
tctlcfg "github.com/gravitational/teleport/tool/tctl/common/config"
)

// AccessRequestCommand implements `tctl users` set of commands
Expand Down Expand Up @@ -76,7 +78,7 @@ type AccessRequestCommand struct {
}

// Initialize allows AccessRequestCommand to plug itself into the CLI parser
func (c *AccessRequestCommand) Initialize(app *kingpin.Application, config *servicecfg.Config) {
func (c *AccessRequestCommand) Initialize(app *kingpin.Application, _ *tctlcfg.GlobalCLIFlags, config *servicecfg.Config) {
c.config = config
requests := app.Command("requests", "Manage access requests.").Alias("request")

Expand Down Expand Up @@ -125,27 +127,36 @@ func (c *AccessRequestCommand) Initialize(app *kingpin.Application, config *serv
}

// TryRun takes the CLI command as an argument (like "access-request list") and executes it.
func (c *AccessRequestCommand) TryRun(ctx context.Context, cmd string, client *authclient.Client) (match bool, err error) {
func (c *AccessRequestCommand) TryRun(ctx context.Context, cmd string, clientFunc commonclient.InitFunc) (match bool, err error) {
var commandFunc func(ctx context.Context, client *authclient.Client) error
switch cmd {
case c.requestList.FullCommand():
err = c.List(ctx, client)
commandFunc = c.List
case c.requestGet.FullCommand():
err = c.Get(ctx, client)
commandFunc = c.Get
case c.requestApprove.FullCommand():
err = c.Approve(ctx, client)
commandFunc = c.Approve
case c.requestDeny.FullCommand():
err = c.Deny(ctx, client)
commandFunc = c.Deny
case c.requestCreate.FullCommand():
err = c.Create(ctx, client)
commandFunc = c.Create
case c.requestDelete.FullCommand():
err = c.Delete(ctx, client)
commandFunc = c.Delete
case c.requestCaps.FullCommand():
err = c.Caps(ctx, client)
commandFunc = c.Caps
case c.requestReview.FullCommand():
err = c.Review(ctx, client)
commandFunc = c.Review
default:
return false, nil
}

client, closeFn, err := clientFunc(ctx)
if err != nil {
return false, trace.Wrap(err)
}
err = commandFunc(ctx, client)
closeFn(ctx)

return true, trace.Wrap(err)
}

Expand Down
16 changes: 12 additions & 4 deletions tool/tctl/common/accessmonitoring/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import (
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/service/servicecfg"
"github.com/gravitational/teleport/lib/utils"
commonclient "github.com/gravitational/teleport/tool/tctl/common/client"
tctlcfg "github.com/gravitational/teleport/tool/tctl/common/config"
)

// Command implements `tctl audit` group of commands.
Expand All @@ -44,7 +46,7 @@ type Command struct {
}

// Initialize allows to implement Command interface.
func (c *Command) Initialize(app *kingpin.Application, cfg *servicecfg.Config) {
func (c *Command) Initialize(app *kingpin.Application, _ *tctlcfg.GlobalCLIFlags, cfg *servicecfg.Config) {
c.innerCmdMap = map[string]runFunc{}

auditCmd := app.Command("audit", "Audit command.")
Expand Down Expand Up @@ -114,13 +116,19 @@ func (c *Command) initAuditReportsCommands(auditCmd *kingpin.CmdClause, cfg *ser

type runFunc func(context.Context, *authclient.Client) error

func (c *Command) TryRun(ctx context.Context, selectedCommand string, authClient *authclient.Client) (match bool, err error) {
handler, ok := c.innerCmdMap[selectedCommand]
func (c *Command) TryRun(ctx context.Context, cmd string, clientFunc commonclient.InitFunc) (match bool, err error) {
handler, ok := c.innerCmdMap[cmd]
if !ok {
return false, nil
}

switch err := trail.FromGRPC(handler(ctx, authClient)); {
client, closeFn, err := clientFunc(ctx)
if err != nil {
return false, trace.Wrap(err)
}
defer closeFn(ctx)

switch err := trail.FromGRPC(handler(ctx, client)); {
case trace.IsNotImplemented(err):
return true, trace.AccessDenied("Access Monitoring requires a Teleport Enterprise Auth Server.")
default:
Expand Down
24 changes: 17 additions & 7 deletions tool/tctl/common/acl_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import (
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/service/servicecfg"
"github.com/gravitational/teleport/lib/utils"
commonclient "github.com/gravitational/teleport/tool/tctl/common/client"
tctlcfg "github.com/gravitational/teleport/tool/tctl/common/config"
)

// ACLCommand implements the `tctl acl` family of commands.
Expand Down Expand Up @@ -64,7 +66,7 @@ const (
)

// Initialize allows ACLCommand to plug itself into the CLI parser
func (c *ACLCommand) Initialize(app *kingpin.Application, _ *servicecfg.Config) {
func (c *ACLCommand) Initialize(app *kingpin.Application, _ *tctlcfg.GlobalCLIFlags, _ *servicecfg.Config) {
acl := app.Command("acl", "Manage access lists.").Alias("access-lists")

c.ls = acl.Command("ls", "List cluster access lists.")
Expand Down Expand Up @@ -93,21 +95,29 @@ func (c *ACLCommand) Initialize(app *kingpin.Application, _ *servicecfg.Config)
}

// TryRun takes the CLI command as an argument (like "acl ls") and executes it.
func (c *ACLCommand) TryRun(ctx context.Context, cmd string, client *authclient.Client) (match bool, err error) {
func (c *ACLCommand) TryRun(ctx context.Context, cmd string, clientFunc commonclient.InitFunc) (match bool, err error) {
var commandFunc func(ctx context.Context, client *authclient.Client) error
switch cmd {
case c.ls.FullCommand():
err = c.List(ctx, client)
commandFunc = c.List
case c.get.FullCommand():
err = c.Get(ctx, client)
commandFunc = c.Get
case c.usersAdd.FullCommand():
err = c.UsersAdd(ctx, client)
commandFunc = c.UsersAdd
case c.usersRemove.FullCommand():
err = c.UsersRemove(ctx, client)
commandFunc = c.UsersRemove
case c.usersList.FullCommand():
err = c.UsersList(ctx, client)
commandFunc = c.UsersList
default:
return false, nil
}
client, closeFn, err := clientFunc(ctx)
if err != nil {
return false, trace.Wrap(err)
}
err = commandFunc(ctx, client)
closeFn(ctx)

return true, trace.Wrap(err)
}

Expand Down
7 changes: 5 additions & 2 deletions tool/tctl/common/admin_action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import (
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/hostid"
tctl "github.com/gravitational/teleport/tool/tctl/common"
tctlcfg "github.com/gravitational/teleport/tool/tctl/common/config"
testserver "github.com/gravitational/teleport/tool/teleport/testenv"
tsh "github.com/gravitational/teleport/tool/tsh/common"
)
Expand Down Expand Up @@ -1156,13 +1157,15 @@ func runTestCase(t *testing.T, ctx context.Context, client *authclient.Client, t

app := utils.InitCLIParser("tctl", tctl.GlobalHelpString)
cfg := servicecfg.MakeDefaultConfig()
tc.cliCommand.Initialize(app, cfg)
tc.cliCommand.Initialize(app, &tctlcfg.GlobalCLIFlags{}, cfg)

args := strings.Split(tc.command, " ")
commandName, err := app.Parse(args)
require.NoError(t, err)

match, err := tc.cliCommand.TryRun(ctx, commandName, client)
match, err := tc.cliCommand.TryRun(ctx, commandName, func(context.Context) (*authclient.Client, func(context.Context), error) {
return client, func(context.Context) {}, nil
})
require.True(t, match)
return err
}
Expand Down
20 changes: 15 additions & 5 deletions tool/tctl/common/alert_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
"github.com/gravitational/teleport/lib/auth/authclient"
libclient "github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/service/servicecfg"
commonclient "github.com/gravitational/teleport/tool/tctl/common/client"
tctlcfg "github.com/gravitational/teleport/tool/tctl/common/config"
)

// AlertCommand implements the `tctl alerts` family of commands.
Expand All @@ -62,7 +64,7 @@ type AlertCommand struct {
}

// Initialize allows AlertCommand to plug itself into the CLI parser
func (c *AlertCommand) Initialize(app *kingpin.Application, config *servicecfg.Config) {
func (c *AlertCommand) Initialize(app *kingpin.Application, _ *tctlcfg.GlobalCLIFlags, config *servicecfg.Config) {
c.config = config
alert := app.Command("alerts", "Manage cluster alerts.").Alias("alert")

Expand Down Expand Up @@ -93,17 +95,25 @@ func (c *AlertCommand) Initialize(app *kingpin.Application, config *servicecfg.C
}

// TryRun takes the CLI command as an argument (like "alerts ls") and executes it.
func (c *AlertCommand) TryRun(ctx context.Context, cmd string, client *authclient.Client) (match bool, err error) {
func (c *AlertCommand) TryRun(ctx context.Context, cmd string, clientFunc commonclient.InitFunc) (match bool, err error) {
var commandFunc func(ctx context.Context, client *authclient.Client) error
switch cmd {
case c.alertList.FullCommand():
err = c.List(ctx, client)
commandFunc = c.List
case c.alertCreate.FullCommand():
err = c.Create(ctx, client)
commandFunc = c.Create
case c.alertAck.FullCommand():
err = c.Ack(ctx, client)
commandFunc = c.Ack
default:
return false, nil
}
client, closeFn, err := clientFunc(ctx)
if err != nil {
return false, trace.Wrap(err)
}
err = commandFunc(ctx, client)
closeFn(ctx)

return true, trace.Wrap(err)
}

Expand Down
16 changes: 13 additions & 3 deletions tool/tctl/common/app_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import (
libclient "github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/service/servicecfg"
"github.com/gravitational/teleport/lib/utils"
commonclient "github.com/gravitational/teleport/tool/tctl/common/client"
tctlcfg "github.com/gravitational/teleport/tool/tctl/common/config"
)

// AppsCommand implements "tctl apps" group of commands.
Expand All @@ -55,7 +57,7 @@ type AppsCommand struct {
}

// Initialize allows AppsCommand to plug itself into the CLI parser
func (c *AppsCommand) Initialize(app *kingpin.Application, config *servicecfg.Config) {
func (c *AppsCommand) Initialize(app *kingpin.Application, _ *tctlcfg.GlobalCLIFlags, config *servicecfg.Config) {
c.config = config

apps := app.Command("apps", "Operate on applications registered with the cluster.")
Expand All @@ -68,13 +70,21 @@ func (c *AppsCommand) Initialize(app *kingpin.Application, config *servicecfg.Co
}

// TryRun attempts to run subcommands like "apps ls".
func (c *AppsCommand) TryRun(ctx context.Context, cmd string, client *authclient.Client) (match bool, err error) {
func (c *AppsCommand) TryRun(ctx context.Context, cmd string, clientFunc commonclient.InitFunc) (match bool, err error) {
var commandFunc func(ctx context.Context, client *authclient.Client) error
switch cmd {
case c.appsList.FullCommand():
err = c.ListApps(ctx, client)
commandFunc = c.ListApps
default:
return false, nil
}
client, closeFn, err := clientFunc(ctx)
if err != nil {
return false, trace.Wrap(err)
}
err = commandFunc(ctx, client)
closeFn(ctx)

return true, trace.Wrap(err)
}

Expand Down
Loading

0 comments on commit 45f29a8

Please sign in to comment.