list for working dir

This commit is contained in:
Boshi Lian 2019-01-06 08:51:04 -08:00
parent 15939ea49e
commit c96750f280
7 changed files with 136 additions and 46 deletions

View file

@ -1,7 +1,10 @@
package main
import (
"fmt"
"github.com/tg123/sshpiper/sshpiperd/upstream"
"os"
"text/template"
)
func createPipeMgr(load func() (upstream.Provider, error)) interface{} {
@ -33,6 +36,24 @@ func createPipeMgr(load func() (upstream.Provider, error)) interface{} {
}{}
pipeMgrCmd.List.callback = func(args []string) error {
p, err := load()
if err != nil {
return err
}
// opt := pipeMgrCmd.List
pipes, err := p.ListPipe()
if err != nil {
return err
}
t := template.Must(template.New("").Parse(`{{.Username}} -> {{.UpstreamUsername}}@{{.Host}}:{{.Port}}`))
for _, pipe := range pipes {
t.Execute(os.Stdout, pipe)
fmt.Println()
}
return nil
}
@ -53,14 +74,14 @@ func createPipeMgr(load func() (upstream.Provider, error)) interface{} {
}
pipeMgrCmd.Remove.callback = func(args []string) error {
name := pipeMgrCmd.Remove.Name
p, err := load()
if err != nil {
return err
}
return p.RemovePipe(name)
opt := pipeMgrCmd.Remove
return p.RemovePipe(opt.Name)
}
return &pipeMgrCmd

View file

@ -112,12 +112,16 @@ type testupstream struct {
h upstream.Handler
}
func (t *testupstream) ListPipe() ([]upstream.Pipe, error) {
return nil, nil
}
func (t *testupstream) CreatePipe(opt upstream.CreatePipeOption) error {
panic("implement me")
return nil
}
func (t *testupstream) RemovePipe(name string) error {
panic("implement me")
return nil
}
func (t *testupstream) GetHandler() upstream.Handler {

View file

@ -20,6 +20,10 @@ type plugin struct {
db *gorm.DB
}
func (p *plugin) ListPipe() ([]upstreamprovider.Pipe, error) {
panic("implement me")
}
func (p *plugin) CreatePipe(opt upstreamprovider.CreatePipeOption) error {
panic("implement me")
}

View file

@ -21,12 +21,21 @@ type CreatePipeOption struct {
Port uint
}
type Pipe struct {
Username string
UpstreamUsername string
Host string
Port uint
}
// Provider is a factory for Upstream Provider
type Provider interface {
registry.Plugin
GetHandler() Handler
ListPipe() ([]Pipe, error)
CreatePipe(opt CreatePipeOption) error
RemovePipe(name string) error

View file

@ -14,6 +14,36 @@ var logger *log.Logger
type plugin struct {
}
func (p *plugin) ListPipe() ([]upstream.Pipe, error) {
files, err := ioutil.ReadDir(config.WorkingDir)
if err != nil {
return nil, err
}
pipes := make([]upstream.Pipe, 0, len(files))
for _, file := range files {
if !file.IsDir() {
continue
}
data, err := userUpstreamFile.read(file.Name())
if err != nil {
continue
}
host, port, mappedUser, err := parseUpstreamFile(string(data))
pipes = append(pipes, upstream.Pipe{
Host: host,
Port: uint(port),
Username: file.Name(),
UpstreamUsername: mappedUser,
})
}
return pipes, nil
}
func (p *plugin) CreatePipe(opt upstream.CreatePipeOption) error {
err := os.MkdirAll(config.WorkingDir+"/"+opt.Username, 0775)
if err != nil {
@ -35,7 +65,7 @@ func (p *plugin) CreatePipe(opt upstream.CreatePipeOption) error {
return err
}
return fmt.Errorf("upstream file alreay exists")
return fmt.Errorf("upstream file of [%v] alreay exists", opt.Username)
}
func (p *plugin) RemovePipe(name string) error {

View file

@ -14,6 +14,7 @@ import (
"os"
"path"
"regexp"
"strconv"
"strings"
"golang.org/x/crypto/ssh"
@ -83,43 +84,48 @@ func checkUsername(user string) bool {
return usernameRule.MatchString(user)
}
func parseUpstreamFile(data string) (string, string) {
var user string
var line string
func parseUpstreamFile(data string) (host string, port int, user string, err error) {
r := bufio.NewReader(strings.NewReader(data))
for {
var err error
line, err = r.ReadString('\n')
host, err = r.ReadString('\n')
if err != nil {
break
}
line = strings.TrimSpace(line)
host = strings.TrimSpace(host)
if line != "" && line[0] != '#' {
if host != "" && host[0] != '#' {
break
}
}
t := strings.SplitN(line, "@", 2)
t := strings.SplitN(host, "@", 2)
if len(t) > 1 {
user = t[0]
line = t[1]
host = t[1]
}
// test if ok
if _, _, err := net.SplitHostPort(line); err != nil && line != "" {
h, p, err := net.SplitHostPort(host)
if err == nil {
host = h
port, err = strconv.Atoi(p)
if err != nil {
return
}
} else if host != "" {
// test valid after concat :22
if _, _, err := net.SplitHostPort(line + ":22"); err == nil {
line += ":22"
if _, _, err := net.SplitHostPort(host + ":22"); err == nil {
port = 22
}
}
return line, user
if host == "" {
err = fmt.Errorf("empty addr")
}
return
}
func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, *ssh.AuthPipe, error) {
@ -143,11 +149,11 @@ func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, *ssh.AuthPipe, e
return nil, nil, err
}
addr, mappedUser := parseUpstreamFile(string(data))
if addr == "" {
return nil, nil, fmt.Errorf("empty addr")
host, port, mappedUser, err := parseUpstreamFile(string(data))
if err != nil {
return nil, nil, err
}
addr := fmt.Sprintf("%v:%v", host, port)
logger.Printf("mapping user [%v] to [%v@%v]", user, mappedUser, addr)

View file

@ -126,58 +126,74 @@ func (s stubConnMetadata) LocalAddr() net.Addr { return nil }
func TestParseUpstreamFile(t *testing.T) {
var addr, user string
{
addr, user = parseUpstreamFile(`
addr, port, user, _ := parseUpstreamFile(`
a:123
`)
if addr != "a:123" || user != "" {
t.Fatalf("parse failed common with port")
if addr != "a" || port != 123 || user != "" {
t.Fatalf("parse failed common with port")
}
}
addr, user = parseUpstreamFile(`
{
addr, port, user, _ := parseUpstreamFile(`
a:123
b:456
`)
if addr != "a:123" || user != "" {
t.Fatalf("parse multi line")
if addr != "a" || port != 123 || user != "" {
t.Fatalf("parse multi line")
}
}
addr, user = parseUpstreamFile(`
{
addr, port, user, _ := parseUpstreamFile(`
host
`)
if addr != "host:22" || user != "" {
t.Fatalf("parse no port")
if addr != "host" || port != 22 || user != "" {
t.Fatalf("parse no port")
}
}
addr, user = parseUpstreamFile(`
{
addr, port, user, _ := parseUpstreamFile(`
user@github.com
`)
if addr != "github.com:22" || user != "user" {
t.Fatalf("parse no port with user")
if addr != "github.com" || port != 22 || user != "user" {
t.Fatalf("parse no port with user")
}
}
addr, user = parseUpstreamFile(``)
{
if addr != "" || user != "" {
t.Fatalf("empty file")
_, _, _, err := parseUpstreamFile(``)
if err == nil {
t.Fatalf("empty file")
}
}
addr, user = parseUpstreamFile(`
{
addr, port, user, _ := parseUpstreamFile(`
# comment
user@github.com
test@linode.com
`)
if addr != "github.com:22" || user != "user" {
t.Fatalf("multi line with comment")
if addr != "github.com" || port != 22 || user != "user" {
t.Fatalf("multi line with comment")
}
}
}