gitlab.com/jfprevost/gitlab-runner-notlscheck@v11.11.4+incompatible/helpers/docker/auth_config.go (about)

     1  package docker_helpers
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  	"os/user"
    11  	"path"
    12  	"strings"
    13  
    14  	"github.com/docker/cli/cli/config/configfile"
    15  	"github.com/docker/cli/cli/config/credentials"
    16  	"github.com/docker/docker/api/types"
    17  	"github.com/docker/docker/pkg/homedir"
    18  )
    19  
    20  // DefaultDockerRegistry is the name of the index
    21  const DefaultDockerRegistry = "docker.io"
    22  
    23  // EncodeAuthConfig constructs a token from an AuthConfig, suitable for
    24  // authorizing against the Docker API with.
    25  func EncodeAuthConfig(authConfig *types.AuthConfig) (string, error) {
    26  	var buf bytes.Buffer
    27  	if err := json.NewEncoder(&buf).Encode(authConfig); err != nil {
    28  		return "", err
    29  	}
    30  
    31  	return base64.URLEncoding.EncodeToString(buf.Bytes()), nil
    32  }
    33  
    34  // SplitDockerImageName breaks a reposName into an index name and remote name
    35  func SplitDockerImageName(reposName string) (string, string) {
    36  	nameParts := strings.SplitN(reposName, "/", 2)
    37  	var indexName, remoteName string
    38  	if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") &&
    39  		!strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") {
    40  		// This is a Docker Index repos (ex: samalba/hipache or ubuntu)
    41  		// 'docker.io'
    42  		indexName = DefaultDockerRegistry
    43  		remoteName = reposName
    44  	} else {
    45  		indexName = nameParts[0]
    46  		remoteName = nameParts[1]
    47  	}
    48  
    49  	if indexName == "index."+DefaultDockerRegistry {
    50  		indexName = DefaultDockerRegistry
    51  	}
    52  	return indexName, remoteName
    53  }
    54  
    55  var HomeDirectory = homedir.Get()
    56  
    57  func ReadDockerAuthConfigsFromHomeDir(userName string) (map[string]types.AuthConfig, error) {
    58  	homeDir := HomeDirectory
    59  
    60  	if userName != "" {
    61  		u, err := user.Lookup(userName)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		homeDir = u.HomeDir
    66  	}
    67  
    68  	if homeDir == "" {
    69  		return nil, fmt.Errorf("Failed to get home directory")
    70  	}
    71  
    72  	p := path.Join(homeDir, ".docker", "config.json")
    73  
    74  	r, err := os.Open(p)
    75  	defer r.Close()
    76  
    77  	if err != nil {
    78  		p := path.Join(homeDir, ".dockercfg")
    79  		r, err = os.Open(p)
    80  		if err != nil && !os.IsNotExist(err) {
    81  			return nil, err
    82  		}
    83  	}
    84  
    85  	if r == nil {
    86  		return make(map[string]types.AuthConfig), nil
    87  	}
    88  
    89  	return ReadAuthConfigsFromReader(r)
    90  }
    91  
    92  func ReadAuthConfigsFromReader(r io.Reader) (map[string]types.AuthConfig, error) {
    93  	config := &configfile.ConfigFile{}
    94  
    95  	if err := config.LoadFromReader(r); err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	auths := make(map[string]types.AuthConfig)
   100  	addAll(auths, config.AuthConfigs)
   101  
   102  	if config.CredentialsStore != "" {
   103  		authsFromCredentialsStore, err := readAuthConfigsFromCredentialsStore(config)
   104  		if err != nil {
   105  			return nil, err
   106  		}
   107  		addAll(auths, authsFromCredentialsStore)
   108  	}
   109  
   110  	return auths, nil
   111  }
   112  
   113  func readAuthConfigsFromCredentialsStore(config *configfile.ConfigFile) (map[string]types.AuthConfig, error) {
   114  	store := credentials.NewNativeStore(config, config.CredentialsStore)
   115  
   116  	newAuths, err := store.GetAll()
   117  
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	return newAuths, nil
   123  }
   124  
   125  func addAll(to, from map[string]types.AuthConfig) {
   126  	for reg, ac := range from {
   127  		to[reg] = ac
   128  	}
   129  }
   130  
   131  // ResolveDockerAuthConfig taken from: https://github.com/docker/docker/blob/master/registry/auth.go
   132  func ResolveDockerAuthConfig(indexName string, configs map[string]types.AuthConfig) *types.AuthConfig {
   133  	if configs == nil {
   134  		return nil
   135  	}
   136  
   137  	convertToHostname := func(url string) string {
   138  		stripped := url
   139  		if strings.HasPrefix(url, "http://") {
   140  			stripped = strings.Replace(url, "http://", "", 1)
   141  		} else if strings.HasPrefix(url, "https://") {
   142  			stripped = strings.Replace(url, "https://", "", 1)
   143  		}
   144  
   145  		nameParts := strings.SplitN(stripped, "/", 2)
   146  		if nameParts[0] == "index."+DefaultDockerRegistry {
   147  			return DefaultDockerRegistry
   148  		}
   149  		return nameParts[0]
   150  	}
   151  
   152  	// Maybe they have a legacy config file, we will iterate the keys converting
   153  	// them to the new format and testing
   154  	for registry, authConfig := range configs {
   155  		if indexName == convertToHostname(registry) {
   156  			return &authConfig
   157  		}
   158  	}
   159  
   160  	// When all else fails, return an empty auth config
   161  	return nil
   162  }