Skip to content

Commit 2f46063

Browse files
authored
Merge pull request #364 from rsteube/add-sftp
added sftp
2 parents c0babb2 + fb8c285 commit 2f46063

File tree

4 files changed

+195
-115
lines changed

4 files changed

+195
-115
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package cmd
2+
3+
import (
4+
"github.com/rsteube/carapace"
5+
"github.com/rsteube/carapace-bin/pkg/actions/net"
6+
"github.com/rsteube/carapace-bin/pkg/actions/net/ssh"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
var rootCmd = &cobra.Command{
11+
Use: "sftp",
12+
Short: "",
13+
Run: func(cmd *cobra.Command, args []string) {},
14+
}
15+
16+
func Execute() error {
17+
return rootCmd.Execute()
18+
}
19+
func init() {
20+
carapace.Gen(rootCmd).Standalone()
21+
22+
rootCmd.Flags().BoolS("4", "4", false, "Forces sftp to use IPv4 addresses only.")
23+
rootCmd.Flags().BoolS("6", "6", false, "Forces sftp to use IPv6 addresses only.")
24+
rootCmd.Flags().BoolS("A", "A", false, "Allows forwarding of ssh-agent(1) to the remote system.")
25+
rootCmd.Flags().BoolS("a", "a", false, "Attempt to continue interrupted transfers rather than overwriting existing partial or complete copies of files.")
26+
rootCmd.Flags().StringS("B", "B", "", "Specify the size of the buffer that sftp uses when transferring files.")
27+
rootCmd.Flags().StringS("b", "b", "", "Batch mode reads a series of commands from an input batchfile instead of stdin.")
28+
rootCmd.Flags().BoolS("C", "C", false, "Enables compression (via ssh's -C flag).")
29+
rootCmd.Flags().StringS("c", "c", "", "Selects the cipher to use for encrypting the data transfers.")
30+
rootCmd.Flags().StringS("D", "D", "", "Connect directly to a local sftp server (rather than via ssh(1)).")
31+
rootCmd.Flags().StringS("F", "F", "", "Specifies an alternative per-user configuration file for ssh(1).")
32+
rootCmd.Flags().BoolS("f", "f", false, "Requests that files be flushed to disk immediately after transfer.")
33+
rootCmd.Flags().StringS("i", "i", "", "Selects the file from which the identity (private key) for public key authentication is read.")
34+
rootCmd.Flags().StringS("J", "J", "", "Connect to the target host by first making an sftp connection to the jump host described by destination.")
35+
rootCmd.Flags().StringS("l", "l", "", "Limits the used bandwidth, specified in Kbit/s.")
36+
rootCmd.Flags().BoolS("N", "N", false, "Disables quiet mode, e.g. to override the implicit quiet mode set by the -b flag.")
37+
rootCmd.Flags().StringS("o", "o", "", "Can be used to pass options to ssh in the format used in ssh_config(5).")
38+
rootCmd.Flags().StringS("P", "P", "", "Specifies the port to connect to on the remote host.")
39+
rootCmd.Flags().BoolS("p", "p", false, "Preserves modification times, access times, and modes from the original files transferred.")
40+
rootCmd.Flags().BoolS("q", "q", false, "Quiet mode: disables the progress meter as well as warning and diagnostic messages from ssh(1).")
41+
rootCmd.Flags().StringS("R", "R", "", "Specify how many requests may be outstanding at any one time.")
42+
rootCmd.Flags().BoolS("r", "r", false, "Recursively copy entire directories when uploading and downloading.")
43+
rootCmd.Flags().StringS("S", "S", "", "Name of the program to use for the encrypted connection.")
44+
rootCmd.Flags().StringS("s", "s", "", "Specifies the SSH2 subsystem or the path for an sftp server on the remote host.")
45+
rootCmd.Flags().BoolS("v", "v", false, "Raise logging level. This option is also passed to ssh.")
46+
47+
carapace.Gen(rootCmd).FlagCompletion(carapace.ActionMap{
48+
"D": carapace.ActionDirectories(),
49+
"F": carapace.ActionFiles(),
50+
"J": net.ActionHosts(),
51+
"b": carapace.ActionFiles(),
52+
"c": ssh.ActionCiphers(),
53+
"i": carapace.ActionFiles(),
54+
"o": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action {
55+
return ssh.ActionOptions()
56+
}),
57+
})
58+
59+
carapace.Gen(rootCmd).PositionalCompletion(
60+
net.ActionHosts(),
61+
)
62+
}

completers/sftp_completer/main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package main
2+
3+
import "github.com/rsteube/carapace-bin/completers/sftp_completer/cmd"
4+
5+
func main() {
6+
cmd.Execute()
7+
}

completers/ssh_completer/cmd/root.go

Lines changed: 3 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/rsteube/carapace"
77
"github.com/rsteube/carapace-bin/pkg/actions/net"
8+
"github.com/rsteube/carapace-bin/pkg/actions/net/ssh"
89
"github.com/spf13/cobra"
910
)
1011

@@ -70,7 +71,7 @@ func init() {
7071
// "B"
7172
// "b"
7273
"c": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action {
73-
return ActionCiphers().Invoke(c).Filter(c.Parts).ToA()
74+
return ssh.ActionCiphers().Invoke(c).Filter(c.Parts).ToA()
7475
}),
7576
// "D"
7677
"E": carapace.ActionFiles(),
@@ -88,7 +89,7 @@ func init() {
8889
"exit", "request the master to exit",
8990
"stop", "request the master to stop accepting further multiplexing requests",
9091
),
91-
"o": ActionOptions(),
92+
"o": ssh.ActionOptions(),
9293
// "p"
9394
"Q": ActionQueryOptions(),
9495
// "R"
@@ -109,119 +110,6 @@ func init() {
109110
)
110111
}
111112

112-
func ActionCiphers() carapace.Action {
113-
return carapace.ActionValues(
114-
"3des-cbc", "aes128-cbc", "aes192-cbc", "aes256-cbc", "aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour128", "arcfour256", "arcfour", "blowfish-cbc", "cast128-cbc",
115-
)
116-
}
117-
118-
func ActionOptions() carapace.Action {
119-
return carapace.ActionMultiParts("=", func(c carapace.Context) carapace.Action {
120-
options := map[string]carapace.Action{
121-
"AddKeysToAgent": carapace.ActionValues(),
122-
"AddressFamily": carapace.ActionValues("any", "inet", "inet6"),
123-
"BatchMode": carapace.ActionValues("yes", "no"),
124-
"BindAddress": carapace.ActionValues("yes", "no"),
125-
"CanonicalDomains": carapace.ActionValues(),
126-
"CanonicalizeFallbackLocal": carapace.ActionValues(),
127-
"CanonicalizeHostname": carapace.ActionValues(),
128-
"CanonicalizeMaxDots": carapace.ActionValues(),
129-
"CanonicalizePermittedCNAMEs": carapace.ActionValues(),
130-
"CASignatureAlgorithms": carapace.ActionValues(),
131-
"CertificateFile": carapace.ActionValues(),
132-
"ChallengeResponseAuthentication": carapace.ActionValues("yes", "no"),
133-
"CheckHostIP": carapace.ActionValues("yes", "no"),
134-
"Ciphers": carapace.ActionValues(),
135-
"ClearAllForwardings": carapace.ActionValues(),
136-
"Compression": carapace.ActionValues("yes", "no"),
137-
"ConnectionAttempts": carapace.ActionValues(),
138-
"ConnectTimeout": carapace.ActionValues(),
139-
"ControlMaster": carapace.ActionValues(),
140-
"ControlPath": carapace.ActionValues(),
141-
"ControlPersist": carapace.ActionValues(),
142-
"DynamicForward": carapace.ActionValues(),
143-
"EscapeChar": carapace.ActionValues(),
144-
"ExitOnForwardFailure": carapace.ActionValues("yes", "no"),
145-
"FingerprintHash": carapace.ActionValues(),
146-
"ForwardAgent": carapace.ActionValues("yes", "no"),
147-
"ForwardX11": carapace.ActionValues("yes", "no"),
148-
"ForwardX11Timeout": carapace.ActionValues(),
149-
"ForwardX11Trusted": carapace.ActionValues("yes", "no"),
150-
"GatewayPorts": carapace.ActionValues("yes", "no"),
151-
"GlobalKnownHostsFile": carapace.ActionFiles(),
152-
"GSSAPIAuthentication": carapace.ActionValues("yes", "no"),
153-
"HashKnownHosts": carapace.ActionValues("yes", "no"),
154-
"Host": carapace.ActionValues(),
155-
"HostbasedAuthentication": carapace.ActionValues("yes", "no"),
156-
"HostbasedKeyTypes": carapace.ActionValues(),
157-
"HostKeyAlgorithms": carapace.ActionValues(),
158-
"HostKeyAlias": carapace.ActionValues(),
159-
"Hostname": carapace.ActionValues(),
160-
"IdentitiesOnly": carapace.ActionValues("yes", "no"),
161-
"IdentityAgent": carapace.ActionValues(),
162-
"IdentityFile": carapace.ActionFiles(),
163-
"IPQoS": carapace.ActionValues(),
164-
"KbdInteractiveAuthentication": carapace.ActionValues(),
165-
"KbdInteractiveDevices": carapace.ActionValues(),
166-
"KexAlgorithms": carapace.ActionValues(),
167-
"LocalCommand": carapace.ActionValues(),
168-
"LocalForward": carapace.ActionValues(),
169-
"LogLevel": carapace.ActionValues("QUIET", "FATAL", "ERROR", "INFO", "VERBOSE", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3"),
170-
"MACs": carapace.ActionValues(),
171-
"Match": carapace.ActionValues(),
172-
"NoHostAuthenticationForLocalhost": carapace.ActionValues(),
173-
"NumberOfPasswordPrompts": carapace.ActionValues(),
174-
"PasswordAuthentication": carapace.ActionValues(),
175-
"PermitLocalCommand": carapace.ActionValues(),
176-
"PKCS11Provider": carapace.ActionValues(),
177-
"Port": carapace.ActionValues(),
178-
"PreferredAuthentications": carapace.ActionValues(),
179-
"ProxyCommand": carapace.ActionValues(),
180-
"ProxyJump": carapace.ActionValues(),
181-
"ProxyUseFdpass": carapace.ActionValues(),
182-
"PubkeyAcceptedKeyTypes": carapace.ActionValues(),
183-
"PubkeyAuthentication": carapace.ActionValues(),
184-
"RekeyLimit": carapace.ActionValues(),
185-
"RemoteCommand": carapace.ActionValues(),
186-
"RemoteForward": carapace.ActionValues(),
187-
"RequestTTY": carapace.ActionValues(),
188-
"SendEnv": carapace.ActionValues(),
189-
"ServerAliveInterval": carapace.ActionValues(),
190-
"ServerAliveCountMax": carapace.ActionValues(),
191-
"SetEnv": carapace.ActionValues(),
192-
"StreamLocalBindMask": carapace.ActionValues(),
193-
"StreamLocalBindUnlink": carapace.ActionValues(),
194-
"StrictHostKeyChecking": carapace.ActionValues("yes", "no", "ask"),
195-
"TCPKeepAlive": carapace.ActionValues("yes", "no"),
196-
"Tunnel": carapace.ActionValues("yes", "point-to-point", "ethernet", "no"),
197-
"TunnelDevice": carapace.ActionValues(),
198-
"UpdateHostKeys": carapace.ActionValues(),
199-
"User": carapace.ActionValues(),
200-
"UserKnownHostsFile": carapace.ActionFiles(),
201-
"VerifyHostKeyDNS": carapace.ActionValues("yes", "no", "ask"),
202-
"VisualHostKey": carapace.ActionValues("yes", "no"),
203-
"XAuthLocation": carapace.ActionFiles(),
204-
}
205-
206-
switch len(c.Parts) {
207-
case 0:
208-
keys := make([]string, 0, len(options))
209-
for key := range options {
210-
keys = append(keys, key)
211-
}
212-
return carapace.ActionValues(keys...).Invoke(c).Suffix("=").ToA()
213-
case 1:
214-
if val, ok := options[c.Parts[0]]; ok {
215-
return val
216-
} else {
217-
return carapace.ActionValues()
218-
}
219-
default:
220-
return carapace.ActionValues()
221-
}
222-
})
223-
}
224-
225113
func ActionQueryOptions() carapace.Action {
226114
return carapace.ActionValuesDescribed(
227115
"cipher", "supported symmetric ciphers",

pkg/actions/net/ssh/ssh.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// package ssh contains ssh related actions
2+
package ssh
3+
4+
import "github.com/rsteube/carapace"
5+
6+
// ActionCiphers completes ciphers
7+
// 3des-cbc
8+
// aes128-cbc
9+
func ActionCiphers() carapace.Action {
10+
return carapace.ActionValues(
11+
"3des-cbc", "aes128-cbc", "aes192-cbc", "aes256-cbc", "aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour128", "arcfour256", "arcfour", "blowfish-cbc", "cast128-cbc",
12+
)
13+
}
14+
15+
// ActionOptions completies options and they values
16+
// AddKeysToAgent
17+
// AddressFamily=inet
18+
func ActionOptions() carapace.Action {
19+
return carapace.ActionMultiParts("=", func(c carapace.Context) carapace.Action {
20+
options := map[string]carapace.Action{
21+
"AddKeysToAgent": carapace.ActionValues(),
22+
"AddressFamily": carapace.ActionValues("any", "inet", "inet6"),
23+
"BatchMode": carapace.ActionValues("yes", "no"),
24+
"BindAddress": carapace.ActionValues("yes", "no"),
25+
"CanonicalDomains": carapace.ActionValues(),
26+
"CanonicalizeFallbackLocal": carapace.ActionValues(),
27+
"CanonicalizeHostname": carapace.ActionValues(),
28+
"CanonicalizeMaxDots": carapace.ActionValues(),
29+
"CanonicalizePermittedCNAMEs": carapace.ActionValues(),
30+
"CASignatureAlgorithms": carapace.ActionValues(),
31+
"CertificateFile": carapace.ActionValues(),
32+
"ChallengeResponseAuthentication": carapace.ActionValues("yes", "no"),
33+
"CheckHostIP": carapace.ActionValues("yes", "no"),
34+
"Ciphers": carapace.ActionValues(),
35+
"ClearAllForwardings": carapace.ActionValues(),
36+
"Compression": carapace.ActionValues("yes", "no"),
37+
"ConnectionAttempts": carapace.ActionValues(),
38+
"ConnectTimeout": carapace.ActionValues(),
39+
"ControlMaster": carapace.ActionValues(),
40+
"ControlPath": carapace.ActionValues(),
41+
"ControlPersist": carapace.ActionValues(),
42+
"DynamicForward": carapace.ActionValues(),
43+
"EscapeChar": carapace.ActionValues(),
44+
"ExitOnForwardFailure": carapace.ActionValues("yes", "no"),
45+
"FingerprintHash": carapace.ActionValues(),
46+
"ForwardAgent": carapace.ActionValues("yes", "no"),
47+
"ForwardX11": carapace.ActionValues("yes", "no"),
48+
"ForwardX11Timeout": carapace.ActionValues(),
49+
"ForwardX11Trusted": carapace.ActionValues("yes", "no"),
50+
"GatewayPorts": carapace.ActionValues("yes", "no"),
51+
"GlobalKnownHostsFile": carapace.ActionFiles(),
52+
"GSSAPIAuthentication": carapace.ActionValues("yes", "no"),
53+
"HashKnownHosts": carapace.ActionValues("yes", "no"),
54+
"Host": carapace.ActionValues(),
55+
"HostbasedAuthentication": carapace.ActionValues("yes", "no"),
56+
"HostbasedKeyTypes": carapace.ActionValues(),
57+
"HostKeyAlgorithms": carapace.ActionValues(),
58+
"HostKeyAlias": carapace.ActionValues(),
59+
"Hostname": carapace.ActionValues(),
60+
"IdentitiesOnly": carapace.ActionValues("yes", "no"),
61+
"IdentityAgent": carapace.ActionValues(),
62+
"IdentityFile": carapace.ActionFiles(),
63+
"IPQoS": carapace.ActionValues(),
64+
"KbdInteractiveAuthentication": carapace.ActionValues(),
65+
"KbdInteractiveDevices": carapace.ActionValues(),
66+
"KexAlgorithms": carapace.ActionValues(),
67+
"LocalCommand": carapace.ActionValues(),
68+
"LocalForward": carapace.ActionValues(),
69+
"LogLevel": carapace.ActionValues("QUIET", "FATAL", "ERROR", "INFO", "VERBOSE", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3"),
70+
"MACs": carapace.ActionValues(),
71+
"Match": carapace.ActionValues(),
72+
"NoHostAuthenticationForLocalhost": carapace.ActionValues(),
73+
"NumberOfPasswordPrompts": carapace.ActionValues(),
74+
"PasswordAuthentication": carapace.ActionValues(),
75+
"PermitLocalCommand": carapace.ActionValues(),
76+
"PKCS11Provider": carapace.ActionValues(),
77+
"Port": carapace.ActionValues(),
78+
"PreferredAuthentications": carapace.ActionValues(),
79+
"ProxyCommand": carapace.ActionValues(),
80+
"ProxyJump": carapace.ActionValues(),
81+
"ProxyUseFdpass": carapace.ActionValues(),
82+
"PubkeyAcceptedKeyTypes": carapace.ActionValues(),
83+
"PubkeyAuthentication": carapace.ActionValues(),
84+
"RekeyLimit": carapace.ActionValues(),
85+
"RemoteCommand": carapace.ActionValues(),
86+
"RemoteForward": carapace.ActionValues(),
87+
"RequestTTY": carapace.ActionValues(),
88+
"SendEnv": carapace.ActionValues(),
89+
"ServerAliveInterval": carapace.ActionValues(),
90+
"ServerAliveCountMax": carapace.ActionValues(),
91+
"SetEnv": carapace.ActionValues(),
92+
"StreamLocalBindMask": carapace.ActionValues(),
93+
"StreamLocalBindUnlink": carapace.ActionValues(),
94+
"StrictHostKeyChecking": carapace.ActionValues("yes", "no", "ask"),
95+
"TCPKeepAlive": carapace.ActionValues("yes", "no"),
96+
"Tunnel": carapace.ActionValues("yes", "point-to-point", "ethernet", "no"),
97+
"TunnelDevice": carapace.ActionValues(),
98+
"UpdateHostKeys": carapace.ActionValues(),
99+
"User": carapace.ActionValues(),
100+
"UserKnownHostsFile": carapace.ActionFiles(),
101+
"VerifyHostKeyDNS": carapace.ActionValues("yes", "no", "ask"),
102+
"VisualHostKey": carapace.ActionValues("yes", "no"),
103+
"XAuthLocation": carapace.ActionFiles(),
104+
}
105+
106+
switch len(c.Parts) {
107+
case 0:
108+
keys := make([]string, 0, len(options))
109+
for key := range options {
110+
keys = append(keys, key)
111+
}
112+
return carapace.ActionValues(keys...).Invoke(c).Suffix("=").ToA()
113+
case 1:
114+
if val, ok := options[c.Parts[0]]; ok {
115+
return val
116+
} else {
117+
return carapace.ActionValues()
118+
}
119+
default:
120+
return carapace.ActionValues()
121+
}
122+
})
123+
}

0 commit comments

Comments
 (0)