move auth to the client WIP
This commit is contained in:
parent
7ff2e6b797
commit
49e656839f
8 changed files with 55 additions and 168 deletions
50
api.go
50
api.go
|
@ -66,48 +66,15 @@ func getBoolParam(value string) (bool, error) {
|
|||
return false, fmt.Errorf("Bad parameter")
|
||||
}
|
||||
|
||||
func getAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
// FIXME: Handle multiple login at once
|
||||
// FIXME: return specific error code if config file missing?
|
||||
authConfig, err := auth.LoadConfig(srv.runtime.root)
|
||||
if err != nil {
|
||||
if err != auth.ErrConfigFileMissing {
|
||||
return err
|
||||
}
|
||||
authConfig = &auth.AuthConfig{}
|
||||
}
|
||||
b, err := json.Marshal(&auth.AuthConfig{Username: authConfig.Username, Email: authConfig.Email})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writeJson(w, b)
|
||||
return nil
|
||||
}
|
||||
|
||||
func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
// FIXME: Handle multiple login at once
|
||||
config := &auth.AuthConfig{}
|
||||
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
||||
authConfig := &auth.AuthConfig{}
|
||||
if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authConfig, err := auth.LoadConfig(srv.runtime.root)
|
||||
if err != nil {
|
||||
if err != auth.ErrConfigFileMissing {
|
||||
return err
|
||||
}
|
||||
authConfig = &auth.AuthConfig{}
|
||||
}
|
||||
if config.Username == authConfig.Username {
|
||||
config.Password = authConfig.Password
|
||||
}
|
||||
|
||||
newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root)
|
||||
status, err := auth.Login(newAuthConfig)
|
||||
status, err := auth.Login(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if status != "" {
|
||||
b, err := json.Marshal(&ApiAuth{Status: status})
|
||||
if err != nil {
|
||||
|
@ -317,7 +284,9 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht
|
|||
if version > 1.0 {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
}
|
||||
if err := srv.ImagePull(image, tag, registry, w, version > 1.0); err != nil {
|
||||
authConfig := &auth.AuthConfig{}
|
||||
json.NewDecoder(r.Body).Decode(authConfig)
|
||||
if err := srv.ImagePull(image, tag, registry, w, version > 1.0, authConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
} else { //import
|
||||
|
@ -371,6 +340,10 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht
|
|||
}
|
||||
|
||||
func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
authConfig := &auth.AuthConfig{}
|
||||
if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := parseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -381,7 +354,7 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http
|
|||
}
|
||||
name := vars["name"]
|
||||
|
||||
if err := srv.ImagePush(name, registry, w); err != nil {
|
||||
if err := srv.ImagePush(name, registry, w, authConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -676,7 +649,6 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
|
|||
|
||||
m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{
|
||||
"GET": {
|
||||
"/auth": getAuth,
|
||||
"/version": getVersion,
|
||||
"/info": getInfo,
|
||||
"/images/json": getImagesJson,
|
||||
|
|
43
api_test.go
43
api_test.go
|
@ -6,7 +6,6 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/dotcloud/docker/auth"
|
||||
"github.com/dotcloud/docker/registry"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -18,7 +17,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func TestGetAuth(t *testing.T) {
|
||||
func TestPostAuth(t *testing.T) {
|
||||
runtime, err := newTestRuntime()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -54,12 +53,6 @@ func TestGetAuth(t *testing.T) {
|
|||
if r.Code != http.StatusOK && r.Code != 0 {
|
||||
t.Fatalf("%d OK or 0 expected, received %d\n", http.StatusOK, r.Code)
|
||||
}
|
||||
|
||||
newAuthConfig := registry.NewRegistry(runtime.root).GetAuthConfig(false)
|
||||
if newAuthConfig.Username != authConfig.Username ||
|
||||
newAuthConfig.Email != authConfig.Email {
|
||||
t.Fatalf("The auth configuration hasn't been set correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetVersion(t *testing.T) {
|
||||
|
@ -494,40 +487,6 @@ func TestGetContainersByName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPostAuth(t *testing.T) {
|
||||
runtime, err := newTestRuntime()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer nuke(runtime)
|
||||
|
||||
srv := &Server{
|
||||
runtime: runtime,
|
||||
}
|
||||
|
||||
config := &auth.AuthConfig{
|
||||
Username: "utest",
|
||||
Email: "utest@yopmail.com",
|
||||
}
|
||||
|
||||
authStr := auth.EncodeAuth(config)
|
||||
auth.SaveConfig(runtime.root, authStr, config.Email)
|
||||
|
||||
r := httptest.NewRecorder()
|
||||
if err := getAuth(srv, API_VERSION, r, nil, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
authConfig := &auth.AuthConfig{}
|
||||
if err := json.Unmarshal(r.Body.Bytes(), authConfig); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if authConfig.Username != config.Username || authConfig.Email != config.Email {
|
||||
t.Errorf("The retrieve auth mismatch with the one set.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostCommit(t *testing.T) {
|
||||
runtime, err := newTestRuntime()
|
||||
if err != nil {
|
||||
|
|
28
auth/auth.go
28
auth/auth.go
|
@ -48,7 +48,7 @@ func IndexServerAddress() string {
|
|||
}
|
||||
|
||||
// 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)))
|
||||
|
@ -57,7 +57,7 @@ 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)
|
||||
|
@ -82,7 +82,7 @@ func DecodeAuth(authStr string) (*AuthConfig, error) {
|
|||
func LoadConfig(rootPath string) (*AuthConfig, error) {
|
||||
confFile := path.Join(rootPath, CONFIGFILE)
|
||||
if _, err := os.Stat(confFile); err != nil {
|
||||
return nil, ErrConfigFileMissing
|
||||
return &AuthConfig{rootPath:rootPath}, ErrConfigFileMissing
|
||||
}
|
||||
b, err := ioutil.ReadFile(confFile)
|
||||
if err != nil {
|
||||
|
@ -94,7 +94,7 @@ func LoadConfig(rootPath string) (*AuthConfig, error) {
|
|||
}
|
||||
origAuth := strings.Split(arr[0], " = ")
|
||||
origEmail := strings.Split(arr[1], " = ")
|
||||
authConfig, err := DecodeAuth(origAuth[1])
|
||||
authConfig, err := decodeAuth(origAuth[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -104,13 +104,13 @@ func LoadConfig(rootPath string) (*AuthConfig, error) {
|
|||
}
|
||||
|
||||
// save the auth config
|
||||
func SaveConfig(rootPath, authStr string, email string) error {
|
||||
confFile := path.Join(rootPath, CONFIGFILE)
|
||||
if len(email) == 0 {
|
||||
func SaveConfig(authConfig *AuthConfig) error {
|
||||
confFile := path.Join(authConfig.rootPath, CONFIGFILE)
|
||||
if len(authConfig.Email) == 0 {
|
||||
os.Remove(confFile)
|
||||
return nil
|
||||
}
|
||||
lines := "auth = " + authStr + "\n" + "email = " + email + "\n"
|
||||
lines := "auth = " + encodeAuth(authConfig) + "\n" + "email = " + authConfig.Email + "\n"
|
||||
b := []byte(lines)
|
||||
err := ioutil.WriteFile(confFile, b, 0600)
|
||||
if err != nil {
|
||||
|
@ -121,7 +121,6 @@ func SaveConfig(rootPath, authStr string, email string) error {
|
|||
|
||||
// try to register/login to the registry server
|
||||
func Login(authConfig *AuthConfig) (string, error) {
|
||||
storeConfig := false
|
||||
client := &http.Client{}
|
||||
reqStatusCode := 0
|
||||
var status string
|
||||
|
@ -147,7 +146,6 @@ func Login(authConfig *AuthConfig) (string, error) {
|
|||
if reqStatusCode == 201 {
|
||||
status = "Account created. Please use the confirmation link we sent" +
|
||||
" to your e-mail to activate it.\n"
|
||||
storeConfig = true
|
||||
} else if reqStatusCode == 403 {
|
||||
return "", fmt.Errorf("Login: Your account hasn't been activated. " +
|
||||
"Please check your e-mail for a confirmation link.")
|
||||
|
@ -166,11 +164,7 @@ func Login(authConfig *AuthConfig) (string, error) {
|
|||
}
|
||||
if resp.StatusCode == 200 {
|
||||
status = "Login Succeeded\n"
|
||||
storeConfig = true
|
||||
} else if resp.StatusCode == 401 {
|
||||
if err := SaveConfig(authConfig.rootPath, "", ""); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "", fmt.Errorf("Wrong login/password, please try again")
|
||||
} else {
|
||||
return "", fmt.Errorf("Login: %s (Code: %d; Headers: %s)", body,
|
||||
|
@ -182,11 +176,5 @@ func Login(authConfig *AuthConfig) (string, error) {
|
|||
} else {
|
||||
return "", fmt.Errorf("Unexpected status code [%d] : %s", reqStatusCode, reqBody)
|
||||
}
|
||||
if storeConfig {
|
||||
authStr := EncodeAuth(authConfig)
|
||||
if err := SaveConfig(authConfig.rootPath, authStr, authConfig.Email); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ func (b *buildFile) CmdFrom(name string) error {
|
|||
remote = name
|
||||
}
|
||||
|
||||
if err := b.srv.ImagePull(remote, tag, "", b.out, false); err != nil {
|
||||
if err := b.srv.ImagePull(remote, tag, "", b.out, false, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
83
commands.go
83
commands.go
|
@ -279,27 +279,16 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
body, _, err := cli.call("GET", "/auth", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var out auth.AuthConfig
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var username string
|
||||
var password string
|
||||
var email string
|
||||
|
||||
fmt.Print("Username (", out.Username, "): ")
|
||||
fmt.Print("Username (", cli.authConfig.Username, "): ")
|
||||
username = readAndEchoString(os.Stdin, os.Stdout)
|
||||
if username == "" {
|
||||
username = out.Username
|
||||
username = cli.authConfig.Username
|
||||
}
|
||||
if username != out.Username {
|
||||
if username != cli.authConfig.Username {
|
||||
fmt.Print("Password: ")
|
||||
password = readString(os.Stdin, os.Stdout)
|
||||
|
||||
|
@ -307,20 +296,21 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
|
|||
return fmt.Errorf("Error : Password Required")
|
||||
}
|
||||
|
||||
fmt.Print("Email (", out.Email, "): ")
|
||||
fmt.Print("Email (", cli.authConfig.Email, "): ")
|
||||
email = readAndEchoString(os.Stdin, os.Stdout)
|
||||
if email == "" {
|
||||
email = out.Email
|
||||
email = cli.authConfig.Email
|
||||
}
|
||||
} else {
|
||||
email = out.Email
|
||||
email = cli.authConfig.Email
|
||||
}
|
||||
term.RestoreTerminal(oldState)
|
||||
|
||||
out.Username = username
|
||||
out.Password = password
|
||||
out.Email = email
|
||||
cli.authConfig.Username = username
|
||||
cli.authConfig.Password = password
|
||||
cli.authConfig.Email = email
|
||||
|
||||
body, _, err = cli.call("POST", "/auth", out)
|
||||
body, _, err := cli.call("POST", "/auth", cli.authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -328,10 +318,11 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
|
|||
var out2 ApiAuth
|
||||
err = json.Unmarshal(body, &out2)
|
||||
if err != nil {
|
||||
auth.LoadConfig(os.Getenv("HOME"))
|
||||
return err
|
||||
}
|
||||
auth.SaveConfig(cli.authConfig)
|
||||
if out2.Status != "" {
|
||||
term.RestoreTerminal(oldState)
|
||||
fmt.Print(out2.Status)
|
||||
}
|
||||
return nil
|
||||
|
@ -688,13 +679,12 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
username, err := cli.checkIfLogged(*registry == "", "push")
|
||||
if err != nil {
|
||||
if err := cli.checkIfLogged(*registry == "", "push"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(strings.SplitN(name, "/", 2)) == 1 {
|
||||
return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)", username, name)
|
||||
return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)", cli.authConfig.Username, name)
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
|
@ -726,7 +716,7 @@ func (cli *DockerCli) CmdPull(args ...string) error {
|
|||
}
|
||||
|
||||
if strings.Contains(remote, "/") {
|
||||
if _, err := cli.checkIfLogged(true, "pull"); err != nil {
|
||||
if err := cli.checkIfLogged(true, "pull"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -1220,38 +1210,17 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cli *DockerCli) checkIfLogged(condition bool, action string) (string, error) {
|
||||
body, _, err := cli.call("GET", "/auth", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var out auth.AuthConfig
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
func (cli *DockerCli) checkIfLogged(condition bool, action string) error {
|
||||
// If condition AND the login failed
|
||||
if condition && out.Username == "" {
|
||||
if condition && cli.authConfig.Username == "" {
|
||||
if err := cli.CmdLogin(""); err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
body, _, err = cli.call("GET", "/auth", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if out.Username == "" {
|
||||
return "", fmt.Errorf("Please login prior to %s. ('docker login')", action)
|
||||
if cli.authConfig.Username == "" {
|
||||
return fmt.Errorf("Please login prior to %s. ('docker login')", action)
|
||||
}
|
||||
}
|
||||
return out.Username, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int, error) {
|
||||
|
@ -1435,10 +1404,12 @@ func Subcmd(name, signature, description string) *flag.FlagSet {
|
|||
}
|
||||
|
||||
func NewDockerCli(addr string, port int) *DockerCli {
|
||||
return &DockerCli{addr, port}
|
||||
authConfig, _ := auth.LoadConfig(os.Getenv("HOME"))
|
||||
return &DockerCli{addr, port, authConfig}
|
||||
}
|
||||
|
||||
type DockerCli struct {
|
||||
host string
|
||||
port int
|
||||
host string
|
||||
port int
|
||||
authConfig *auth.AuthConfig
|
||||
}
|
||||
|
|
|
@ -466,10 +466,7 @@ type Registry struct {
|
|||
authConfig *auth.AuthConfig
|
||||
}
|
||||
|
||||
func NewRegistry(root string) *Registry {
|
||||
// If the auth file does not exist, keep going
|
||||
authConfig, _ := auth.LoadConfig(root)
|
||||
|
||||
func NewRegistry(root string, authConfig *auth.AuthConfig) *Registry {
|
||||
r := &Registry{
|
||||
authConfig: authConfig,
|
||||
client: &http.Client{},
|
||||
|
|
|
@ -65,7 +65,7 @@ func init() {
|
|||
runtime: runtime,
|
||||
}
|
||||
// Retrieve the Image
|
||||
if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout, false); err != nil {
|
||||
if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout, false, nil); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
10
server.go
10
server.go
|
@ -50,7 +50,7 @@ func (srv *Server) ContainerExport(name string, out io.Writer) error {
|
|||
|
||||
func (srv *Server) ImagesSearch(term string) ([]ApiSearch, error) {
|
||||
|
||||
results, err := registry.NewRegistry(srv.runtime.root).SearchRepositories(term)
|
||||
results, err := registry.NewRegistry(srv.runtime.root, nil).SearchRepositories(term)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -394,8 +394,8 @@ func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, remote, a
|
|||
return nil
|
||||
}
|
||||
|
||||
func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, json bool) error {
|
||||
r := registry.NewRegistry(srv.runtime.root)
|
||||
func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, json bool, authConfig *auth.AuthConfig) error {
|
||||
r := registry.NewRegistry(srv.runtime.root, authConfig)
|
||||
out = utils.NewWriteFlusher(out)
|
||||
if endpoint != "" {
|
||||
if err := srv.pullImage(r, out, name, endpoint, nil, json); err != nil {
|
||||
|
@ -576,10 +576,10 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (srv *Server) ImagePush(name, endpoint string, out io.Writer) error {
|
||||
func (srv *Server) ImagePush(name, endpoint string, out io.Writer, authConfig *auth.AuthConfig) error {
|
||||
out = utils.NewWriteFlusher(out)
|
||||
img, err := srv.runtime.graph.Get(name)
|
||||
r := registry.NewRegistry(srv.runtime.root)
|
||||
r := registry.NewRegistry(srv.runtime.root, authConfig)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, "The push refers to a repository [%s] (len: %d)\n", name, len(srv.runtime.repositories.Repositories[name]))
|
||||
|
|
Loading…
Add table
Reference in a new issue