diff --git a/cmd/notary/repo_factory.go b/cmd/notary/repo_factory.go index 0a8702bb3..f53978338 100644 --- a/cmd/notary/repo_factory.go +++ b/cmd/notary/repo_factory.go @@ -18,7 +18,7 @@ type RepoFactory func(gun data.GUN) (client.Repository, error) // ConfigureRepo takes in the configuration parameters and returns a repoFactory that can // initialize new client.Repository objects with the correct upstreams and password // retrieval mechanisms. -func ConfigureRepo(v *viper.Viper, retriever notary.PassRetriever, onlineOperation bool) RepoFactory { +func ConfigureRepo(v *viper.Viper, retriever notary.PassRetriever, onlineOperation bool, permission httpAccess) RepoFactory { localRepo := func(gun data.GUN) (client.Repository, error) { var rt http.RoundTripper trustPin, err := getTrustPinning(v) @@ -26,7 +26,7 @@ func ConfigureRepo(v *viper.Viper, retriever notary.PassRetriever, onlineOperati return nil, err } if onlineOperation { - rt, err = getTransport(v, gun, admin) + rt, err = getTransport(v, gun, permission) if err != nil { return nil, err } diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index f9f133d9b..cc789f9d1 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -205,7 +205,7 @@ func (t *tufCommander) tufWitness(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) roles := data.NewRoleList(args[1:]) - fact := ConfigureRepo(config, t.retriever, false) + fact := ConfigureRepo(config, t.retriever, false, readOnly) nRepo, err := fact(gun) if err != nil { return err @@ -294,7 +294,7 @@ func (t *tufCommander) tufAddByHash(cmd *cobra.Command, args []string) error { // no online operations are performed by add so the transport argument // should be nil - fact := ConfigureRepo(config, t.retriever, false) + fact := ConfigureRepo(config, t.retriever, false, readWrite) nRepo, err := fact(gun) if err != nil { return err @@ -350,7 +350,7 @@ func (t *tufCommander) tufAdd(cmd *cobra.Command, args []string) error { // no online operations are performed by add so the transport argument // should be nil - fact := ConfigureRepo(config, t.retriever, false) + fact := ConfigureRepo(config, t.retriever, false, readWrite) nRepo, err := fact(gun) if err != nil { return err @@ -481,7 +481,7 @@ func (t *tufCommander) tufInit(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - fact := ConfigureRepo(config, t.retriever, true) + fact := ConfigureRepo(config, t.retriever, true, readWrite) nRepo, err := fact(gun) if err != nil { return err @@ -547,7 +547,7 @@ func (t *tufCommander) tufList(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - fact := ConfigureRepo(config, t.retriever, true) + fact := ConfigureRepo(config, t.retriever, true, readOnly) nRepo, err := fact(gun) if err != nil { return err @@ -576,7 +576,7 @@ func (t *tufCommander) tufLookup(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) targetName := args[1] - fact := ConfigureRepo(config, t.retriever, true) + fact := ConfigureRepo(config, t.retriever, true, readOnly) nRepo, err := fact(gun) if err != nil { return err @@ -603,7 +603,7 @@ func (t *tufCommander) tufStatus(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - fact := ConfigureRepo(config, t.retriever, false) + fact := ConfigureRepo(config, t.retriever, false, readOnly) nRepo, err := fact(gun) if err != nil { return err @@ -655,7 +655,7 @@ func (t *tufCommander) tufReset(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - fact := ConfigureRepo(config, t.retriever, false) + fact := ConfigureRepo(config, t.retriever, false, admin) nRepo, err := fact(gun) if err != nil { return err @@ -692,7 +692,7 @@ func (t *tufCommander) tufPublish(cmd *cobra.Command, args []string) error { cmd.Println("Pushing changes to", gun) - fact := ConfigureRepo(config, t.retriever, true) + fact := ConfigureRepo(config, t.retriever, true, readWrite) nRepo, err := fact(gun) if err != nil { return err @@ -713,7 +713,7 @@ func (t *tufCommander) tufRemove(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) targetName := args[1] - fact := ConfigureRepo(config, t.retriever, false) + fact := ConfigureRepo(config, t.retriever, false, admin) nRepo, err := fact(gun) if err != nil { return err @@ -748,7 +748,7 @@ func (t *tufCommander) tufVerify(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) targetName := args[1] - fact := ConfigureRepo(config, t.retriever, true) + fact := ConfigureRepo(config, t.retriever, true, readOnly) nRepo, err := fact(gun) if err != nil { return err diff --git a/cmd/notary/tuf_test.go b/cmd/notary/tuf_test.go index cfad1c86c..4534867ab 100644 --- a/cmd/notary/tuf_test.go +++ b/cmd/notary/tuf_test.go @@ -2,6 +2,7 @@ package main import ( "encoding/base64" + "fmt" "io/ioutil" "net/http" "net/http/httptest" @@ -199,6 +200,76 @@ func TestAdminTokenAuthNon200Non401Status(t *testing.T) { require.Nil(t, auth) } +func fakeAuthServerFactory(t *testing.T, expectedScope string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + require.Contains(t, r.URL.RawQuery, "scope="+url.QueryEscape(expectedScope)) + w.WriteHeader(200) + } +} + +func authChallengerFactory(URL string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Www-Authenticate", fmt.Sprintf(`Bearer realm="%s"`, URL)) + w.WriteHeader(401) + } +} +func TestConfigureRepo(t *testing.T) { + authserver := httptest.NewServer(http.HandlerFunc(fakeAuthServerFactory(t, "repository:yes:pull"))) + defer authserver.Close() + + s := httptest.NewServer(http.HandlerFunc(authChallengerFactory(authserver.URL))) + defer s.Close() + + tempBaseDir := tempDirWithConfig(t, "{}") + defer os.RemoveAll(tempBaseDir) + v := viper.New() + v.SetDefault("trust_dir", tempBaseDir) + v.Set("remote_server.url", s.URL) + + repo, err := ConfigureRepo(v, nil, true, readOnly)("yes") + require.NoError(t, err) + //perform an arbitrary action to trigger a call to the fake auth server + repo.ListRoles() +} + +func TestConfigureRepoRW(t *testing.T) { + authserver := httptest.NewServer(http.HandlerFunc(fakeAuthServerFactory(t, "repository:yes:push,pull"))) + defer authserver.Close() + + s := httptest.NewServer(http.HandlerFunc(authChallengerFactory(authserver.URL))) + defer s.Close() + + tempBaseDir := tempDirWithConfig(t, "{}") + defer os.RemoveAll(tempBaseDir) + v := viper.New() + v.SetDefault("trust_dir", tempBaseDir) + v.Set("remote_server.url", s.URL) + + repo, err := ConfigureRepo(v, nil, true, readWrite)("yes") + require.NoError(t, err) + //perform an arbitrary action to trigger a call to the fake auth server + repo.ListRoles() +} + +func TestConfigureRepoAdmin(t *testing.T) { + authserver := httptest.NewServer(http.HandlerFunc(fakeAuthServerFactory(t, "repository:yes:*"))) + defer authserver.Close() + + s := httptest.NewServer(http.HandlerFunc(authChallengerFactory(authserver.URL))) + defer s.Close() + + tempBaseDir := tempDirWithConfig(t, "{}") + defer os.RemoveAll(tempBaseDir) + v := viper.New() + v.SetDefault("trust_dir", tempBaseDir) + v.Set("remote_server.url", s.URL) + + repo, err := ConfigureRepo(v, nil, true, admin)("yes") + require.NoError(t, err) + //perform an arbitrary action to trigger a call to the fake auth server + repo.ListRoles() +} + func TestStatusUnstageAndReset(t *testing.T) { setUp(t) tempBaseDir := tempDirWithConfig(t, "{}")