119 lines
3.1 KiB
Go
119 lines
3.1 KiB
Go
package ssh
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/distributor/internal/storage"
|
|
"github.com/pkg/sftp"
|
|
)
|
|
|
|
func TestOptionsNormalizeDefaultsUserPortAndHostKeyPolicy(t *testing.T) {
|
|
options, err := (Options{
|
|
Host: "example.com",
|
|
Root: "/reports",
|
|
}).normalized()
|
|
if err != nil {
|
|
t.Fatalf("normalized() error = %v", err)
|
|
}
|
|
if options.User == "" {
|
|
t.Fatal("normalized user is empty")
|
|
}
|
|
if options.Port != 22 {
|
|
t.Fatalf("port = %d, want 22", options.Port)
|
|
}
|
|
if options.HostKeyPolicy != HostKeyPolicyAcceptNew {
|
|
t.Fatalf("host key policy = %q, want accept-new", options.HostKeyPolicy)
|
|
}
|
|
}
|
|
|
|
func TestOptionsNormalizeRejectsInvalidFields(t *testing.T) {
|
|
tests := map[string]Options{
|
|
"host": {Root: "/reports"},
|
|
"port": {
|
|
Host: "example.com",
|
|
Port: 70000,
|
|
Root: "/reports",
|
|
},
|
|
"path": {
|
|
Host: "example.com",
|
|
},
|
|
"host key policy": {
|
|
Host: "example.com",
|
|
Root: "/reports",
|
|
HostKeyPolicy: "prompt",
|
|
},
|
|
}
|
|
for name, options := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
if _, err := options.normalized(); err == nil {
|
|
t.Fatal("normalized() error = nil, want error")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNativePathEnforcesLogicalPathRules(t *testing.T) {
|
|
backend := &Backend{root: "/srv/reports"}
|
|
tests := map[string]string{
|
|
"bundle/report.md": "/srv/reports/bundle/report.md",
|
|
"": "/srv/reports",
|
|
}
|
|
for logicalPath, want := range tests {
|
|
t.Run(logicalPath, func(t *testing.T) {
|
|
got, err := backend.nativePath(logicalPath, true)
|
|
if err != nil {
|
|
t.Fatalf("nativePath() error = %v", err)
|
|
}
|
|
if got != want {
|
|
t.Fatalf("nativePath() = %q, want %q", got, want)
|
|
}
|
|
})
|
|
}
|
|
|
|
for _, logicalPath := range []string{"/absolute", "../escape", "a/../b", `a\b`} {
|
|
t.Run("reject "+logicalPath, func(t *testing.T) {
|
|
_, err := backend.nativePath(logicalPath, true)
|
|
if err == nil || !storage.IsInvalidPath(err) {
|
|
t.Fatalf("nativePath() error = %v, want invalid path", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewRejectsMissingAuthBeforeDial(t *testing.T) {
|
|
t.Setenv("SSH_AUTH_SOCK", "")
|
|
_, err := New(context.Background(), Options{
|
|
Host: "example.com",
|
|
User: "reports",
|
|
Root: "/reports",
|
|
HostKeyPolicy: HostKeyPolicyOff,
|
|
})
|
|
if err == nil || !strings.Contains(err.Error(), "no SSH auth methods configured") {
|
|
t.Fatalf("New() error = %v, want missing auth", err)
|
|
}
|
|
}
|
|
|
|
func TestTranslateErrorMapsSFTPStatusCodes(t *testing.T) {
|
|
backend := &Backend{}
|
|
tests := []struct {
|
|
name string
|
|
err error
|
|
want storage.ErrorKind
|
|
}{
|
|
{name: "not found", err: sftp.ErrSSHFxNoSuchFile, want: storage.ErrNotFound},
|
|
{name: "permission", err: sftp.ErrSSHFxPermissionDenied, want: storage.ErrPermission},
|
|
{name: "unsupported", err: sftp.ErrSSHFxOpUnsupported, want: storage.ErrUnsupported},
|
|
{name: "temporary", err: sftp.ErrSSHFxConnectionLost, want: storage.ErrTemporary},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := backend.translateError(storage.OpStat, "report.md", tt.err)
|
|
if !storage.IsKind(err, tt.want) {
|
|
t.Fatalf("translateError() = %v, want kind %s", err, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|