diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 3cc96428db..b55c021f2a 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -5,12 +5,17 @@ import ( "crypto/tls" "fmt" "io/ioutil" + "net" "net/http" + "net/url" "os" + "time" "crypto/subtle" "github.com/Sirupsen/logrus" + "github.com/docker/distribution/registry/client/auth" + "github.com/docker/distribution/registry/client/transport" notaryclient "github.com/docker/notary/client" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -77,7 +82,7 @@ func tufAdd(cmd *cobra.Command, args []string) { parseConfig() - nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(), retriever) + nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(gun), retriever) if err != nil { fatalf(err.Error()) } @@ -102,7 +107,7 @@ func tufInit(cmd *cobra.Command, args []string) { gun := args[0] parseConfig() - nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(), retriever) + nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(gun), retriever) if err != nil { fatalf(err.Error()) } @@ -144,7 +149,7 @@ func tufList(cmd *cobra.Command, args []string) { gun := args[0] parseConfig() - nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(), retriever) + nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(gun), retriever) if err != nil { fatalf(err.Error()) } @@ -170,7 +175,7 @@ func tufLookup(cmd *cobra.Command, args []string) { targetName := args[1] parseConfig() - nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(), retriever) + nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(gun), retriever) if err != nil { fatalf(err.Error()) } @@ -194,7 +199,7 @@ func tufPublish(cmd *cobra.Command, args []string) { fmt.Println("Pushing changes to ", gun, ".") - nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(), retriever) + nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(gun), retriever) if err != nil { fatalf(err.Error()) } @@ -215,7 +220,7 @@ func tufRemove(cmd *cobra.Command, args []string) { parseConfig() repo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, - getTransport(), retriever) + getTransport(gun), retriever) if err != nil { fatalf(err.Error()) } @@ -242,7 +247,7 @@ func verify(cmd *cobra.Command, args []string) { gun := args[0] targetName := args[1] - nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(), retriever) + nRepo, err := notaryclient.NewNotaryRepository(trustDir, gun, remoteTrustServer, getTransport(gun), retriever) if err != nil { fatalf(err.Error()) } @@ -266,13 +271,56 @@ func verify(cmd *cobra.Command, args []string) { return } -func getTransport() *http.Transport { - if viper.GetBool("skipTLSVerify") { - return &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - }, - } - } - return &http.Transport{} +type passwordStore struct { +} + +func (ps passwordStore) Basic(u *url.URL) (string, string) { + // TODO(dmcgowan): Prompt user and cache + return "", "" +} + +func getTransport(gun string) http.RoundTripper { + tlsConfig := &tls.Config{ + InsecureSkipVerify: viper.GetBool("skipTLSVerify"), + } + + base := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: tlsConfig, + DisableKeepAlives: true, + } + + // TODO(dmcgowan): add notary specific headers + authTransport := transport.NewTransport(base) + pingClient := &http.Client{ + Transport: authTransport, + Timeout: 5 * time.Second, + } + endpointStr := "https://notary.docker.io/v2/" + req, err := http.NewRequest("GET", endpointStr, nil) + if err != nil { + fatalf(err.Error()) + } + resp, err := pingClient.Do(req) + if err != nil { + fatalf(err.Error()) + } + defer resp.Body.Close() + + challengeManager := auth.NewSimpleChallengeManager() + if err := challengeManager.AddResponse(resp); err != nil { + fatalf(err.Error()) + } + + ps := passwordStore{} + tokenHandler := auth.NewTokenHandler(authTransport, ps, gun, "push", "pull") + basicHandler := auth.NewBasicHandler(ps) + modifier := transport.RequestModifier(auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler)) + return transport.NewTransport(base, modifier) }