|
|
@@ -2,7 +2,9 @@ package cmd
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
+ "encoding/base64"
|
|
|
"encoding/json"
|
|
|
+ "fmt"
|
|
|
"io/ioutil"
|
|
|
"net/url"
|
|
|
"os"
|
|
|
@@ -16,6 +18,7 @@ import (
|
|
|
"github.com/spf13/cobra"
|
|
|
|
|
|
"github.com/docker/cli/cli/config/configfile"
|
|
|
+ "github.com/docker/cli/cli/config/types"
|
|
|
)
|
|
|
|
|
|
var dockerCmd = &cobra.Command{
|
|
|
@@ -132,7 +135,49 @@ func dockerConfig(user *api.AuthCheckResponse, client *api.Client, args []string
|
|
|
}
|
|
|
|
|
|
for _, regURL := range regToAdd {
|
|
|
- config.CredentialHelpers[regURL] = "porter"
|
|
|
+ // if this is a dockerhub registry, see if an auth config has already been generated
|
|
|
+ // for index.docker.io
|
|
|
+ if strings.Contains(regURL, "index.docker.io") {
|
|
|
+ isAuthenticated := false
|
|
|
+
|
|
|
+ for key, _ := range config.AuthConfigs {
|
|
|
+ if key == "https://index.docker.io/v1/" {
|
|
|
+ isAuthenticated = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if !isAuthenticated {
|
|
|
+ // get a dockerhub token from the Porter API
|
|
|
+ tokenResp, err := client.GetDockerhubAuthorizationToken(context.Background(), getProjectID())
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ decodedToken, err := base64.StdEncoding.DecodeString(tokenResp.Token)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("Invalid token: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ parts := strings.SplitN(string(decodedToken), ":", 2)
|
|
|
+
|
|
|
+ if len(parts) < 2 {
|
|
|
+ return fmt.Errorf("Invalid token: expected two parts, got %d", len(parts))
|
|
|
+ }
|
|
|
+
|
|
|
+ config.AuthConfigs["https://index.docker.io/v1/"] = types.AuthConfig{
|
|
|
+ Auth: tokenResp.Token,
|
|
|
+ Username: parts[0],
|
|
|
+ Password: parts[1],
|
|
|
+ }
|
|
|
+
|
|
|
+ // since we're using token-based auth, unset the credstore
|
|
|
+ config.CredentialsStore = ""
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ config.CredentialHelpers[regURL] = "porter"
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return config.Save()
|