Skip to content

Commit af2c03b

Browse files
committed
Add options to authenticate using a private key
1 parent 8a0c92a commit af2c03b

File tree

2 files changed

+75
-9
lines changed

2 files changed

+75
-9
lines changed

DOCS.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ You can override the default configuration with the following parameters:
55
* `port` - Server port, default to 22
66
* `username` - Server username, default to blank
77
* `password` - Password for password-based authentication
8+
* `key` - Private key for public-key-based authentication
9+
* `key_path` - Private key path for public-key-based authentication
10+
* `passphrase` - Passphrase of your key for public-key-based authentication (optional)
811
* `destination_path` - Target path on the server, default to '/'
912
* `files` - List of files to upload
1013

1114
All file paths must be relative to current project sources
1215

13-
## Example
16+
## Examples
1417

15-
The following is a sample configuration in your .drone.yml file:
18+
Sample configuration using a password in your .drone.yml file:
1619

1720
```yaml
1821
publish:
@@ -21,6 +24,21 @@ publish:
2124
port: 2222
2225
username: user
2326
password: pa$$word
24-
files:
27+
files:
28+
- *.nupkg
29+
```
30+
31+
Sample configuration using a private key saved as a secret in your .drone.yml file:
32+
33+
```yaml
34+
publish:
35+
sftp:
36+
host: sftp.company.com
37+
port: 2222
38+
username: user
39+
private_key:
40+
from_secret: sftp_private_key
41+
passphrase: my_passphrase
42+
files:
2543
- *.nupkg
2644
```

plugin/plugin.go

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ type (
3737
Port int `envconfig:"PLUGIN_PORT"`
3838
Username string `envconfig:"PLUGIN_USERNAME"`
3939
Password string `envconfig:"PLUGIN_PASSWORD"`
40+
Key string `envconfig:"PLUGIN_KEY"`
41+
KeyPath string `envconfig:"PLUGIN_KEY_PATH"`
42+
Passphrase string `envconfig:"PLUGIN_PASSPHRASE"`
4043
Files []string `envconfig:"PLUGIN_FILES"`
4144
Destination string `envconfig:"PLUGIN_DESTINATION_PATH"`
4245
}
@@ -130,8 +133,8 @@ func verifyArgs(args *Args) error {
130133
return fmt.Errorf("no username provided: %w", errConfiguration)
131134
}
132135

133-
if args.Password == "" {
134-
return fmt.Errorf("no password provided: %w", errConfiguration)
136+
if args.Password == "" && args.Key == "" && args.KeyPath == "" {
137+
return fmt.Errorf("no password or key provided: %w", errConfiguration)
135138
}
136139

137140
if args.Host == "" {
@@ -171,12 +174,15 @@ func findFileUploads(args *Args) ([]string, error) {
171174
}
172175

173176
func createSftpClient(args *Args) (*sftp.Client, error) {
177+
authMethod, err := createSftpAuthMethod(args)
178+
if err != nil {
179+
return nil, err
180+
}
181+
174182
server := fmt.Sprintf("%s:%d", args.Host, args.Port)
175183
config := &ssh.ClientConfig{
176-
User: args.Username,
177-
Auth: []ssh.AuthMethod{
178-
ssh.Password(args.Password),
179-
},
184+
User: args.Username,
185+
Auth: []ssh.AuthMethod{authMethod},
180186
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
181187
}
182188

@@ -197,6 +203,48 @@ func createSftpClient(args *Args) (*sftp.Client, error) {
197203
return client, nil
198204
}
199205

206+
func createSftpAuthMethod(args *Args) (ssh.AuthMethod, error) {
207+
if args.Password != "" {
208+
return ssh.Password(args.Password), nil
209+
}
210+
211+
if args.Key != "" {
212+
signer, err := parsePrivateKey([]byte(args.Key), []byte(args.Passphrase))
213+
if err != nil {
214+
return nil, err
215+
}
216+
return ssh.PublicKeys(signer), nil
217+
}
218+
219+
if args.KeyPath != "" {
220+
buffer, err := os.ReadFile(args.KeyPath)
221+
if err != nil {
222+
return nil, fmt.Errorf("could not read private key: %w", err)
223+
}
224+
signer, err := parsePrivateKey(buffer, []byte(args.Passphrase))
225+
if err != nil {
226+
return nil, err
227+
}
228+
return ssh.PublicKeys(signer), nil
229+
}
230+
231+
return nil, fmt.Errorf("could not determinate sftp auth method")
232+
}
233+
234+
func parsePrivateKey(key []byte, passphrase []byte) (ssh.Signer, error) {
235+
var signer ssh.Signer
236+
var err error
237+
if len(passphrase) > 0 {
238+
signer, err = ssh.ParsePrivateKeyWithPassphrase(key, passphrase)
239+
} else {
240+
signer, err = ssh.ParsePrivateKey(key)
241+
}
242+
if err != nil {
243+
return nil, fmt.Errorf("could not parse private key: %w", err)
244+
}
245+
return signer, nil
246+
}
247+
200248
func createDirectory(client *sftp.Client, directory string) error {
201249
if directory == defaultDirectory {
202250
return nil

0 commit comments

Comments
 (0)