Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var WebshCmd = &cobra.Command{ Use: "websh [flags] [USER@]SERVER [COMMAND]", Short: "Open a websh terminal or execute a command on a server", Long: `Open a websh terminal for interacting with a server or execute a command directly on the server. Supports SSH-like user@host syntax for specifying the username inline. For executing commands, it is highly recommended to wrap the entire command string in quotes to ensure it is interpreted correctly on the remote server. Shell metacharacters (;, |, &, $) pass through unquoted to the remote shell. To send a literal metacharacter, wrap the argument in quotes: alpacon websh server 'echo hello;world' Executing a command (SERVER followed by COMMAND) runs through the same executor as 'alpacon exec'—identical output, exit codes, and sudo-approval handling. Command execution does not accept exec-only flags such as --detach or --wait. Exit code 3 indicates a WorkSession gate denial; run with --output json to parse a machine-readable diagnostic on stderr. Exit code 4 indicates the sudo command is pending human approval; approve it in the Alpacon console (web), then re-run—or use 'alpacon exec --wait' to block. Requires an active WorkSession when using Browser login (Auth0); Token auth (API token or Service token) bypasses this requirement.`, Example: ` # Open a websh terminal alpacon websh my-server # Open as root using SSH-like syntax alpacon websh root@my-server # Open with specific user and group alpacon websh admin@my-server alpacon websh -u admin -g developers my-server # Execute a command on a server alpacon websh my-server "ls -la /var/log" alpacon websh root@my-server "systemctl status nginx" # Pass a secret via the shell env; the value stays off the alpacon command line # and out of the session recording. psql reads PGPASSWORD directly from the env. export PGPASSWORD=hunter2 alpacon websh --env="PGPASSWORD" my-server 'psql -h localhost -U app -c "SELECT 1"' # Share terminal session alpacon websh --share my-server alpacon websh --share --read-only=true my-server # Join an existing shared session alpacon websh join --url https://myws.us1.alpacon.io/websh/shared/abcd1234?channel=default --password my-session-pass # Session management alpacon websh ls # List active sessions alpacon websh describe SESSION_ID # Show session details alpacon websh watch SESSION_ID # Watch a session (read-only, staff/superuser only) alpacon websh invite SESSION_ID --email user@example.com alpacon websh close SESSION_ID # Close a session alpacon websh force-close SESSION_ID # Force close (admin only) Flags: -u, --username [USER_NAME] Specify the username for command execution. -g, --groupname [GROUP_NAME] Specify the group name for command execution. --env="KEY" Pass an environment variable, reading its value from the current shell. This keeps the value off the alpacon command line and out of the audit log—use it for secrets such as passwords or tokens. --env="KEY=VALUE" Set 'KEY' to a literal value. Discouraged: the value is written on the command line and recorded verbatim in the audit log. Never pass credentials this way. -s, --share Share the terminal via a temporary link. --read-only=[true|false] Set shared session to read-only (default: false). --work-session [UUID] Attach this session to a work-session. Overrides the workspace's active session set via 'alpacon work-session use'. Note: All flags must be placed before the server name. Everything after the server name is treated as the remote command.`, DisableFlagParsing: true, Run: func(cmd *cobra.Command, args []string) { parsed, err := ParseWebshArgs(args) if err != nil { if errors.Is(err, errHelpRequested) { _ = cmd.Help() return } utils.CliErrorWithExit("%s", err) } username := parsed.Username groupname := parsed.Groupname serverName := parsed.ServerName commandArgs := parsed.CommandArgs share := parsed.Share readOnly := parsed.ReadOnly env := parsed.Env if serverName == "" { utils.CliErrorWithExit("Server name is required.") } if share && len(commandArgs) > 0 { utils.CliErrorWithExit("The --share flag cannot be used with remote commands. Use --share for interactive sessions only.") } if strings.Contains(serverName, "@") && !strings.Contains(serverName, ":") { sshTarget := utils.ParseSSHTarget(serverName) if username == "" && sshTarget.User != "" { username = sshTarget.User } serverName = sshTarget.Host } if len(commandArgs) > 0 { execCmd.RunRemoteExec(execCmd.RemoteExecArgs{ Username: username, Groupname: groupname, WorkSessionID: parsed.WorkSessionID, OutputFormat: parsed.OutputFormat, Server: serverName, Command: execCmd.ShellJoin(commandArgs), Env: env, }) return } if len(env) > 0 { utils.CliWarning("--env has no effect on an interactive websh session; it applies only when running a command") } if parsed.OutputFormat != "" { if parsed.OutputFormat != utils.OutputFormatTable && parsed.OutputFormat != utils.OutputFormatJSON { utils.CliErrorWithExit("invalid --output value %q: must be 'table' or 'json'", parsed.OutputFormat) } utils.OutputFormat = parsed.OutputFormat } workSessionID := worksession.ResolveOrExit(parsed.WorkSessionID) authMethod := config.ResolveAuthMethod() alpaconClient, err := client.NewAlpaconAPIClient() if err != nil { utils.CliErrorWithExit("Connection to Alpacon API failed: %s. Consider re-logging.", err) } session, err := websh.CreateWebshSession(alpaconClient, serverName, username, groupname, share, readOnly, workSessionID) if err != nil { err = utils.HandleCommonErrors(err, serverName, utils.ErrorHandlerCallbacks{ OnMFARequired: func(srv string) error { return mfa.HandleMFAError(alpaconClient, srv) }, OnUsernameRequired: func() error { _, err := iam.HandleUsernameRequired() return err }, CheckMFACompleted: func() (bool, error) { return mfa.CheckMFACompletion(alpaconClient) }, RefreshToken: alpaconClient.RefreshToken, RetryOperation: func() error { session, err = websh.CreateWebshSession(alpaconClient, serverName, username, groupname, share, readOnly, workSessionID) return err }, }) if err != nil { utils.HandleWorkSessionError(err, "websh", serverName, authMethod, workSessionID) utils.CliErrorWithExit("Failed to create websh session for '%s' server: %s.", serverName, err) } } listenerDone := make(chan *event.SudoListener, 1) go func() { listenerDone <- setupSudoListener(alpaconClient, session.ID, serverName) }() defer func() { select { case sl := <-listenerDone: if sl != nil { sl.Stop() } case <-time.After(3 * time.Second): } }() _ = websh.OpenNewTerminal(alpaconClient, session) }, }
Functions ¶
This section is empty.
Types ¶
type WebshArgs ¶ added in v1.4.6
type WebshArgs struct {
Username string
Groupname string
ServerName string
CommandArgs []string
ReadOnly bool
WorkSessionID string
OutputFormat string
Env map[string]string
}
func ParseWebshArgs ¶ added in v1.4.6
ParseWebshArgs parses raw CLI args for `alpacon websh` (DisableFlagParsing mode). Returns errHelpRequested when -h/--help is seen.
NOTE: --read-only must be checked before generic -r prefixes, and --work-session before the default fallthrough.
Click to show internal directories.
Click to hide internal directories.