Browse Source

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

creack 12 years ago
parent
commit
c72ff318d3
6 changed files with 55 additions and 51 deletions
  1. 1 0
      .gitignore
  2. 34 28
      auth/auth.go
  3. 1 1
      auth/auth_test.go
  4. 9 16
      commands.go
  5. 2 6
      registry.go
  6. 8 0
      runtime.go

+ 1 - 0
.gitignore

@@ -7,3 +7,4 @@ build_src
 command-line-arguments.test
 .flymake*
 docker.test
+auth/auth.test

+ 34 - 28
auth/auth.go

@@ -8,11 +8,12 @@ import (
 	"io/ioutil"
 	"net/http"
 	"os"
+	"path"
 	"strings"
 )
 
 // Where we store the config file
-const CONFIGFILE = "/var/lib/docker/.dockercfg"
+const CONFIGFILE = ".dockercfg"
 
 // the registry server we want to login against
 //const REGISTRY_SERVER = "https://registry.docker.io"
@@ -22,10 +23,11 @@ type AuthConfig struct {
 	Username string `json:"username"`
 	Password string `json:"password"`
 	Email    string `json:"email"`
+	rootPath string `json:-`
 }
 
 // create a base64 encoded auth string to store in config
-func EncodeAuth(authConfig AuthConfig) string {
+func EncodeAuth(authConfig *AuthConfig) string {
 	authStr := authConfig.Username + ":" + authConfig.Password
 	msg := []byte(authStr)
 	encoded := make([]byte, base64.StdEncoding.EncodedLen(len(msg)))
@@ -34,50 +36,54 @@ func EncodeAuth(authConfig AuthConfig) string {
 }
 
 // decode the auth string
-func DecodeAuth(authStr string) (AuthConfig, error) {
+func DecodeAuth(authStr string) (*AuthConfig, error) {
 	decLen := base64.StdEncoding.DecodedLen(len(authStr))
 	decoded := make([]byte, decLen)
 	authByte := []byte(authStr)
 	n, err := base64.StdEncoding.Decode(decoded, authByte)
 	if err != nil {
-		return AuthConfig{}, err
+		return nil, err
 	}
 	if n > decLen {
-		return AuthConfig{}, errors.New("something went wrong decoding auth config")
+		return nil, fmt.Errorf("Something went wrong decoding auth config")
 	}
 	arr := strings.Split(string(decoded), ":")
+	if len(arr) != 2 {
+		return nil, fmt.Errorf("Invalid auth configuration file")
+	}
 	password := strings.Trim(arr[1], "\x00")
-	return AuthConfig{Username: arr[0], Password: password}, nil
+	return &AuthConfig{Username: arr[0], Password: password}, nil
 
 }
 
 // load up the auth config information and return values
-func LoadConfig() (AuthConfig, error) {
-	if _, err := os.Stat(CONFIGFILE); err == nil {
-		b, err := ioutil.ReadFile(CONFIGFILE)
-		if err != nil {
-			return AuthConfig{}, err
-		}
-		arr := strings.Split(string(b), "\n")
-		orig_auth := strings.Split(arr[0], " = ")
-		orig_email := strings.Split(arr[1], " = ")
-		authConfig, err := DecodeAuth(orig_auth[1])
-		if err != nil {
-			return AuthConfig{}, err
-		}
-		authConfig.Email = orig_email[1]
-		return authConfig, nil
-	} else {
-		return AuthConfig{}, nil
+// FIXME: use the internal golang config parser
+func LoadConfig(rootPath string) (*AuthConfig, error) {
+	confFile := path.Join(rootPath, CONFIGFILE)
+	if _, err := os.Stat(confFile); err != nil {
+		return &AuthConfig{}, fmt.Errorf("The Auth config file is missing")
+	}
+	b, err := ioutil.ReadFile(confFile)
+	if err != nil {
+		return nil, err
+	}
+	arr := strings.Split(string(b), "\n")
+	orig_auth := strings.Split(arr[0], " = ")
+	orig_email := strings.Split(arr[1], " = ")
+	authConfig, err := DecodeAuth(orig_auth[1])
+	if err != nil {
+		return nil, err
 	}
-	return AuthConfig{}, nil
+	authConfig.Email = orig_email[1]
+	authConfig.rootPath = rootPath
+	return authConfig, nil
 }
 
 // save the auth config
-func saveConfig(authStr string, email string) error {
+func saveConfig(rootPath, authStr string, email string) error {
 	lines := "auth = " + authStr + "\n" + "email = " + email + "\n"
 	b := []byte(lines)
-	err := ioutil.WriteFile(CONFIGFILE, b, 0600)
+	err := ioutil.WriteFile(path.Join(rootPath, CONFIGFILE), b, 0600)
 	if err != nil {
 		return err
 	}
@@ -85,7 +91,7 @@ func saveConfig(authStr string, email string) error {
 }
 
 // try to register/login to the registry server
-func Login(authConfig AuthConfig) (string, error) {
+func Login(authConfig *AuthConfig) (string, error) {
 	storeConfig := false
 	reqStatusCode := 0
 	var status string
@@ -146,7 +152,7 @@ func Login(authConfig AuthConfig) (string, error) {
 	}
 	if storeConfig {
 		authStr := EncodeAuth(authConfig)
-		saveConfig(authStr, authConfig.Email)
+		saveConfig(authConfig.rootPath, authStr, authConfig.Email)
 	}
 	return status, nil
 }

+ 1 - 1
auth/auth_test.go

@@ -5,7 +5,7 @@ import (
 )
 
 func TestEncodeAuth(t *testing.T) {
-	newAuthConfig := AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
+	newAuthConfig := &AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
 	authStr := EncodeAuth(newAuthConfig)
 	decAuthConfig, err := DecodeAuth(authStr)
 	if err != nil {

+ 9 - 16
commands.go

@@ -69,17 +69,13 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout io.Writer, args ...strin
 	var username string
 	var password string
 	var email string
-	authConfig, err := auth.LoadConfig()
-	if err != nil {
-		fmt.Fprintf(stdout, "Error : %s\n", err)
-	}
 
-	fmt.Fprint(stdout, "Username (", authConfig.Username, "): ")
+	fmt.Fprint(stdout, "Username (", srv.runtime.authConfig.Username, "): ")
 	fmt.Fscanf(stdin, "%s", &username)
 	if username == "" {
-		username = authConfig.Username
+		username = srv.runtime.authConfig.Username
 	}
-	if username != authConfig.Username {
+	if username != srv.runtime.authConfig.Username {
 		fmt.Fprint(stdout, "Password: ")
 		fmt.Fscanf(stdin, "%s", &password)
 
@@ -87,16 +83,16 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout io.Writer, args ...strin
 			return errors.New("Error : Password Required\n")
 		}
 
-		fmt.Fprint(stdout, "Email (", authConfig.Email, "): ")
+		fmt.Fprint(stdout, "Email (", srv.runtime.authConfig.Email, "): ")
 		fmt.Fscanf(stdin, "%s", &email)
 		if email == "" {
-			email = authConfig.Email
+			email = srv.runtime.authConfig.Email
 		}
 	} else {
-		password = authConfig.Password
-		email = authConfig.Email
+		password = srv.runtime.authConfig.Password
+		email = srv.runtime.authConfig.Email
 	}
-	newAuthConfig := auth.AuthConfig{Username: username, Password: password, Email: email}
+	newAuthConfig := &auth.AuthConfig{Username: username, Password: password, Email: email}
 	status, err := auth.Login(newAuthConfig)
 	if err != nil {
 		fmt.Fprintf(stdout, "Error : %s\n", err)
@@ -473,7 +469,7 @@ func (srv *Server) CmdPull(stdin io.ReadCloser, stdout io.Writer, args ...string
 		return fmt.Errorf("Not loggin and no user specified\n")
 	}
 	// FIXME: Allow pull repo:tag
-	return srv.runtime.graph.PullRepository(*user, cmd.Arg(0), "", srv.runtime.repositories)
+	return srv.runtime.graph.PullRepository(*user, cmd.Arg(0), "", srv.runtime.repositories, srv.runtime.authConfig)
 }
 
 func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
@@ -867,9 +863,6 @@ func NewServer() (*Server, error) {
 	if runtime.GOARCH != "amd64" {
 		log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
 	}
-	// if err != nil {
-	// 	return nil, err
-	// }
 	runtime, err := NewRuntime()
 	if err != nil {
 		return nil, err

+ 2 - 6
registry.go

@@ -129,19 +129,15 @@ func (graph *Graph) PullImage(imgId string) error {
 }
 
 // FIXME: Handle the askedTag parameter
-func (graph *Graph) PullRepository(user, repoName, askedTag string, repositories *TagStore) error {
+func (graph *Graph) PullRepository(user, repoName, askedTag string, repositories *TagStore, authConfig *auth.AuthConfig) error {
 	client := &http.Client{}
 
 	req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/users/"+user+"/"+repoName, nil)
 	if err != nil {
 		return err
 	}
-	authStruct, err := auth.LoadConfig()
-	if err != nil {
-		return err
-	}
 
-	req.SetBasicAuth(authStruct.Username, authStruct.Password)
+	req.SetBasicAuth(authConfig.Username, authConfig.Password)
 	res, err := client.Do(req)
 	if err != nil {
 		return err

+ 8 - 0
runtime.go

@@ -3,6 +3,7 @@ package docker
 import (
 	"container/list"
 	"fmt"
+	"github.com/dotcloud/docker/auth"
 	"io"
 	"io/ioutil"
 	"log"
@@ -20,6 +21,7 @@ type Runtime struct {
 	networkManager *NetworkManager
 	graph          *Graph
 	repositories   *TagStore
+	authConfig     *auth.AuthConfig
 }
 
 var sysInitPath string
@@ -246,6 +248,11 @@ func NewRuntimeFromDirectory(root string) (*Runtime, error) {
 	if err != nil {
 		return nil, err
 	}
+	authConfig, err := auth.LoadConfig(root)
+	if err != nil && authConfig == nil {
+		// If the auth file does not exist, keep going
+		return nil, err
+	}
 
 	runtime := &Runtime{
 		root:           root,
@@ -254,6 +261,7 @@ func NewRuntimeFromDirectory(root string) (*Runtime, error) {
 		networkManager: netManager,
 		graph:          g,
 		repositories:   repositories,
+		authConfig:     authConfig,
 	}
 
 	if err := runtime.restore(); err != nil {