1package credentials 2 3import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "fmt" 8 "io" 9 "os" 10 "strings" 11) 12 13// Credentials holds the information shared between docker and the credentials store. 14type Credentials struct { 15 ServerURL string 16 Username string 17 Secret string 18} 19 20// Serve initializes the credentials helper and parses the action argument. 21// This function is designed to be called from a command line interface. 22// It uses os.Args[1] as the key for the action. 23// It uses os.Stdin as input and os.Stdout as output. 24// This function terminates the program with os.Exit(1) if there is an error. 25func Serve(helper Helper) { 26 var err error 27 if len(os.Args) != 2 { 28 err = fmt.Errorf("Usage: %s <store|get|erase|list>", os.Args[0]) 29 } 30 31 if err == nil { 32 err = HandleCommand(helper, os.Args[1], os.Stdin, os.Stdout) 33 } 34 35 if err != nil { 36 fmt.Fprintf(os.Stdout, "%v\n", err) 37 os.Exit(1) 38 } 39} 40 41// HandleCommand uses a helper and a key to run a credential action. 42func HandleCommand(helper Helper, key string, in io.Reader, out io.Writer) error { 43 switch key { 44 case "store": 45 return Store(helper, in) 46 case "get": 47 return Get(helper, in, out) 48 case "erase": 49 return Erase(helper, in) 50 case "list": 51 return List(helper, out) 52 } 53 return fmt.Errorf("Unknown credential action `%s`", key) 54} 55 56// Store uses a helper and an input reader to save credentials. 57// The reader must contain the JSON serialization of a Credentials struct. 58func Store(helper Helper, reader io.Reader) error { 59 scanner := bufio.NewScanner(reader) 60 61 buffer := new(bytes.Buffer) 62 for scanner.Scan() { 63 buffer.Write(scanner.Bytes()) 64 } 65 66 if err := scanner.Err(); err != nil && err != io.EOF { 67 return err 68 } 69 70 var creds Credentials 71 if err := json.NewDecoder(buffer).Decode(&creds); err != nil { 72 return err 73 } 74 75 return helper.Add(&creds) 76} 77 78// Get retrieves the credentials for a given server url. 79// The reader must contain the server URL to search. 80// The writer is used to write the JSON serialization of the credentials. 81func Get(helper Helper, reader io.Reader, writer io.Writer) error { 82 scanner := bufio.NewScanner(reader) 83 84 buffer := new(bytes.Buffer) 85 for scanner.Scan() { 86 buffer.Write(scanner.Bytes()) 87 } 88 89 if err := scanner.Err(); err != nil && err != io.EOF { 90 return err 91 } 92 93 serverURL := strings.TrimSpace(buffer.String()) 94 95 username, secret, err := helper.Get(serverURL) 96 if err != nil { 97 return err 98 } 99 100 resp := Credentials{ 101 Username: username, 102 Secret: secret, 103 } 104 105 buffer.Reset() 106 if err := json.NewEncoder(buffer).Encode(resp); err != nil { 107 return err 108 } 109 110 fmt.Fprint(writer, buffer.String()) 111 return nil 112} 113 114// Erase removes credentials from the store. 115// The reader must contain the server URL to remove. 116func Erase(helper Helper, reader io.Reader) error { 117 scanner := bufio.NewScanner(reader) 118 119 buffer := new(bytes.Buffer) 120 for scanner.Scan() { 121 buffer.Write(scanner.Bytes()) 122 } 123 124 if err := scanner.Err(); err != nil && err != io.EOF { 125 return err 126 } 127 128 serverURL := strings.TrimSpace(buffer.String()) 129 130 return helper.Delete(serverURL) 131} 132 133//List returns all the serverURLs of keys in 134//the OS store as a list of strings 135func List(helper Helper, writer io.Writer) error { 136 accts, err := helper.List() 137 if err != nil { 138 return err 139 } 140 return json.NewEncoder(writer).Encode(accts) 141} 142