Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vnet] add windows tsh cli commands #50935

Merged
merged 5 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Friendly reminder to update your templates (if any) to 2025. I suppose this was written in 2024 so it's probably fine? (Obligatory I'm not a lawyer.)

//
// 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()
}()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could alternatively use context.AfterFunc.

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
Loading