From 333c4925e28a07e7e63806513e4f6b064a65b14a Mon Sep 17 00:00:00 2001 From: reubenmiller Date: Mon, 13 Jan 2025 21:52:02 +0100 Subject: [PATCH 1/6] fix: fix indentation issue on c8y remoteaccess server --- pkg/cmd/remoteaccess/server/server.manual.go | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pkg/cmd/remoteaccess/server/server.manual.go b/pkg/cmd/remoteaccess/server/server.manual.go index fb24a01d6..990a52b1c 100644 --- a/pkg/cmd/remoteaccess/server/server.manual.go +++ b/pkg/cmd/remoteaccess/server/server.manual.go @@ -39,25 +39,25 @@ func NewCmdServer(f *cmdutil.Factory) *CmdServer { cmd := &cobra.Command{ Use: "server", Short: "Start a local proxy server", - Long: ` - Start a local proxy server - - You can add use the remote access local proxy within your ssh config file, to use it to - connect to your device with ssh without having to manually launch the proxy yourself! - - To do this add the following configuration to your device. - - --- - Host - User - PreferredAuthentications publickey - IdentityFile - ServerAliveInterval 120 - StrictHostKeyChecking no - UserKnownHostsFile /dev/null - ProxyCommand c8y remoteaccess server --device %n --listen - - --- - `, + Long: heredoc.Doc(` + Start a local proxy server + + You can add use the remote access local proxy within your ssh config file, to use it to + connect to your device with ssh without having to manually launch the proxy yourself! + + To do this add the following configuration to your device. + + --- + Host + User + PreferredAuthentications publickey + IdentityFile + ServerAliveInterval 120 + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + ProxyCommand c8y remoteaccess server --device %n --listen - + --- + `), Example: heredoc.Doc(` $ c8y remoteaccess server --device 12345 Start a local proxy server on a random local port From 9d44bc0e39e46423be73979a8c665b2cb83401c1 Mon Sep 17 00:00:00 2001 From: reubenmiller Date: Mon, 13 Jan 2025 21:54:16 +0100 Subject: [PATCH 2/6] feat(remoteaccess): add port-forwarding flag to remoteaccess connect ssh --- .../remoteaccess/connect/ssh/ssh.manual.go | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go b/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go index a57b4151e..a7e117ddc 100644 --- a/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go +++ b/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go @@ -24,10 +24,11 @@ import ( ) type CmdSSH struct { - device []string - listen string - user string - configuration string + device []string + listen string + user string + configuration string + portForwarding string *subcommand.SubCommand @@ -62,6 +63,9 @@ func NewCmdSSH(f *cmdutil.Factory) *CmdSSH { $ c8y remoteaccess connect ssh --device 12345 --user admin Start an interactive SSH session on the device with a given ssh user + $ c8y remoteaccess connect ssh --device 12345 --user admin -L 1883:127.0.0.1:1883 + Start an interactive SSH session and configure port-forwarding by mapping the remote's 127.0.0.1:1883 to your machine's port 1883 + $ c8y remoteaccess connect ssh --device 12345 --user admin -- systemctl status Use a non-interactive session to execute a single command and print the result @@ -76,6 +80,7 @@ func NewCmdSSH(f *cmdutil.Factory) *CmdSSH { cmd.Flags().StringVar(&ccmd.listen, "listen", "127.0.0.1:0", "Listener address. unix:///run/example.sock") cmd.Flags().StringVar(&ccmd.user, "user", "", "Default ssh user") cmd.Flags().StringVar(&ccmd.configuration, "configuration", "", "Remote Access Configuration") + cmd.Flags().StringVarP(&ccmd.portForwarding, "port-forwarding", "L", "", "SSH Port-Forwarding option in the format [bind_address:]port:host:hostport. The value is passed to the ssh -L option, so read the ssh man page for more info") completion.WithOptions( cmd, @@ -185,6 +190,10 @@ func (n *CmdSSH) RunE(cmd *cobra.Command, args []string) error { } sshArgs = append(sshArgs, "-p", port, sshTarget) + if n.portForwarding != "" { + sshArgs = append(sshArgs, "-L", n.portForwarding) + } + dashIdx := cmd.ArgsLenAtDash() if dashIdx > -1 { sshArgs = append(sshArgs, "--") @@ -198,7 +207,11 @@ func (n *CmdSSH) RunE(cmd *cobra.Command, args []string) error { log.Infof("Executing command: ssh %s\n", strings.Join(sshArgs, " ")) cs := n.factory.IOStreams.ColorScheme() - fmt.Fprintln(n.factory.IOStreams.ErrOut, cs.Green(fmt.Sprintf("Starting interactive ssh session with %s (%s)\n", device, strings.TrimRight(client.BaseURL.String(), "/")))) + if n.portForwarding != "" { + fmt.Fprintln(n.factory.IOStreams.ErrOut, cs.Green(fmt.Sprintf("Starting interactive ssh session with %s (%s) with port-forwarding %s\n", device, strings.TrimRight(client.BaseURL.String(), "/"), n.portForwarding))) + } else { + fmt.Fprintln(n.factory.IOStreams.ErrOut, cs.Green(fmt.Sprintf("Starting interactive ssh session with %s (%s)\n", device, strings.TrimRight(client.BaseURL.String(), "/")))) + } start := time.Now() sshErr := sshCmd.Run() From b57150bdc9239ef86c4d20944729c98e237b5314 Mon Sep 17 00:00:00 2001 From: reubenmiller Date: Mon, 13 Jan 2025 21:56:11 +0100 Subject: [PATCH 3/6] fix(remoteaccess): run command in parent processes environment variable context --- pkg/cmd/remoteaccess/connect/run/run.manual.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/cmd/remoteaccess/connect/run/run.manual.go b/pkg/cmd/remoteaccess/connect/run/run.manual.go index 25d3fcf0d..b5245495a 100644 --- a/pkg/cmd/remoteaccess/connect/run/run.manual.go +++ b/pkg/cmd/remoteaccess/connect/run/run.manual.go @@ -3,6 +3,7 @@ package run import ( "context" "fmt" + "os" "os/exec" "strings" "time" @@ -189,6 +190,7 @@ func (n *CmdRun) RunE(cmd *cobra.Command, args []string) error { } runCmd := exec.CommandContext(context.Background(), run, runArgs...) + runCmd.Env = append(runCmd.Env, os.Environ()...) // Add target and port to the environment variables so it can be easily accessed from more // complex scripts From 879f8c95b68cf9c5ef796e11c8fdd84d13799e6e Mon Sep 17 00:00:00 2001 From: reubenmiller Date: Mon, 13 Jan 2025 21:56:48 +0100 Subject: [PATCH 4/6] feat(remoteaccess): add port-forwarding example --- pkg/cmd/remoteaccess/connect/run/run.manual.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/cmd/remoteaccess/connect/run/run.manual.go b/pkg/cmd/remoteaccess/connect/run/run.manual.go index b5245495a..56e6eee44 100644 --- a/pkg/cmd/remoteaccess/connect/run/run.manual.go +++ b/pkg/cmd/remoteaccess/connect/run/run.manual.go @@ -67,6 +67,9 @@ func NewCmdRun(f *cmdutil.Factory) *CmdRun { Example: heredoc.Doc(` $ c8y remoteaccess connect run --device 12345 -- ssh -p %p root@%h Start an interactive SSH session on the device with a given ssh user + + $ c8y remoteaccess connect run --device rpi5-abcdef01 --configuration passthrough -- ssh -p %p -L 1885:127.0.0.1:1883 -o ServerAliveInterval=120 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@127.0.0.1 + Start an SSH session to setup port-forwarding to map the remote's 127.0.0.1:1883 port to your machine's 1885 port `), RunE: ccmd.RunE, } From ab5a1c07ab16ef72203ddead592f84cd52ec1ec6 Mon Sep 17 00:00:00 2001 From: reubenmiller Date: Mon, 13 Jan 2025 22:21:33 +0100 Subject: [PATCH 5/6] feat(remoteaccess): allow short form when specifying port-forwarding values --- .../remoteaccess/connect/ssh/ssh.manual.go | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go b/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go index a7e117ddc..c151f71ce 100644 --- a/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go +++ b/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go @@ -66,6 +66,12 @@ func NewCmdSSH(f *cmdutil.Factory) *CmdSSH { $ c8y remoteaccess connect ssh --device 12345 --user admin -L 1883:127.0.0.1:1883 Start an interactive SSH session and configure port-forwarding by mapping the remote's 127.0.0.1:1883 to your machine's port 1883 + $ c8y remoteaccess connect ssh --device 12345 --user admin -L 1883 + Start an interactive SSH session and configure port-forwarding: 127.0.0.11883 (remote) => 1883 (local) + + $ c8y remoteaccess connect ssh --device 12345 --user admin -L 1884:1883 + Start an interactive SSH session and configure port-forwarding: 127.0.0.11883 (remote) => 1884 (local) + $ c8y remoteaccess connect ssh --device 12345 --user admin -- systemctl status Use a non-interactive session to execute a single command and print the result @@ -80,7 +86,7 @@ func NewCmdSSH(f *cmdutil.Factory) *CmdSSH { cmd.Flags().StringVar(&ccmd.listen, "listen", "127.0.0.1:0", "Listener address. unix:///run/example.sock") cmd.Flags().StringVar(&ccmd.user, "user", "", "Default ssh user") cmd.Flags().StringVar(&ccmd.configuration, "configuration", "", "Remote Access Configuration") - cmd.Flags().StringVarP(&ccmd.portForwarding, "port-forwarding", "L", "", "SSH Port-Forwarding option in the format [bind_address:]port:host:hostport. The value is passed to the ssh -L option, so read the ssh man page for more info") + cmd.Flags().StringVarP(&ccmd.portForwarding, "port-forwarding", "L", "", "SSH Port-Forwarding option in the format [bind_address:]port:host:hostport. It also accepts a custom short form, [:]. The value is passed to the ssh -L option, so read the ssh man page for more info") completion.WithOptions( cmd, @@ -98,6 +104,20 @@ func NewCmdSSH(f *cmdutil.Factory) *CmdSSH { return ccmd } +func (n *CmdSSH) GetPortForwarding() string { + // convenience functions to mirror docker port mapping options + portMapping := n.portForwarding + portForwardingParts := strings.Split(portMapping, ":") + switch len(portForwardingParts) { + case 1: + // -L 1883 => -L 1883:127.0.0.1:1883 + portMapping = fmt.Sprintf("%s:127.0.0.1:%s", portForwardingParts[0], portForwardingParts[0]) + case 2: + // -L 1884:1883 => -L 1884:127.0.0.1:1883 + portMapping = fmt.Sprintf("%s:127.0.0.1:%s", portForwardingParts[0], portForwardingParts[1]) + } + return portMapping +} func (n *CmdSSH) RunE(cmd *cobra.Command, args []string) error { client, err := n.factory.Client() if err != nil { @@ -190,8 +210,9 @@ func (n *CmdSSH) RunE(cmd *cobra.Command, args []string) error { } sshArgs = append(sshArgs, "-p", port, sshTarget) - if n.portForwarding != "" { - sshArgs = append(sshArgs, "-L", n.portForwarding) + portForwarding := n.GetPortForwarding() + if portForwarding != "" { + sshArgs = append(sshArgs, "-L", portForwarding) } dashIdx := cmd.ArgsLenAtDash() @@ -207,8 +228,8 @@ func (n *CmdSSH) RunE(cmd *cobra.Command, args []string) error { log.Infof("Executing command: ssh %s\n", strings.Join(sshArgs, " ")) cs := n.factory.IOStreams.ColorScheme() - if n.portForwarding != "" { - fmt.Fprintln(n.factory.IOStreams.ErrOut, cs.Green(fmt.Sprintf("Starting interactive ssh session with %s (%s) with port-forwarding %s\n", device, strings.TrimRight(client.BaseURL.String(), "/"), n.portForwarding))) + if portForwarding != "" { + fmt.Fprintln(n.factory.IOStreams.ErrOut, cs.Green(fmt.Sprintf("Starting interactive ssh session with %s (%s) with port-forwarding %s\n", device, strings.TrimRight(client.BaseURL.String(), "/"), portForwarding))) } else { fmt.Fprintln(n.factory.IOStreams.ErrOut, cs.Green(fmt.Sprintf("Starting interactive ssh session with %s (%s)\n", device, strings.TrimRight(client.BaseURL.String(), "/")))) } From 9c8f88a1535bf2a646cc907ed61cfaa97ad8c464 Mon Sep 17 00:00:00 2001 From: reubenmiller Date: Mon, 13 Jan 2025 22:24:58 +0100 Subject: [PATCH 6/6] rename port-forwarding flag to "port-forward" --- pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go b/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go index c151f71ce..fda493aec 100644 --- a/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go +++ b/pkg/cmd/remoteaccess/connect/ssh/ssh.manual.go @@ -64,13 +64,13 @@ func NewCmdSSH(f *cmdutil.Factory) *CmdSSH { Start an interactive SSH session on the device with a given ssh user $ c8y remoteaccess connect ssh --device 12345 --user admin -L 1883:127.0.0.1:1883 - Start an interactive SSH session and configure port-forwarding by mapping the remote's 127.0.0.1:1883 to your machine's port 1883 + Start an interactive SSH session and configure port-forward by mapping the remote's 127.0.0.1:1883 to your machine's port 1883 $ c8y remoteaccess connect ssh --device 12345 --user admin -L 1883 - Start an interactive SSH session and configure port-forwarding: 127.0.0.11883 (remote) => 1883 (local) + Start an interactive SSH session and configure port-forward: 127.0.0.11883 (remote) => 1883 (local) $ c8y remoteaccess connect ssh --device 12345 --user admin -L 1884:1883 - Start an interactive SSH session and configure port-forwarding: 127.0.0.11883 (remote) => 1884 (local) + Start an interactive SSH session and configure port-forward: 127.0.0.11883 (remote) => 1884 (local) $ c8y remoteaccess connect ssh --device 12345 --user admin -- systemctl status Use a non-interactive session to execute a single command and print the result @@ -86,7 +86,7 @@ func NewCmdSSH(f *cmdutil.Factory) *CmdSSH { cmd.Flags().StringVar(&ccmd.listen, "listen", "127.0.0.1:0", "Listener address. unix:///run/example.sock") cmd.Flags().StringVar(&ccmd.user, "user", "", "Default ssh user") cmd.Flags().StringVar(&ccmd.configuration, "configuration", "", "Remote Access Configuration") - cmd.Flags().StringVarP(&ccmd.portForwarding, "port-forwarding", "L", "", "SSH Port-Forwarding option in the format [bind_address:]port:host:hostport. It also accepts a custom short form, [:]. The value is passed to the ssh -L option, so read the ssh man page for more info") + cmd.Flags().StringVarP(&ccmd.portForwarding, "port-forward", "L", "", "SSH Port-Forwarding option in the format [bind_address:]port:host:hostport. It also accepts a custom short form, [:]. The value is passed to the ssh -L option, so read the ssh man page for more info") completion.WithOptions( cmd,