|
@@ -3,7 +3,6 @@ package cliconfig
|
|
import (
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"encoding/json"
|
|
- "errors"
|
|
|
|
"fmt"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
"os"
|
|
"os"
|
|
@@ -15,19 +14,18 @@ import (
|
|
)
|
|
)
|
|
|
|
|
|
const (
|
|
const (
|
|
- // Where we store the config file
|
|
|
|
- CONFIGFILE = "config.json"
|
|
|
|
- OLD_CONFIGFILE = ".dockercfg"
|
|
|
|
|
|
+ // ConfigFile is the name of config file
|
|
|
|
+ ConfigFileName = "config.json"
|
|
|
|
+ oldConfigfile = ".dockercfg"
|
|
|
|
|
|
// This constant is only used for really old config files when the
|
|
// This constant is only used for really old config files when the
|
|
// URL wasn't saved as part of the config file and it was just
|
|
// URL wasn't saved as part of the config file and it was just
|
|
// assumed to be this value.
|
|
// assumed to be this value.
|
|
- DEFAULT_INDEXSERVER = "https://index.docker.io/v1/"
|
|
|
|
|
|
+ defaultIndexserver = "https://index.docker.io/v1/"
|
|
)
|
|
)
|
|
|
|
|
|
var (
|
|
var (
|
|
- configDir = os.Getenv("DOCKER_CONFIG")
|
|
|
|
- ErrConfigFileMissing = errors.New("The Auth config file is missing")
|
|
|
|
|
|
+ configDir = os.Getenv("DOCKER_CONFIG")
|
|
)
|
|
)
|
|
|
|
|
|
func init() {
|
|
func init() {
|
|
@@ -36,15 +34,17 @@ func init() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// ConfigDir returns the directory the configuration file is stored in
|
|
func ConfigDir() string {
|
|
func ConfigDir() string {
|
|
return configDir
|
|
return configDir
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// SetConfigDir sets the directory the configuration file is stored in
|
|
func SetConfigDir(dir string) {
|
|
func SetConfigDir(dir string) {
|
|
configDir = dir
|
|
configDir = dir
|
|
}
|
|
}
|
|
|
|
|
|
-// Registry Auth Info
|
|
|
|
|
|
+// AuthConfig contains authorization information for connecting to a Registry
|
|
type AuthConfig struct {
|
|
type AuthConfig struct {
|
|
Username string `json:"username,omitempty"`
|
|
Username string `json:"username,omitempty"`
|
|
Password string `json:"password,omitempty"`
|
|
Password string `json:"password,omitempty"`
|
|
@@ -53,22 +53,24 @@ type AuthConfig struct {
|
|
ServerAddress string `json:"serveraddress,omitempty"`
|
|
ServerAddress string `json:"serveraddress,omitempty"`
|
|
}
|
|
}
|
|
|
|
|
|
-// ~/.docker/config.json file info
|
|
|
|
|
|
+// ConfigFile ~/.docker/config.json file info
|
|
type ConfigFile struct {
|
|
type ConfigFile struct {
|
|
AuthConfigs map[string]AuthConfig `json:"auths"`
|
|
AuthConfigs map[string]AuthConfig `json:"auths"`
|
|
- HttpHeaders map[string]string `json:"HttpHeaders,omitempty"`
|
|
|
|
|
|
+ HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"`
|
|
filename string // Note: not serialized - for internal use only
|
|
filename string // Note: not serialized - for internal use only
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// NewConfigFile initilizes an empty configuration file for the given filename 'fn'
|
|
func NewConfigFile(fn string) *ConfigFile {
|
|
func NewConfigFile(fn string) *ConfigFile {
|
|
return &ConfigFile{
|
|
return &ConfigFile{
|
|
AuthConfigs: make(map[string]AuthConfig),
|
|
AuthConfigs: make(map[string]AuthConfig),
|
|
- HttpHeaders: make(map[string]string),
|
|
|
|
|
|
+ HTTPHeaders: make(map[string]string),
|
|
filename: fn,
|
|
filename: fn,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-// load up the auth config information and return values
|
|
|
|
|
|
+// Load reads the configuration files in the given directory, and sets up
|
|
|
|
+// the auth config information and return values.
|
|
// FIXME: use the internal golang config parser
|
|
// FIXME: use the internal golang config parser
|
|
func Load(configDir string) (*ConfigFile, error) {
|
|
func Load(configDir string) (*ConfigFile, error) {
|
|
if configDir == "" {
|
|
if configDir == "" {
|
|
@@ -77,7 +79,7 @@ func Load(configDir string) (*ConfigFile, error) {
|
|
|
|
|
|
configFile := ConfigFile{
|
|
configFile := ConfigFile{
|
|
AuthConfigs: make(map[string]AuthConfig),
|
|
AuthConfigs: make(map[string]AuthConfig),
|
|
- filename: filepath.Join(configDir, CONFIGFILE),
|
|
|
|
|
|
+ filename: filepath.Join(configDir, ConfigFileName),
|
|
}
|
|
}
|
|
|
|
|
|
// Try happy path first - latest config file
|
|
// Try happy path first - latest config file
|
|
@@ -110,8 +112,7 @@ func Load(configDir string) (*ConfigFile, error) {
|
|
}
|
|
}
|
|
|
|
|
|
// Can't find latest config file so check for the old one
|
|
// Can't find latest config file so check for the old one
|
|
- confFile := filepath.Join(homedir.Get(), OLD_CONFIGFILE)
|
|
|
|
-
|
|
|
|
|
|
+ confFile := filepath.Join(homedir.Get(), oldConfigfile)
|
|
if _, err := os.Stat(confFile); err != nil {
|
|
if _, err := os.Stat(confFile); err != nil {
|
|
return &configFile, nil //missing file is not an error
|
|
return &configFile, nil //missing file is not an error
|
|
}
|
|
}
|
|
@@ -140,8 +141,8 @@ func Load(configDir string) (*ConfigFile, error) {
|
|
return &configFile, fmt.Errorf("Invalid Auth config file")
|
|
return &configFile, fmt.Errorf("Invalid Auth config file")
|
|
}
|
|
}
|
|
authConfig.Email = origEmail[1]
|
|
authConfig.Email = origEmail[1]
|
|
- authConfig.ServerAddress = DEFAULT_INDEXSERVER
|
|
|
|
- configFile.AuthConfigs[DEFAULT_INDEXSERVER] = authConfig
|
|
|
|
|
|
+ authConfig.ServerAddress = defaultIndexserver
|
|
|
|
+ configFile.AuthConfigs[defaultIndexserver] = authConfig
|
|
} else {
|
|
} else {
|
|
for k, authConfig := range configFile.AuthConfigs {
|
|
for k, authConfig := range configFile.AuthConfigs {
|
|
authConfig.Username, authConfig.Password, err = DecodeAuth(authConfig.Auth)
|
|
authConfig.Username, authConfig.Password, err = DecodeAuth(authConfig.Auth)
|
|
@@ -156,12 +157,13 @@ func Load(configDir string) (*ConfigFile, error) {
|
|
return &configFile, nil
|
|
return &configFile, nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Save encodes and writes out all the authorization information
|
|
func (configFile *ConfigFile) Save() error {
|
|
func (configFile *ConfigFile) Save() error {
|
|
// Encode sensitive data into a new/temp struct
|
|
// Encode sensitive data into a new/temp struct
|
|
tmpAuthConfigs := make(map[string]AuthConfig, len(configFile.AuthConfigs))
|
|
tmpAuthConfigs := make(map[string]AuthConfig, len(configFile.AuthConfigs))
|
|
for k, authConfig := range configFile.AuthConfigs {
|
|
for k, authConfig := range configFile.AuthConfigs {
|
|
authCopy := authConfig
|
|
authCopy := authConfig
|
|
-
|
|
|
|
|
|
+ // encode and save the authstring, while blanking out the original fields
|
|
authCopy.Auth = EncodeAuth(&authCopy)
|
|
authCopy.Auth = EncodeAuth(&authCopy)
|
|
authCopy.Username = ""
|
|
authCopy.Username = ""
|
|
authCopy.Password = ""
|
|
authCopy.Password = ""
|
|
@@ -189,11 +191,12 @@ func (configFile *ConfigFile) Save() error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (config *ConfigFile) Filename() string {
|
|
|
|
- return config.filename
|
|
|
|
|
|
+// Filename returns the name of the configuration file
|
|
|
|
+func (configFile *ConfigFile) Filename() string {
|
|
|
|
+ return configFile.filename
|
|
}
|
|
}
|
|
|
|
|
|
-// create a base64 encoded auth string to store in config
|
|
|
|
|
|
+// EncodeAuth creates a base64 encoded string to containing authorization information
|
|
func EncodeAuth(authConfig *AuthConfig) string {
|
|
func EncodeAuth(authConfig *AuthConfig) string {
|
|
authStr := authConfig.Username + ":" + authConfig.Password
|
|
authStr := authConfig.Username + ":" + authConfig.Password
|
|
msg := []byte(authStr)
|
|
msg := []byte(authStr)
|
|
@@ -202,7 +205,7 @@ func EncodeAuth(authConfig *AuthConfig) string {
|
|
return string(encoded)
|
|
return string(encoded)
|
|
}
|
|
}
|
|
|
|
|
|
-// decode the auth string
|
|
|
|
|
|
+// DecodeAuth decodes a base64 encoded string and returns username and password
|
|
func DecodeAuth(authStr string) (string, string, error) {
|
|
func DecodeAuth(authStr string) (string, string, error) {
|
|
decLen := base64.StdEncoding.DecodedLen(len(authStr))
|
|
decLen := base64.StdEncoding.DecodedLen(len(authStr))
|
|
decoded := make([]byte, decLen)
|
|
decoded := make([]byte, decLen)
|