Skip to content

Commit

Permalink
[vnet] add windows tsh cli commands
Browse files Browse the repository at this point in the history
This PR refactors the VNet tsh CLI commands and adds stubs for the
commands that are going to be added for Windows VNet support.
  • Loading branch information
nklaassen committed Jan 10, 2025
1 parent 80732b4 commit 4e228f7
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 142 deletions.
27 changes: 18 additions & 9 deletions tool/tsh/common/tsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -1258,9 +1258,12 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error {

workloadIdentityCmd := newSVIDCommands(app)

vnetCmd := newVnetCommand(app)
vnetAdminSetupCmd := newVnetAdminSetupCommand(app)
vnetDaemonCmd := newVnetDaemonCommand(app)
vnetCommand := newVnetCommand(app)
vnetAdminSetupCommand := newVnetAdminSetupCommand(app)
vnetDaemonCommand := newPlatformVnetDaemonCommand(app)
vnetInstallServiceCommand := newVnetInstallServiceCommand(app)
vnetUninstallServiceCommand := newVnetUninstallServiceCommand(app)
vnetServiceCommand := newVnetServiceCommand(app)

gitCmd := newGitCommands(app)

Expand Down Expand Up @@ -1638,12 +1641,18 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error {
err = onHeadlessApprove(&cf)
case workloadIdentityCmd.issue.FullCommand():
err = workloadIdentityCmd.issue.run(&cf)
case vnetCmd.FullCommand():
err = vnetCmd.run(&cf)
case vnetAdminSetupCmd.FullCommand():
err = vnetAdminSetupCmd.run(&cf)
case vnetDaemonCmd.FullCommand():
err = vnetDaemonCmd.run(&cf)
case vnetCommand.FullCommand():
err = vnetCommand.run(&cf)
case vnetAdminSetupCommand.FullCommand():
err = vnetAdminSetupCommand.run(&cf)
case vnetDaemonCommand.FullCommand():
err = vnetDaemonCommand.run(&cf)
case vnetInstallServiceCommand.FullCommand():
err = vnetInstallServiceCommand.run(&cf)
case vnetUninstallServiceCommand.FullCommand():
err = vnetUninstallServiceCommand.run(&cf)
case vnetServiceCommand.FullCommand():
err = vnetServiceCommand.run(&cf)
case gitCmd.list.FullCommand():
err = gitCmd.list.run(&cf)
case gitCmd.login.FullCommand():
Expand Down
94 changes: 94 additions & 0 deletions tool/tsh/common/vnet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Teleport
// Copyright (C) 2024 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package common

import (
"fmt"

"github.com/alecthomas/kingpin/v2"
"github.com/gravitational/trace"

"github.com/gravitational/teleport/lib/vnet"
)

type vnetCLICommand interface {
// FullCommand matches the signature of kingpin.CmdClause.FullCommand, which
// most commands should embed.
FullCommand() string
// run should be called iff FullCommand() matches the CLI parameters.
run(cf *CLIConf) error
}

// vnetCommand implements the `tsh vnet` command to run VNet.
type vnetCommand struct {
*kingpin.CmdClause
}

func newVnetCommand(app *kingpin.Application) *vnetCommand {
cmd := &vnetCommand{
CmdClause: app.Command("vnet", "Start Teleport VNet, a virtual network for TCP application access."),
}
return cmd
}

func (c *vnetCommand) run(cf *CLIConf) error {
appProvider, err := newVnetAppProvider(cf)
if err != nil {
return trace.Wrap(err)
}
processManager, err := vnet.Run(cf.Context, &vnet.RunConfig{AppProvider: appProvider})
if err != nil {
return trace.Wrap(err)
}
go func() {
<-cf.Context.Done()
processManager.Close()
}()
fmt.Println("VNet is ready.")
return trace.Wrap(processManager.Wait())
}

func newVnetAdminSetupCommand(app *kingpin.Application) vnetCLICommand {
return newPlatformVnetAdminSetupCommand(app)
}

func newVnetDaemonCommand(app *kingpin.Application) vnetCLICommand {
return newPlatformVnetDaemonCommand(app)
}

func newVnetInstallServiceCommand(app *kingpin.Application) vnetCLICommand {
return newPlatformVnetInstallServiceCommand(app)
}

func newVnetUninstallServiceCommand(app *kingpin.Application) vnetCLICommand {
return newPlatformVnetUninstallServiceCommand(app)
}

func newVnetServiceCommand(app *kingpin.Application) vnetCLICommand {
return newPlatformVnetServiceCommand(app)
}

// vnetCommandNotSupported implements vnetCLICommand, it is returned when a specific
// command is not implemented for a certain platform or environment.
type vnetCommandNotSupported struct{}

func (vnetCommandNotSupported) FullCommand() string {
return ""
}
func (vnetCommandNotSupported) run(*CLIConf) error {
panic("vnetCommandNotSupported.run should never be called, this is a bug")
}
4 changes: 3 additions & 1 deletion tool/tsh/common/vnet_daemon_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ const (
vnetDaemonSubCommand = "vnet-daemon"
)

// vnetDaemonCommand implements the vnet-daemon subcommand to run the VNet MacOS
// daemon.
type vnetDaemonCommand struct {
*kingpin.CmdClause
// Launch daemons added through SMAppService are launched from a static .plist file, hence
// why this command does not accept any arguments.
// Instead, the daemon expects the arguments to be sent over XPC from an unprivileged process.
}

func newVnetDaemonCommand(app *kingpin.Application) *vnetDaemonCommand {
func newPlatformVnetDaemonCommand(app *kingpin.Application) *vnetDaemonCommand {
return &vnetDaemonCommand{
CmdClause: app.Command(vnetDaemonSubCommand, "Start the VNet daemon").Hidden(),
}
Expand Down
50 changes: 16 additions & 34 deletions tool/tsh/common/vnet_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package common

import (
"fmt"
"os"

"github.com/alecthomas/kingpin/v2"
Expand All @@ -29,38 +28,6 @@ import (
"github.com/gravitational/teleport/lib/vnet/daemon"
)

type vnetCommand struct {
*kingpin.CmdClause
}

func newVnetCommand(app *kingpin.Application) *vnetCommand {
cmd := &vnetCommand{
CmdClause: app.Command("vnet", "Start Teleport VNet, a virtual network for TCP application access."),
}
return cmd
}

func (c *vnetCommand) run(cf *CLIConf) error {
appProvider, err := newVnetAppProvider(cf)
if err != nil {
return trace.Wrap(err)
}

processManager, err := vnet.Run(cf.Context, &vnet.RunConfig{AppProvider: appProvider})
if err != nil {
return trace.Wrap(err)
}

go func() {
<-cf.Context.Done()
processManager.Close()
}()

fmt.Println("VNet is ready.")

return trace.Wrap(processManager.Wait())
}

// vnetAdminSetupCommand is the fallback command ran as root when tsh wasn't compiled with the
// vnetdaemon build tag. This is typically the case when running tsh in development where it's not
// signed and bundled in tsh.app.
Expand All @@ -83,7 +50,7 @@ type vnetAdminSetupCommand struct {
euid int
}

func newVnetAdminSetupCommand(app *kingpin.Application) *vnetAdminSetupCommand {
func newPlatformVnetAdminSetupCommand(app *kingpin.Application) *vnetAdminSetupCommand {
cmd := &vnetAdminSetupCommand{
CmdClause: app.Command(teleport.VnetAdminSetupSubCommand, "Start the VNet admin subprocess.").Hidden(),
}
Expand Down Expand Up @@ -116,3 +83,18 @@ func (c *vnetAdminSetupCommand) run(cf *CLIConf) error {

return trace.Wrap(vnet.RunAdminProcess(cf.Context, config))
}

// the vnet-install-service command is only supported on windows.
func newPlatformVnetInstallServiceCommand(app *kingpin.Application) vnetCommandNotSupported {
return vnetCommandNotSupported{}
}

// the vnet-uninstall-service command is only supported on windows.
func newPlatformVnetUninstallServiceCommand(app *kingpin.Application) vnetCommandNotSupported {
return vnetCommandNotSupported{}
}

// the vnet-service command is only supported on windows.
func newPlatformVnetServiceCommand(app *kingpin.Application) vnetCommandNotSupported {
return vnetCommandNotSupported{}
}
15 changes: 3 additions & 12 deletions tool/tsh/common/vnet_nodaemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,9 @@ package common

import (
"github.com/alecthomas/kingpin/v2"
"github.com/gravitational/trace"
)

func newVnetDaemonCommand(app *kingpin.Application) vnetDaemonNotSupported {
return vnetDaemonNotSupported{}
}

type vnetDaemonNotSupported struct{}

func (vnetDaemonNotSupported) FullCommand() string {
return ""
}
func (vnetDaemonNotSupported) run(*CLIConf) error {
return trace.NotImplemented("tsh was built without support for VNet daemon")
// The vnet-daemon command is only supported with the vnetdaemon tag on darwin.
func newPlatformVnetDaemonCommand(app *kingpin.Application) vnetCommandNotSupported {
return vnetCommandNotSupported{}
}
39 changes: 18 additions & 21 deletions tool/tsh/common/vnet_other.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build !darwin && !windows
// +build !darwin,!windows

// Teleport
// Copyright (C) 2024 Gravitational, Inc.
//
Expand All @@ -17,34 +14,34 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build !darwin && !windows
// +build !darwin,!windows

package common

import (
"github.com/alecthomas/kingpin/v2"
"github.com/gravitational/trace"

"github.com/gravitational/teleport/lib/vnet"
)

func newVnetCommand(app *kingpin.Application) vnetNotSupported {
return vnetNotSupported{}
}
// Satisfy unused linter.
var _ = newVnetAppProvider

func newVnetAdminSetupCommand(app *kingpin.Application) vnetNotSupported {
return vnetNotSupported{}
func newPlatformVnetAdminSetupCommand(app *kingpin.Application) vnetCLICommand {
return commandNotSupported{}
}

type vnetNotSupported struct{}
func newPlatformVnetDaemonCommand(app *kingpin.Application) vnetCLICommand {
return commandNotSupported{}
}

func (vnetNotSupported) FullCommand() string {
return ""
func newPlatformVnetInstallServiceCommand(app *kingpin.Application) vnetCLICommand {
return commandNotSupported{}
}
func (vnetNotSupported) run(*CLIConf) error {
return trace.Wrap(vnet.ErrVnetNotImplemented)

func newPlatformVnetUninstallServiceCommand(app *kingpin.Application) vnetCLICommand {
return commandNotSupported{}
}

var (
// Satisfy unused linter.
_ = (*vnetAppProvider)(nil)
_ = newVnetAppProvider
)
func newPlatformVnetServiceCommand(app *kingpin.Application) vnetCLICommand {
return commandNotSupported{}
}
Loading

0 comments on commit 4e228f7

Please sign in to comment.