github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/client/cmd/keys.go (about) 1 package cmd 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "path" 7 "regexp" 8 "sort" 9 "strconv" 10 "strings" 11 12 "github.com/deis/deis/client/controller/api" 13 "github.com/deis/deis/client/controller/client" 14 "github.com/deis/deis/client/controller/models/keys" 15 ) 16 17 // KeysList lists a user's keys. 18 func KeysList(results int) error { 19 c, err := client.New() 20 21 if err != nil { 22 return err 23 } 24 25 if results == defaultLimit { 26 results = c.ResponseLimit 27 } 28 29 keys, count, err := keys.List(c, results) 30 31 if err != nil { 32 return err 33 } 34 35 fmt.Printf("=== %s Keys%s", c.Username, limitCount(len(keys), count)) 36 37 sort.Sort(keys) 38 39 for _, key := range keys { 40 fmt.Printf("%s %s...%s\n", key.ID, key.Public[:16], key.Public[len(key.Public)-10:]) 41 } 42 return nil 43 } 44 45 // KeyRemove removes keys. 46 func KeyRemove(keyID string) error { 47 c, err := client.New() 48 49 if err != nil { 50 return err 51 } 52 53 fmt.Printf("Removing %s SSH Key...", keyID) 54 55 if err = keys.Delete(c, keyID); err != nil { 56 fmt.Println() 57 return err 58 } 59 60 fmt.Println(" done") 61 return nil 62 } 63 64 // KeyAdd adds keys. 65 func KeyAdd(keyLocation string) error { 66 c, err := client.New() 67 68 if err != nil { 69 return err 70 } 71 72 var key api.KeyCreateRequest 73 74 if keyLocation == "" { 75 key, err = chooseKey() 76 } else { 77 key, err = getKey(keyLocation) 78 } 79 80 if err != nil { 81 return err 82 } 83 84 fmt.Printf("Uploading %s to deis...", path.Base(key.Name)) 85 86 if _, err = keys.New(c, key.ID, key.Public); err != nil { 87 fmt.Println() 88 return err 89 } 90 91 fmt.Println(" done") 92 return nil 93 } 94 95 func chooseKey() (api.KeyCreateRequest, error) { 96 keys, err := listKeys() 97 98 if err != nil { 99 return api.KeyCreateRequest{}, err 100 } 101 102 fmt.Println("Found the following SSH public keys:") 103 104 for i, key := range keys { 105 fmt.Printf("%d) %s %s\n", i+1, path.Base(key.Name), key.ID) 106 } 107 108 fmt.Println("0) Enter path to pubfile (or use keys:add <key_path>)") 109 110 var selected string 111 112 fmt.Print("Which would you like to use with Deis? ") 113 fmt.Scanln(&selected) 114 115 numSelected, err := strconv.Atoi(selected) 116 117 if err != nil { 118 return api.KeyCreateRequest{}, err 119 } 120 121 if numSelected > len(keys)+1 { 122 return api.KeyCreateRequest{}, fmt.Errorf("%d is not a valid option", numSelected) 123 } 124 125 if numSelected == 0 { 126 var filename string 127 128 fmt.Print("Enter the path to the pubkey file: ") 129 fmt.Scanln(&filename) 130 131 return getKey(filename) 132 } 133 134 return keys[numSelected-1], nil 135 } 136 137 func listKeys() ([]api.KeyCreateRequest, error) { 138 folder := path.Join(client.FindHome(), ".ssh") 139 files, err := ioutil.ReadDir(folder) 140 141 if err != nil { 142 return nil, err 143 } 144 145 var keys []api.KeyCreateRequest 146 147 for _, file := range files { 148 if path.Ext(file.Name()) == ".pub" { 149 key, err := getKey(path.Join(folder, file.Name())) 150 151 if err == nil { 152 keys = append(keys, key) 153 } else { 154 fmt.Println(err) 155 } 156 } 157 } 158 159 return keys, nil 160 } 161 162 func getKey(filename string) (api.KeyCreateRequest, error) { 163 regex := regexp.MustCompile("^(ssh-...|ecdsa-[^ ]+) ([^ ]+) ?(.*)") 164 contents, err := ioutil.ReadFile(filename) 165 166 if err != nil { 167 return api.KeyCreateRequest{}, err 168 } 169 170 if regex.Match(contents) { 171 capture := regex.FindStringSubmatch(string(contents)) 172 if capture[3] != "" { 173 return api.KeyCreateRequest{ID: capture[3], Public: string(contents), Name: filename}, nil 174 } 175 176 id := strings.Split(path.Base(filename), ".")[0] 177 return api.KeyCreateRequest{ID: id, Public: string(contents), Name: filename}, nil 178 } 179 180 return api.KeyCreateRequest{}, fmt.Errorf("%s is not a valid ssh key", filename) 181 }