From f7ca3ef62ee74a8224e3d584bedea3ac2f3e7980 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 29 Jul 2015 12:03:20 -0700 Subject: [PATCH] make key algorithm configurable for local development with in memory ed25519 crypto service Signed-off-by: David Lawrence (github: endophage) --- .gitignore | 2 ++ client/client_test.go | 6 ++++++ cmd/notary-server/config.json | 9 ++++++++- cmd/notary-server/dev-config.json | 3 ++- cmd/notary-server/main.go | 31 ++++++++++++++++++++++++------- errors/errors.go | 19 +++++++++---------- server/handlers/default.go | 13 ++++++++++--- server/server.go | 4 +--- 8 files changed, 62 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index f5a0193ff9..c88be6800b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /cmd/notary-server/notary-server +/cmd/notary-server/local.config.json +/cmd/notary-signer/local.config.json cover bin cross diff --git a/client/client_test.go b/client/client_test.go index dea0ba7db2..f6ed1523ec 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -456,6 +456,12 @@ func testPublish(t *testing.T, rootType data.KeyAlgorithm) { // Set up server ctx := context.WithValue(context.Background(), "metaStore", storage.NewMemStorage()) + + // Do not pass one of the const KeyAlgorithms here as the value! Passing a + // string is in itself good test that we are handling it correctly as we will + // be receiving a string from the configuration. + ctx = context.WithValue(ctx, "keyAlgorithm", "ecdsa") + hand := utils.RootHandlerFactory(nil, ctx, cryptoservice.NewCryptoService("", trustmanager.NewKeyMemoryStore(passphraseRetriever))) diff --git a/cmd/notary-server/config.json b/cmd/notary-server/config.json index 9c41206a35..98ebd6f9de 100644 --- a/cmd/notary-server/config.json +++ b/cmd/notary-server/config.json @@ -6,12 +6,19 @@ "type": "remote", "hostname": "notarysigner", "port": "7899", - "tls_ca_file": "./fixtures/root-ca.crt" }, + "tls_ca_file": "./fixtures/root-ca.crt", + "key_algorithm": "ecdsa" + }, "logging": { "level": "debug" }, "storage": { "backend": "mysql", "db_url": "dockercondemo:dockercondemo@tcp(notarymysql:3306)/dockercondemo" + }, + "reporting": { + "bugsnag": "enable", + "bugsnag_api_key": "", + "bugsnag_release_stage": "development" } } diff --git a/cmd/notary-server/dev-config.json b/cmd/notary-server/dev-config.json index 7026357e69..1a0359672e 100644 --- a/cmd/notary-server/dev-config.json +++ b/cmd/notary-server/dev-config.json @@ -7,7 +7,8 @@ "trust_service": { "type": "local", "hostname": "", - "port": "" + "port": "", + "key_algorithm": "ed25519" }, "logging": { "level": "debug" diff --git a/cmd/notary-server/main.go b/cmd/notary-server/main.go index 219005ea09..8c0c8c61df 100644 --- a/cmd/notary-server/main.go +++ b/cmd/notary-server/main.go @@ -8,18 +8,18 @@ import ( "net/http" _ "net/http/pprof" "os" - "os/signal" "path/filepath" "strings" - "syscall" "github.com/Sirupsen/logrus" + "github.com/bugsnag/bugsnag-go" _ "github.com/docker/distribution/registry/auth/htpasswd" _ "github.com/docker/distribution/registry/auth/token" "github.com/endophage/gotuf/signed" _ "github.com/go-sql-driver/mysql" "golang.org/x/net/context" + bugsnag_hook "github.com/Sirupsen/logrus/hooks/bugsnag" "github.com/docker/notary/server" "github.com/docker/notary/server/storage" "github.com/docker/notary/signer" @@ -71,11 +71,28 @@ func main() { } logrus.SetLevel(lvl) - sigHup := make(chan os.Signal) - sigTerm := make(chan os.Signal) - - signal.Notify(sigHup, syscall.SIGHUP) - signal.Notify(sigTerm, syscall.SIGTERM) + // set up bugsnag and attach to logrus + bugs := viper.GetString("reporting.bugsnag") + if bugs != "" { + apiKey := viper.GetString("reporting.bugsnag_api_key") + releaseStage := viper.GetString("reporting.bugsnag_release_stage") + bugsnag.Configure(bugsnag.Configuration{ + APIKey: apiKey, + ReleaseStage: releaseStage, + }) + hook, err := bugsnag_hook.NewBugsnagHook() + if err != nil { + logrus.Error("Could not attach bugsnag to logrus: ", err.Error()) + } else { + logrus.AddHook(hook) + } + } + keyAlgo := viper.GetString("trust_service.key_algorithm") + if keyAlgo == "" { + logrus.Fatal("no key algorithm configured.") + os.Exit(1) + } + ctx = context.WithValue(ctx, "keyAlgorithm", keyAlgo) var trust signed.CryptoService if viper.GetString("trust_service.type") == "remote" { diff --git a/errors/errors.go b/errors/errors.go index e43bea400a..f9d35c182d 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -10,70 +10,69 @@ import ( // with the registry API const errGroup = "notary.api.v1" +// These errors should be returned from contextHandlers only. They are +// serialized and returned to a user as part of the generic error handling +// done by the rootHandler var ( - // ErrNoStorage lint comment ErrNoStorage = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "NO_STORAGE", Message: "The server is misconfigured and has no storage.", Description: "No storage backend has been configured for the server.", HTTPStatusCode: http.StatusInternalServerError, }) - // ErrNoFilename lint comment ErrNoFilename = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "NO_FILENAME", Message: "No file/role name provided.", Description: "No file/role name is provided to associate an update with.", HTTPStatusCode: http.StatusBadRequest, }) - // ErrInvalidRole lint comment ErrInvalidRole = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "INVALID_ROLE", Message: "The role you are attempting to operate on is invalid.", Description: "The user attempted to operate on a role that is not deemed valid.", HTTPStatusCode: http.StatusBadRequest, }) - // ErrMalformedJSON lint comment ErrMalformedJSON = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "MALFORMED_JSON", Message: "JSON sent by the client could not be parsed by the server", Description: "The client sent malformed JSON.", HTTPStatusCode: http.StatusBadRequest, }) - // ErrUpdating lint comment ErrUpdating = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "UPDATING", Message: "An error has occurred while updating the TUF repository.", Description: "An error occurred when attempting to apply an update at the storage layer.", HTTPStatusCode: http.StatusInternalServerError, }) - // ErrMetadataNotFound lint comment ErrMetadataNotFound = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "METADATA_NOT_FOUND", Message: "You have requested metadata that does not exist.", Description: "The user requested metadata that is not known to the server.", HTTPStatusCode: http.StatusNotFound, }) - // ErrMalformedUpload lint comment ErrMalformedUpload = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "MALFORMED_UPLOAD", Message: "The body of your request is malformed.", Description: "The user uploaded new TUF data and the server was unable to parse it as multipart/form-data.", HTTPStatusCode: http.StatusBadRequest, }) - // ErrGenericNotFound lint comment ErrGenericNotFound = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "GENERIC_NOT_FOUND", Message: "You have requested a resource that does not exist.", Description: "The user requested a non-specific resource that is not known to the server.", HTTPStatusCode: http.StatusNotFound, }) - // ErrNoCryptoService lint comment ErrNoCryptoService = errcode.Register(errGroup, errcode.ErrorDescriptor{ Value: "NO_CRYPTOSERVICE", Message: "The server does not have a signing service configured.", Description: "No signing service has been configured for the server and it has been asked to perform an operation that requires either signing, or key generation.", HTTPStatusCode: http.StatusInternalServerError, }) - // ErrUnknown is the generic internal server error + ErrNoKeyAlgorithm = errcode.Register(errGroup, errcode.ErrorDescriptor{ + Value: "NO_KEYALGORITHM", + Message: "The server does not have a key algorithm configured.", + Description: "No key algorihtm has been configured for the server and it has been asked to perform an operation that requires generation.", + HTTPStatusCode: http.StatusInternalServerError, + }) ErrUnknown = errcode.ErrorCodeUnknown ) diff --git a/server/handlers/default.go b/server/handlers/default.go index 9ba52edeba..a1c256b160 100644 --- a/server/handlers/default.go +++ b/server/handlers/default.go @@ -161,20 +161,27 @@ func GetTimestampKeyHandler(ctx context.Context, w http.ResponseWriter, r *http. s := ctx.Value("metaStore") store, ok := s.(storage.MetaStore) if !ok { - logrus.Debugf("[Notary Server] 500 GET storage not configured") + logrus.Debug("[Notary Server] 500 GET storage not configured") return errors.ErrNoStorage.WithDetail(nil) } c := ctx.Value("cryptoService") crypto, ok := c.(signed.CryptoService) if !ok { - logrus.Debugf("[Notary Server] 500 GET crypto service not configured") + logrus.Debug("[Notary Server] 500 GET crypto service not configured") return errors.ErrNoCryptoService.WithDetail(nil) } + algo := ctx.Value("keyAlgorithm") + keyAlgo, ok := algo.(string) + if !ok { + logrus.Debug("[Notary Server] 500 GET key algorithm not configured") + return errors.ErrNoKeyAlgorithm.WithDetail(nil) + } + keyAlgorithm := data.KeyAlgorithm(keyAlgo) vars := mux.Vars(r) gun := vars["imageName"] - key, err := timestamp.GetOrCreateTimestampKey(gun, store, crypto, data.ECDSAKey) + key, err := timestamp.GetOrCreateTimestampKey(gun, store, crypto, keyAlgorithm) if err != nil { logrus.Debugf("[Notary Server] 500 GET timestamp key for %s: %v", gun, err) return errors.ErrUnknown.WithDetail(err) diff --git a/server/server.go b/server/server.go index 7eb7d885fb..4728cdd3b8 100644 --- a/server/server.go +++ b/server/server.go @@ -70,9 +70,7 @@ func Run(ctx context.Context, addr, tlsCertFile, tlsKeyFile string, trust signed } var ac auth.AccessController - if authMethod == "" { - ac = nil - } else { + if authMethod == "token" { authOptions, ok := authOpts.(map[string]interface{}) if !ok { return fmt.Errorf("auth.options must be a map[string]interface{}")