From eba415e20c28d0e9968802bcfba30673109b9f52 Mon Sep 17 00:00:00 2001 From: Riyaz Faizullabhoy Date: Wed, 13 Jul 2016 17:38:14 -0700 Subject: [PATCH] Introduce enum for access Signed-off-by: Riyaz Faizullabhoy --- cmd/notary/delegations.go | 2 +- cmd/notary/keys.go | 2 +- cmd/notary/tuf.go | 65 ++++++++++++++++----------------------- cmd/notary/tuf_test.go | 24 +++++---------- 4 files changed, 37 insertions(+), 56 deletions(-) diff --git a/cmd/notary/delegations.go b/cmd/notary/delegations.go index a1ebcd8bb6..6a83db5cde 100644 --- a/cmd/notary/delegations.go +++ b/cmd/notary/delegations.go @@ -79,7 +79,7 @@ func (d *delegationCommander) delegationsList(cmd *cobra.Command, args []string) gun := args[0] - rt, err := getTransport(config, gun, true) + rt, err := getTransport(config, gun, readOnly) if err != nil { return err } diff --git a/cmd/notary/keys.go b/cmd/notary/keys.go index a733360fe7..d98bbc0e02 100644 --- a/cmd/notary/keys.go +++ b/cmd/notary/keys.go @@ -413,7 +413,7 @@ func (k *keyCommander) keysRotate(cmd *cobra.Command, args []string) error { gun := args[0] rotateKeyRole := args[1] - rt, err := getTransport(config, gun, false) + rt, err := getTransport(config, gun, readWrite) if err != nil { return err } diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 806c4e5399..e7e292f9dd 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -252,7 +252,7 @@ func (t *tufCommander) tufInit(cmd *cobra.Command, args []string) error { } gun := args[0] - rt, err := getTransport(config, gun, false) + rt, err := getTransport(config, gun, readWrite) if err != nil { return err } @@ -302,7 +302,7 @@ func (t *tufCommander) tufList(cmd *cobra.Command, args []string) error { } gun := args[0] - rt, err := getTransport(config, gun, true) + rt, err := getTransport(config, gun, readOnly) if err != nil { return err } @@ -342,7 +342,7 @@ func (t *tufCommander) tufLookup(cmd *cobra.Command, args []string) error { gun := args[0] targetName := args[1] - rt, err := getTransport(config, gun, true) + rt, err := getTransport(config, gun, readOnly) if err != nil { return err } @@ -423,7 +423,7 @@ func (t *tufCommander) tufPublish(cmd *cobra.Command, args []string) error { cmd.Println("Pushing changes to", gun) - rt, err := getTransport(config, gun, false) + rt, err := getTransport(config, gun, readWrite) if err != nil { return err } @@ -497,7 +497,7 @@ func (t *tufCommander) tufVerify(cmd *cobra.Command, args []string) error { gun := args[0] targetName := args[1] - rt, err := getTransport(config, gun, true) + rt, err := getTransport(config, gun, readOnly) if err != nil { return err } @@ -568,37 +568,21 @@ func (ps passwordStore) Basic(u *url.URL) (string, string) { return username, password } -// getTransport returns a non-admin http.RoundTripper to be used for all http requests. +type httpAccess int + +const ( + readOnly httpAccess = iota + readWrite + admin +) + // It correctly handles the auth challenge/credentials required to interact // with a notary server over both HTTP Basic Auth and the JWT auth implemented // in the notary-server // The readOnly flag indicates if the operation should be performed as an // anonymous read only operation. If the command entered requires write // permissions on the server, readOnly must be false -// This RoundTripper cannot perform admin requests, such as deleting repos -func getTransport(config *viper.Viper, gun string, readOnly bool) (http.RoundTripper, error) { - trustServerURL := getRemoteTrustServer(config) - base, err := getBaseTransport(config) - if err != nil { - return nil, err - } - return tokenAuth(trustServerURL, base, gun, readOnly, false) -} - -// getAdminTransport returns an admin http.RoundTripper to be used for all http requests, -// and can be used for deleting repos -func getAdminTransport(config *viper.Viper, gun string) (http.RoundTripper, error) { - trustServerURL := getRemoteTrustServer(config) - base, err := getBaseTransport(config) - if err != nil { - return nil, err - } - return tokenAuth(trustServerURL, base, gun, false, true) -} - -// getBaseTransport parses the config for TLS and server options to be used and bundles them in a -// http.Transport. This does not include logic for handling auth credentials -func getBaseTransport(config *viper.Viper) (*http.Transport, error) { +func getTransport(config *viper.Viper, gun string, permission httpAccess) (http.RoundTripper, error) { // Attempt to get a root CA from the config file. Nil is the host defaults. rootCAFile := utils.GetPathRelativeToConfig(config, "remote_server.root_ca") clientCert := utils.GetPathRelativeToConfig(config, "remote_server.tls_client_cert") @@ -634,11 +618,12 @@ func getBaseTransport(config *viper.Viper) (*http.Transport, error) { TLSClientConfig: tlsConfig, DisableKeepAlives: true, } - return base, nil + trustServerURL := getRemoteTrustServer(config) + return tokenAuth(trustServerURL, base, gun, permission) } func tokenAuth(trustServerURL string, baseTransport *http.Transport, gun string, - readOnly, adminAccess bool) (http.RoundTripper, error) { + permission httpAccess) (http.RoundTripper, error) { // TODO(dmcgowan): add notary specific headers authTransport := transport.NewTransport(baseTransport) @@ -685,22 +670,26 @@ func tokenAuth(trustServerURL string, baseTransport *http.Transport, gun string, return nil, err } - ps := passwordStore{anonymous: readOnly} + ps := passwordStore{anonymous: permission == readOnly} var actions []string - if adminAccess { + switch permission { + case admin: actions = []string{"*"} - } else if readOnly { - actions = []string{"pull"} - } else { + case readWrite: actions = []string{"push", "pull"} + case readOnly: + actions = []string{"pull"} + default: + return nil, fmt.Errorf("Invalid permission requested for token authentication of gun %s", gun) } + tokenHandler := auth.NewTokenHandler(authTransport, ps, gun, actions...) basicHandler := auth.NewBasicHandler(ps) modifier := auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler) - if adminAccess || !readOnly { + if permission != readOnly { return newAuthRoundTripper(transport.NewTransport(baseTransport, modifier)), nil } diff --git a/cmd/notary/tuf_test.go b/cmd/notary/tuf_test.go index 4b3b277ad2..be2d5647ff 100644 --- a/cmd/notary/tuf_test.go +++ b/cmd/notary/tuf_test.go @@ -10,22 +10,20 @@ import ( func TestTokenAuth(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) - auth, err := tokenAuth("https://localhost:9999", baseTransport, gun, readOnly, false) + auth, err := tokenAuth("https://localhost:9999", baseTransport, gun, readOnly) require.NoError(t, err) require.Nil(t, auth) } func TestAdminTokenAuth(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) - auth, err := tokenAuth("https://localhost:9999", baseTransport, gun, readOnly, true) + auth, err := tokenAuth("https://localhost:9999", baseTransport, gun, admin) require.NoError(t, err) require.Nil(t, auth) } @@ -37,28 +35,26 @@ func StatusOKTestHandler(w http.ResponseWriter, r *http.Request) { func TestTokenAuth200Status(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) s := httptest.NewServer(http.HandlerFunc(NotAuthorizedTestHandler)) defer s.Close() - auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly, false) + auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly) require.NoError(t, err) require.NotNil(t, auth) } func TestAdminTokenAuth200Status(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) s := httptest.NewServer(http.HandlerFunc(NotAuthorizedTestHandler)) defer s.Close() - auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly, true) + auth, err := tokenAuth(s.URL, baseTransport, gun, admin) require.NoError(t, err) require.NotNil(t, auth) } @@ -69,28 +65,26 @@ func NotAuthorizedTestHandler(w http.ResponseWriter, r *http.Request) { func TestTokenAuth401Status(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) s := httptest.NewServer(http.HandlerFunc(NotAuthorizedTestHandler)) defer s.Close() - auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly, false) + auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly) require.NoError(t, err) require.NotNil(t, auth) } func TestAdminTokenAuth401Status(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) s := httptest.NewServer(http.HandlerFunc(NotAuthorizedTestHandler)) defer s.Close() - auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly, true) + auth, err := tokenAuth(s.URL, baseTransport, gun, admin) require.NoError(t, err) require.NotNil(t, auth) } @@ -101,28 +95,26 @@ func NotFoundTestHandler(w http.ResponseWriter, r *http.Request) { func TestTokenAuthNon200Non401Status(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) s := httptest.NewServer(http.HandlerFunc(NotFoundTestHandler)) defer s.Close() - auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly, false) + auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly) require.NoError(t, err) require.Nil(t, auth) } func TestAdminTokenAuthNon200Non401Status(t *testing.T) { var ( - readOnly bool baseTransport = &http.Transport{} gun = "test" ) s := httptest.NewServer(http.HandlerFunc(NotFoundTestHandler)) defer s.Close() - auth, err := tokenAuth(s.URL, baseTransport, gun, readOnly, true) + auth, err := tokenAuth(s.URL, baseTransport, gun, admin) require.NoError(t, err) require.Nil(t, auth) }