mirror of
https://github.com/ssh-vault/ssh-vault.git
synced 2025-07-31 05:24:22 +03:00
cache, http client, vault
This commit is contained in:
50
cache.go
Normal file
50
cache.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package sshvault
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cache struct {
|
||||||
|
dir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Cache() *cache {
|
||||||
|
usr, _ := user.Current()
|
||||||
|
sv := filepath.Join(usr.HomeDir, ".ssh-vault", "keys")
|
||||||
|
if _, err := os.Stat(sv); os.IsNotExist(err) {
|
||||||
|
os.MkdirAll(sv, os.ModePerm)
|
||||||
|
}
|
||||||
|
return &cache{sv}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) Get(u string) (string, error) {
|
||||||
|
uKey := fmt.Sprintf("%s/%s.key", c.dir, u)
|
||||||
|
if c.isFile(uKey) {
|
||||||
|
// read from file and return
|
||||||
|
}
|
||||||
|
key, err := GetKey(u)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(uKey, []byte(key), 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) isFile(path string) bool {
|
||||||
|
f, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if m := f.Mode(); !m.IsDir() && m.IsRegular() && m&400 != 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@ -4,6 +4,8 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
sv "github.com/ssh-vault/ssh-vault"
|
sv "github.com/ssh-vault/ssh-vault"
|
||||||
)
|
)
|
||||||
@ -11,22 +13,58 @@ import (
|
|||||||
var version string
|
var version string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
parser := &sv.Parse{}
|
var (
|
||||||
|
k = flag.String("k", "~/.ssh/id_rsa.pub", "public `ssh key`")
|
||||||
|
u = flag.String("u", "", "GitHub `username`")
|
||||||
|
options = []string{"create", "decrypt", "edit", "encrypt", "view"}
|
||||||
|
v = flag.Bool("v", false, fmt.Sprintf("Print version: %s", version))
|
||||||
|
)
|
||||||
|
|
||||||
// flag set
|
flag.Usage = func() {
|
||||||
fs := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
|
fmt.Fprintf(os.Stderr, "Usage: %s [-k key] [-u user] [create|decrypt|edit|encrypt|view] vault\n\n%s\n%s\n%s\n%s\n%s\n%s\n\n",
|
||||||
fs.Usage = parser.Usage(fs)
|
os.Args[0],
|
||||||
|
" Options:",
|
||||||
err := sv.ParseArgs(parser, fs)
|
" create creates a new vault",
|
||||||
if err != nil {
|
" decrypt decrypt a file",
|
||||||
fmt.Fprintln(os.Stderr, err)
|
" edit open an existing vault",
|
||||||
os.Exit(1)
|
" encrypt encrypt a file",
|
||||||
|
" view open an existing vault")
|
||||||
|
flag.PrintDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
// if -v print version
|
flag.Parse()
|
||||||
if (fs.Lookup("v")).Value.(flag.Getter).Get().(bool) {
|
|
||||||
|
if *v {
|
||||||
fmt.Printf("%s\n", version)
|
fmt.Printf("%s\n", version)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flag.NArg() < 1 {
|
||||||
|
fmt.Printf("Missing option, use (\"%s -h\") for help.\n", os.Args[0])
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
exit := true
|
||||||
|
for _, v := range options {
|
||||||
|
if flag.Arg(0) == v {
|
||||||
|
exit = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if exit {
|
||||||
|
fmt.Printf("Invalid option, use (\"%s -h\") for help.\n", os.Args[0])
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag.NArg() < 2 {
|
||||||
|
fmt.Printf("Missing vault name, use (\"%s -h\") for help.\n", os.Args[0])
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
usr, _ := user.Current()
|
||||||
|
if (*k)[:2] == "~/" {
|
||||||
|
*k = filepath.Join(usr.HomeDir, (*k)[2:])
|
||||||
|
}
|
||||||
|
|
||||||
|
sv.New(*k, *u, flag.Arg(0), flag.Arg(1))
|
||||||
}
|
}
|
||||||
|
11
flags.go
11
flags.go
@ -1,11 +0,0 @@
|
|||||||
package sshvault
|
|
||||||
|
|
||||||
// Flags available command flags
|
|
||||||
type Flags struct {
|
|
||||||
Version bool
|
|
||||||
Create string
|
|
||||||
Decrypt string
|
|
||||||
Edit string
|
|
||||||
Encrypt string
|
|
||||||
View string
|
|
||||||
}
|
|
35
getkey.go
Normal file
35
getkey.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package sshvault
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/textproto"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const GITHUB = "https://github.com"
|
||||||
|
|
||||||
|
func GetKey(u string) (string, error) {
|
||||||
|
client := &http.Client{}
|
||||||
|
// create a new request
|
||||||
|
req, _ := http.NewRequest("GET", fmt.Sprintf("%s/%s.keys",
|
||||||
|
GITHUB,
|
||||||
|
u),
|
||||||
|
nil)
|
||||||
|
req.Header.Set("User-Agent", "ssh-vault")
|
||||||
|
res, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
reader := bufio.NewReader(res.Body)
|
||||||
|
tp := textproto.NewReader(reader)
|
||||||
|
for {
|
||||||
|
if line, err := tp.ReadLine(); err != nil {
|
||||||
|
return "", err
|
||||||
|
} else if strings.HasPrefix(line, "ssh-") {
|
||||||
|
return line, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
106
parser.go
106
parser.go
@ -1,106 +0,0 @@
|
|||||||
package sshvault
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Parser interface
|
|
||||||
type Parser interface {
|
|
||||||
Parse(fs *flag.FlagSet) (*Flags, error)
|
|
||||||
isDir(path string) bool
|
|
||||||
isFile(path string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse implements parser
|
|
||||||
type Parse struct {
|
|
||||||
Flags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parse the command line flags
|
|
||||||
func (p *Parse) Parse(fs *flag.FlagSet) (*Flags, error) {
|
|
||||||
fs.BoolVar(&p.Flags.Version, "v", false, "Print version")
|
|
||||||
fs.StringVar(&p.Flags.Create, "c", "", "create vault")
|
|
||||||
|
|
||||||
err := fs.Parse(os.Args[1:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &p.Flags, nil
|
|
||||||
}
|
|
||||||
func (p *Parse) Usage(fs *flag.FlagSet) func() {
|
|
||||||
return func() {
|
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s [create|decrypt|edit|encrypt|view] [-k key] [-u user] vault\n\n", os.Args[0])
|
|
||||||
var flags []string
|
|
||||||
fs.VisitAll(func(f *flag.Flag) {
|
|
||||||
flags = append(flags, f.Name)
|
|
||||||
})
|
|
||||||
sort.Strings(flags)
|
|
||||||
for _, v := range flags {
|
|
||||||
f := fs.Lookup(v)
|
|
||||||
s := fmt.Sprintf(" -%s", f.Name)
|
|
||||||
name, usage := flag.UnquoteUsage(f)
|
|
||||||
if len(name) > 0 {
|
|
||||||
s += " " + name
|
|
||||||
}
|
|
||||||
if len(s) <= 4 {
|
|
||||||
s += "\t"
|
|
||||||
} else {
|
|
||||||
s += "\n \t"
|
|
||||||
}
|
|
||||||
s += usage
|
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parse) isDir(path string) bool {
|
|
||||||
f, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if m := f.Mode(); m.IsDir() && m&400 != 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parse) isFile(path string) bool {
|
|
||||||
f, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if m := f.Mode(); !m.IsDir() && m.IsRegular() && m&400 != 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parse) checkWrkdir(dir string) (err error) {
|
|
||||||
if !p.isDir(dir) {
|
|
||||||
err = fmt.Errorf("-d %q does not exist or has wrong permissions, use (\"%s -h\") for help.", dir, os.Args[0])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseArgs parse command arguments
|
|
||||||
func ParseArgs(p Parser, fs *flag.FlagSet) (err error) {
|
|
||||||
flags, err := p.Parse(fs)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// if -v
|
|
||||||
if flags.Version {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no args
|
|
||||||
if len(fs.Args()) < 1 {
|
|
||||||
err = fmt.Errorf("Missing user, use (\"%s -h\") for help.", os.Args[0])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
24
vault.go
Normal file
24
vault.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package sshvault
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Vault structure
|
||||||
|
type Vault struct {
|
||||||
|
key string
|
||||||
|
user string
|
||||||
|
option string
|
||||||
|
vault string
|
||||||
|
}
|
||||||
|
|
||||||
|
// New initialize vault parameters
|
||||||
|
func New(k, u, o, v string) error {
|
||||||
|
cache := Cache()
|
||||||
|
if u != "" {
|
||||||
|
path, err := cache.Get(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("path = %+v\n", path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Reference in New Issue
Block a user