Browse code

Integrate Auth in runtime and make the config file relative to runtime root

creack authored on 2013/03/22 18:19:39
Showing 6 changed files
... ...
@@ -7,3 +7,4 @@ build_src
7 7
 command-line-arguments.test
8 8
 .flymake*
9 9
 docker.test
10
+auth/auth.test
... ...
@@ -8,11 +8,12 @@ import (
8 8
 	"io/ioutil"
9 9
 	"net/http"
10 10
 	"os"
11
+	"path"
11 12
 	"strings"
12 13
 )
13 14
 
14 15
 // Where we store the config file
15
-const CONFIGFILE = "/var/lib/docker/.dockercfg"
16
+const CONFIGFILE = ".dockercfg"
16 17
 
17 18
 // the registry server we want to login against
18 19
 //const REGISTRY_SERVER = "https://registry.docker.io"
... ...
@@ -22,10 +23,11 @@ type AuthConfig struct {
22 22
 	Username string `json:"username"`
23 23
 	Password string `json:"password"`
24 24
 	Email    string `json:"email"`
25
+	rootPath string `json:-`
25 26
 }
26 27
 
27 28
 // create a base64 encoded auth string to store in config
28
-func EncodeAuth(authConfig AuthConfig) string {
29
+func EncodeAuth(authConfig *AuthConfig) string {
29 30
 	authStr := authConfig.Username + ":" + authConfig.Password
30 31
 	msg := []byte(authStr)
31 32
 	encoded := make([]byte, base64.StdEncoding.EncodedLen(len(msg)))
... ...
@@ -34,50 +36,54 @@ func EncodeAuth(authConfig AuthConfig) string {
34 34
 }
35 35
 
36 36
 // decode the auth string
37
-func DecodeAuth(authStr string) (AuthConfig, error) {
37
+func DecodeAuth(authStr string) (*AuthConfig, error) {
38 38
 	decLen := base64.StdEncoding.DecodedLen(len(authStr))
39 39
 	decoded := make([]byte, decLen)
40 40
 	authByte := []byte(authStr)
41 41
 	n, err := base64.StdEncoding.Decode(decoded, authByte)
42 42
 	if err != nil {
43
-		return AuthConfig{}, err
43
+		return nil, err
44 44
 	}
45 45
 	if n > decLen {
46
-		return AuthConfig{}, errors.New("something went wrong decoding auth config")
46
+		return nil, fmt.Errorf("Something went wrong decoding auth config")
47 47
 	}
48 48
 	arr := strings.Split(string(decoded), ":")
49
+	if len(arr) != 2 {
50
+		return nil, fmt.Errorf("Invalid auth configuration file")
51
+	}
49 52
 	password := strings.Trim(arr[1], "\x00")
50
-	return AuthConfig{Username: arr[0], Password: password}, nil
53
+	return &AuthConfig{Username: arr[0], Password: password}, nil
51 54
 
52 55
 }
53 56
 
54 57
 // load up the auth config information and return values
55
-func LoadConfig() (AuthConfig, error) {
56
-	if _, err := os.Stat(CONFIGFILE); err == nil {
57
-		b, err := ioutil.ReadFile(CONFIGFILE)
58
-		if err != nil {
59
-			return AuthConfig{}, err
60
-		}
61
-		arr := strings.Split(string(b), "\n")
62
-		orig_auth := strings.Split(arr[0], " = ")
63
-		orig_email := strings.Split(arr[1], " = ")
64
-		authConfig, err := DecodeAuth(orig_auth[1])
65
-		if err != nil {
66
-			return AuthConfig{}, err
67
-		}
68
-		authConfig.Email = orig_email[1]
69
-		return authConfig, nil
70
-	} else {
71
-		return AuthConfig{}, nil
58
+// FIXME: use the internal golang config parser
59
+func LoadConfig(rootPath string) (*AuthConfig, error) {
60
+	confFile := path.Join(rootPath, CONFIGFILE)
61
+	if _, err := os.Stat(confFile); err != nil {
62
+		return &AuthConfig{}, fmt.Errorf("The Auth config file is missing")
63
+	}
64
+	b, err := ioutil.ReadFile(confFile)
65
+	if err != nil {
66
+		return nil, err
67
+	}
68
+	arr := strings.Split(string(b), "\n")
69
+	orig_auth := strings.Split(arr[0], " = ")
70
+	orig_email := strings.Split(arr[1], " = ")
71
+	authConfig, err := DecodeAuth(orig_auth[1])
72
+	if err != nil {
73
+		return nil, err
72 74
 	}
73
-	return AuthConfig{}, nil
75
+	authConfig.Email = orig_email[1]
76
+	authConfig.rootPath = rootPath
77
+	return authConfig, nil
74 78
 }
75 79
 
76 80
 // save the auth config
77
-func saveConfig(authStr string, email string) error {
81
+func saveConfig(rootPath, authStr string, email string) error {
78 82
 	lines := "auth = " + authStr + "\n" + "email = " + email + "\n"
79 83
 	b := []byte(lines)
80
-	err := ioutil.WriteFile(CONFIGFILE, b, 0600)
84
+	err := ioutil.WriteFile(path.Join(rootPath, CONFIGFILE), b, 0600)
81 85
 	if err != nil {
82 86
 		return err
83 87
 	}
... ...
@@ -85,7 +91,7 @@ func saveConfig(authStr string, email string) error {
85 85
 }
86 86
 
87 87
 // try to register/login to the registry server
88
-func Login(authConfig AuthConfig) (string, error) {
88
+func Login(authConfig *AuthConfig) (string, error) {
89 89
 	storeConfig := false
90 90
 	reqStatusCode := 0
91 91
 	var status string
... ...
@@ -146,7 +152,7 @@ func Login(authConfig AuthConfig) (string, error) {
146 146
 	}
147 147
 	if storeConfig {
148 148
 		authStr := EncodeAuth(authConfig)
149
-		saveConfig(authStr, authConfig.Email)
149
+		saveConfig(authConfig.rootPath, authStr, authConfig.Email)
150 150
 	}
151 151
 	return status, nil
152 152
 }
... ...
@@ -5,7 +5,7 @@ import (
5 5
 )
6 6
 
7 7
 func TestEncodeAuth(t *testing.T) {
8
-	newAuthConfig := AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
8
+	newAuthConfig := &AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
9 9
 	authStr := EncodeAuth(newAuthConfig)
10 10
 	decAuthConfig, err := DecodeAuth(authStr)
11 11
 	if err != nil {
... ...
@@ -69,17 +69,13 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout io.Writer, args ...strin
69 69
 	var username string
70 70
 	var password string
71 71
 	var email string
72
-	authConfig, err := auth.LoadConfig()
73
-	if err != nil {
74
-		fmt.Fprintf(stdout, "Error : %s\n", err)
75
-	}
76 72
 
77
-	fmt.Fprint(stdout, "Username (", authConfig.Username, "): ")
73
+	fmt.Fprint(stdout, "Username (", srv.runtime.authConfig.Username, "): ")
78 74
 	fmt.Fscanf(stdin, "%s", &username)
79 75
 	if username == "" {
80
-		username = authConfig.Username
76
+		username = srv.runtime.authConfig.Username
81 77
 	}
82
-	if username != authConfig.Username {
78
+	if username != srv.runtime.authConfig.Username {
83 79
 		fmt.Fprint(stdout, "Password: ")
84 80
 		fmt.Fscanf(stdin, "%s", &password)
85 81
 
... ...
@@ -87,16 +83,16 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout io.Writer, args ...strin
87 87
 			return errors.New("Error : Password Required\n")
88 88
 		}
89 89
 
90
-		fmt.Fprint(stdout, "Email (", authConfig.Email, "): ")
90
+		fmt.Fprint(stdout, "Email (", srv.runtime.authConfig.Email, "): ")
91 91
 		fmt.Fscanf(stdin, "%s", &email)
92 92
 		if email == "" {
93
-			email = authConfig.Email
93
+			email = srv.runtime.authConfig.Email
94 94
 		}
95 95
 	} else {
96
-		password = authConfig.Password
97
-		email = authConfig.Email
96
+		password = srv.runtime.authConfig.Password
97
+		email = srv.runtime.authConfig.Email
98 98
 	}
99
-	newAuthConfig := auth.AuthConfig{Username: username, Password: password, Email: email}
99
+	newAuthConfig := &auth.AuthConfig{Username: username, Password: password, Email: email}
100 100
 	status, err := auth.Login(newAuthConfig)
101 101
 	if err != nil {
102 102
 		fmt.Fprintf(stdout, "Error : %s\n", err)
... ...
@@ -473,7 +469,7 @@ func (srv *Server) CmdPull(stdin io.ReadCloser, stdout io.Writer, args ...string
473 473
 		return fmt.Errorf("Not loggin and no user specified\n")
474 474
 	}
475 475
 	// FIXME: Allow pull repo:tag
476
-	return srv.runtime.graph.PullRepository(*user, cmd.Arg(0), "", srv.runtime.repositories)
476
+	return srv.runtime.graph.PullRepository(*user, cmd.Arg(0), "", srv.runtime.repositories, srv.runtime.authConfig)
477 477
 }
478 478
 
479 479
 func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
... ...
@@ -867,9 +863,6 @@ func NewServer() (*Server, error) {
867 867
 	if runtime.GOARCH != "amd64" {
868 868
 		log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
869 869
 	}
870
-	// if err != nil {
871
-	// 	return nil, err
872
-	// }
873 870
 	runtime, err := NewRuntime()
874 871
 	if err != nil {
875 872
 		return nil, err
... ...
@@ -129,19 +129,15 @@ func (graph *Graph) PullImage(imgId string) error {
129 129
 }
130 130
 
131 131
 // FIXME: Handle the askedTag parameter
132
-func (graph *Graph) PullRepository(user, repoName, askedTag string, repositories *TagStore) error {
132
+func (graph *Graph) PullRepository(user, repoName, askedTag string, repositories *TagStore, authConfig *auth.AuthConfig) error {
133 133
 	client := &http.Client{}
134 134
 
135 135
 	req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/users/"+user+"/"+repoName, nil)
136 136
 	if err != nil {
137 137
 		return err
138 138
 	}
139
-	authStruct, err := auth.LoadConfig()
140
-	if err != nil {
141
-		return err
142
-	}
143 139
 
144
-	req.SetBasicAuth(authStruct.Username, authStruct.Password)
140
+	req.SetBasicAuth(authConfig.Username, authConfig.Password)
145 141
 	res, err := client.Do(req)
146 142
 	if err != nil {
147 143
 		return err
... ...
@@ -3,6 +3,7 @@ package docker
3 3
 import (
4 4
 	"container/list"
5 5
 	"fmt"
6
+	"github.com/dotcloud/docker/auth"
6 7
 	"io"
7 8
 	"io/ioutil"
8 9
 	"log"
... ...
@@ -20,6 +21,7 @@ type Runtime struct {
20 20
 	networkManager *NetworkManager
21 21
 	graph          *Graph
22 22
 	repositories   *TagStore
23
+	authConfig     *auth.AuthConfig
23 24
 }
24 25
 
25 26
 var sysInitPath string
... ...
@@ -246,6 +248,11 @@ func NewRuntimeFromDirectory(root string) (*Runtime, error) {
246 246
 	if err != nil {
247 247
 		return nil, err
248 248
 	}
249
+	authConfig, err := auth.LoadConfig(root)
250
+	if err != nil && authConfig == nil {
251
+		// If the auth file does not exist, keep going
252
+		return nil, err
253
+	}
249 254
 
250 255
 	runtime := &Runtime{
251 256
 		root:           root,
... ...
@@ -254,6 +261,7 @@ func NewRuntimeFromDirectory(root string) (*Runtime, error) {
254 254
 		networkManager: netManager,
255 255
 		graph:          g,
256 256
 		repositories:   repositories,
257
+		authConfig:     authConfig,
257 258
 	}
258 259
 
259 260
 	if err := runtime.restore(); err != nil {