Skip to content

Commit

Permalink
Merge branch 'release/0.11.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
nbari committed Apr 5, 2017
2 parents ba9ab2b + f17d550 commit 4f9116a
Show file tree
Hide file tree
Showing 8 changed files with 425 additions and 50 deletions.
54 changes: 49 additions & 5 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package sshvault

import (
"crypto/md5"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
"os"
"os/user"
"path/filepath"
"strings"

"github.com/ssh-vault/ssh2pem"
)

type cache struct {
Expand All @@ -25,20 +29,27 @@ func Cache() *cache {
}

// Get return ssh-key
func (c *cache) Get(s Schlosser, u string, k int) (string, error) {
func (c *cache) Get(s Schlosser, u, f string, k int) (string, error) {
if k == 0 {
k = 1
}

// storage format
// ~/.ssh/vault/keys/user.key-N
// or
// ~/.ssh/vault/keys/<md5>.key-N
var (
uKey string
hash string
)
if !isURL.MatchString(u) {
uKey = fmt.Sprintf("%s/%s.key-%d", c.dir, u, k)
uKey = fmt.Sprintf("%s/%s.%d", c.dir, u, k)
} else {
hash = fmt.Sprintf("%x", md5.Sum([]byte(u)))
uKey = fmt.Sprintf("%s/%s.key-%d", c.dir, hash, k)
uKey = fmt.Sprintf("%s/%s.%d", c.dir, hash, k)
}

// if key not found, fetch it
if !c.IsFile(uKey) {
keys, err := s.GetKey(u)
if err != nil {
Expand All @@ -48,7 +59,7 @@ func (c *cache) Get(s Schlosser, u string, k int) (string, error) {
u = hash
}
for k, v := range keys {
err = ioutil.WriteFile(fmt.Sprintf("%s/%s.key-%d", c.dir, u, k+1),
err = ioutil.WriteFile(fmt.Sprintf("%s/%s.%d", c.dir, u, k+1),
[]byte(v),
0644)
if err != nil {
Expand All @@ -58,8 +69,17 @@ func (c *cache) Get(s Schlosser, u string, k int) (string, error) {
if !c.IsFile(uKey) {
return "", fmt.Errorf("key index not found, try -k with a value between 1 and %d", len(keys))
}
return uKey, nil
}

// if fingerprint, find the key that matches
if f != "" {
key, err := c.FindFingerprint(uKey, f)
if err != nil {
return "", err
}
return key, nil
}

return uKey, nil
}

Expand All @@ -74,3 +94,27 @@ func (c *cache) IsFile(path string) bool {
}
return false
}

// Find searches for key
func (c *cache) FindFingerprint(u, f string) (string, error) {
files, err := ioutil.ReadDir(c.dir)
if err != nil {
return "", err
}
var user = strings.TrimSuffix(filepath.Base(u), filepath.Ext(filepath.Base(u)))
for _, file := range files {
if strings.HasPrefix(file.Name(), user) {
out, err := ssh2pem.GetPem(filepath.Join(c.dir, file.Name()))
if err != nil {
return "", err
}
p, _ := pem.Decode(out)
x := &vault{}
fingerprint, _ := x.GenFingerprint(p)
if f == fingerprint {
return u, nil
}
}
}
return "", fmt.Errorf("key fingerprint: %q not found", f)
}
2 changes: 1 addition & 1 deletion cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func TestCacheGet(t *testing.T) {
cache := &cache{dir}
gk := mockSchlosser{}
for _, tt := range testTable {
out, err := cache.Get(gk, tt.user, tt.key)
out, err := cache.Get(gk, tt.user, "", tt.key)
if tt.err {
if err == nil {
t.Error("Expecting error")
Expand Down
74 changes: 60 additions & 14 deletions cmd/ssh-vault/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"os/user"
"path/filepath"
"regexp"

"github.com/ssh-vault/crypto"
"github.com/ssh-vault/crypto/aead"
Expand All @@ -22,16 +23,21 @@ func exit1(err error) {

func main() {
var (
f = flag.Bool("f", false, "Print ssh key `fingerprint`")
k = flag.String("k", "~/.ssh/id_rsa.pub", "Public `ssh key or index` when using option -u")
o = flag.String("o", "", "Write output to `file` instead of stdout. Only for option view")
u = flag.String("u", "", "GitHub `username or URL`, optional [-k N] where N is the key index to use")
v = flag.Bool("v", false, fmt.Sprintf("Print version: %s", version))
options = []string{"create", "edit", "view"}
f = flag.Bool("f", false, "Print ssh key `fingerprint` or create a vault using the key matching the specified fingerprint")
k = flag.String("k", "~/.ssh/id_rsa.pub", "Public `ssh key or index` when using option -u")
o = flag.String("o", "", "Write output to `file` instead of stdout. Only for option view")
u = flag.String("u", "", "GitHub `username or URL`, optional [-k N] where N is the key index to use")
v = flag.Bool("v", false, fmt.Sprintf("Print version: %s", version))
options = []string{"create", "edit", "view"}
rxFingerprint = regexp.MustCompile(`^([0-9a-f]{2}[:-]){15}([0-9a-f]{2})$`)
err error
fingerprint string
option string
outFile string
)

flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [-k key] [-o file] [-u user] [create|edit|view] vault\n\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n",
fmt.Fprintf(os.Stderr, "Usage: %s [-f fingerprint] [-k key] [-o file] [-u user] [create|edit|view] vault\n\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n",
os.Args[0],
" Options:",
" create Creates a new vault, if no vault defined outputs to stdout.",
Expand All @@ -51,8 +57,39 @@ func main() {
os.Exit(0)
}

// only print fingerprint
if flag.NArg() < 1 && !*f {
exit1(fmt.Errorf("Missing option, use (\"%s -h\") for help.\n", os.Args[0]))
exit1(fmt.Errorf("Missing option, use (\"%s -h\") for help.", os.Args[0]))
}

// set option to be the first argument if no -f <fingerprint> is defined
option = flag.Arg(0)
outFile = flag.Arg(1)

// using -f with fingerprint
if *f {
if flag.NArg() == 1 {
exit1(fmt.Errorf("Missing fingerprint/option, use (\"%s -h\") for help.", os.Args[0]))
}
if flag.NArg() >= 1 {
if !rxFingerprint.Match([]byte(flag.Arg(0))) {
exit1(fmt.Errorf("Bad fingerprint format, use (\"%s -h\") for help.", os.Args[0]))
}
if flag.Arg(1) != "create" {
exit1(fmt.Errorf("-f fingerprint can only be used with the %q option, use (\"%s -h\") for help.", "create", os.Args[0]))
}
// create using fingerprint
*f = false
fingerprint = flag.Arg(0)
option = flag.Arg(1)
outFile = flag.Arg(2)

flagset := make(map[string]bool)
flag.Visit(func(f *flag.Flag) { flagset[f.Name] = true })
if flagset["k"] {
exit1(fmt.Errorf("-f fingerprint have no effect when specifying key using -k, use (\"%s -h\") for help.", os.Args[0]))
}
}
}

usr, _ := user.Current()
Expand All @@ -62,26 +99,35 @@ func main() {
}
}

vault, err := sv.New(*k, *u, flag.Arg(0), flag.Arg(1))
vault, err := sv.New(fingerprint, *k, *u, option, outFile)
if err != nil {
exit1(err)
}

// ssh-keygen -f id_rsa.pub -e -m PKCS8
if err := vault.PKCS8(); err != nil {
PKCS8, err := vault.PKCS8()
if err != nil {
exit1(err)
}

vault.PublicKey, err = vault.GetRSAPublicKey(PKCS8)
if err != nil {
exit1(err)
}
vault.Fingerprint, err = vault.GenFingerprint(PKCS8)
if err != nil {
exit1(err)
}

// print fingerprint and exit
if *f {
fmt.Println(vault.Fingerprint)
fmt.Printf("%s\n", vault.Fingerprint)
os.Exit(0)
}

// check options
exit := true
for _, v := range options {
if flag.Arg(0) == v {
if option == v {
exit = false
break
}
Expand All @@ -95,7 +141,7 @@ func main() {
exit1(err)
}

switch flag.Arg(0) {
switch option {
case "create":
data, err := vault.Create()
if err != nil {
Expand Down
15 changes: 13 additions & 2 deletions create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,23 @@ func TestCreate(t *testing.T) {

tmpfile := filepath.Join(dir, "vault")

vault, err := New("test_data/id_rsa.pub", "", "create", tmpfile)
vault, err := New("", "test_data/id_rsa.pub", "", "create", tmpfile)
if err != nil {
t.Error(err)
}

if err = vault.PKCS8(); err != nil {
PKCS8, err := vault.PKCS8()
if err != nil {
t.Error(err)
}

vault.PublicKey, err = vault.GetRSAPublicKey(PKCS8)
if err != nil {
t.Error(err)
}

vault.Fingerprint, err = vault.GenFingerprint(PKCS8)
if err != nil {
t.Error(err)
}

Expand Down

0 comments on commit 4f9116a

Please sign in to comment.