diff --git a/README.md b/README.md index 766122d8..0a8f00b0 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ $ ./build/bin/kms-server start --host localhost:8076 --database-type mongodb --d | --shamir-secret-cache-ttl | KMS_SHAMIR_SECRET_CACHE_TTL | An optional value for Shamir secrets cache TTL. Defaults to 10m if caching is enabled. If set to 0, keys are never cached. | | --kms-cache-ttl | KMS_KMS_CACHE_TTL | An optional value for cache TTL for keys stored in server kms. Defaults to 10m if caching is enabled. If set to 0, keys are never cached. | | --enable-cors | KMS_CORS_ENABLE | Enables CORS. Possible values: [true] [false]. Defaults to false. | -| --disable-auth | KMS_AUTH_DISABLE | Disables authorization. Possible values: [true] [false]. Defaults to false. | +| --auth-type | KMS_AUTH_TYPE | Comma-separated list of the types of authorization to enable. Possible values [GNAP] [ZCAP]. Defaults to 'ZCAP,GNAP'. | | --log-level | KMS_LOG_LEVEL | Logging level. Supported options: critical, error, warning, info, debug. Defaults to info. | ## Running tests diff --git a/cmd/kms-server/startcmd/params.go b/cmd/kms-server/startcmd/params.go index 18e46bd7..fe16b859 100644 --- a/cmd/kms-server/startcmd/params.go +++ b/cmd/kms-server/startcmd/params.go @@ -14,9 +14,14 @@ import ( "time" "github.com/spf13/cobra" + + "github.com/trustbloc/kms/pkg/controller/rest" ) const ( + gnapAuthType = "gnap" + zcapAuthType = "zcap" + commonEnvVarUsageText = "Alternatively, this can be set with the following environment variable: " hostEnvKey = "KMS_HOST" @@ -107,10 +112,13 @@ const ( shamirSecretCacheTTLFlagUsage = "An optional value cache TTL (time to live) for keys in server kms. Defaults to 10m if " + "caching is enabled. If set to 0, keys are never cached. " + commonEnvVarUsageText + shamirSecretCacheTTLEnvKey - disableAuthEnvKey = "KMS_AUTH_DISABLE" - disableAuthFlagName = "disable-auth" - disableAuthFlagUsage = "Disables authorization. Possible values: [true] [false]. Defaults to false. " + - commonEnvVarUsageText + disableAuthEnvKey + authTypeEnvKey = "KMS_AUTH_TYPE" + authTypeFlagName = "auth-type" + authTypeFlagUsage = "Comma-separated list of the types of authorization to enable. " + + "Possible values [GNAP] [ZCAP]. " + + "If GNAP and ZCAP are both enabled, then a client may authorize themselves with either one. " + + "If no options are specified, then no authorization will be required. Defaults to 'ZCAP,GNAP'. " + + commonEnvVarUsageText + authTypeEnvKey disableHTTPSIGEnvKey = "KMS_GNAP_HTTPSIG_DISABLE" disableHTTPSIGFlagName = "disable-HTTPSIG" @@ -184,7 +192,7 @@ type serverParameters struct { kmsCacheTTL time.Duration shamirSecretCacheTTL time.Duration enableCache bool - disableAuth bool + authType rest.AuthMethod disableHTTPSIG bool enableCORS bool logLevel string @@ -226,7 +234,6 @@ func getParameters(cmd *cobra.Command) (*serverParameters, error) { //nolint:fun kmsCacheTTLStr := getUserSetVarOptional(cmd, kmsCacheTTLFlagName, kmsCacheTTLEnvKey) shamirSecretCacheTTLStr := getUserSetVarOptional(cmd, shamirSecretCacheTTLFlagName, shamirSecretCacheTTLEnvKey) enableCacheStr := getUserSetVarOptional(cmd, enableCacheFlagName, enableCacheEnvKey) - disableAuthStr := getUserSetVarOptional(cmd, disableAuthFlagName, disableAuthEnvKey) disableHTTPSIGStr := getUserSetVarOptional(cmd, disableHTTPSIGFlagName, disableHTTPSIGEnvKey) enableCORSStr := getUserSetVarOptional(cmd, enableCORSFlagName, enableCORSEnvKey) logLevel := getUserSetVarOptional(cmd, logLevelFlagName, logLevelEnvKey) @@ -271,9 +278,9 @@ func getParameters(cmd *cobra.Command) (*serverParameters, error) { //nolint:fun return nil, fmt.Errorf("parse enableCache: %w", err) } - disableAuth, err := strconv.ParseBool(disableAuthStr) + authType, err := getAuthTypeParameter(cmd) if err != nil { - return nil, fmt.Errorf("parse disableAuth: %w", err) + return nil, err } disableHTTPSIG, err := strconv.ParseBool(disableHTTPSIGStr) @@ -312,7 +319,7 @@ func getParameters(cmd *cobra.Command) (*serverParameters, error) { //nolint:fun kmsCacheTTL: kmsCacheTTL, shamirSecretCacheTTL: shamirSecretCacheTTL, enableCache: enableCache, - disableAuth: disableAuth, + authType: authType, disableHTTPSIG: disableHTTPSIG, enableCORS: enableCORS, logLevel: logLevel, @@ -401,6 +408,33 @@ func getSecretLockParameters(cmd *cobra.Command) (*secretLockParameters, error) }, nil } +func getAuthTypeParameter(cmd *cobra.Command) (rest.AuthMethod, error) { + var result rest.AuthMethod + value, err := getUserSetVar(cmd, authTypeFlagName, authTypeEnvKey, false) + if err != nil { + return rest.AuthNone, err + } + if value == "" { + return rest.AuthNone, nil + } + + authTypes := strings.Split(value, ",") + + for _, authType := range authTypes { + authType = strings.ToLower(strings.Trim(authType, " ")) + switch authType { + case gnapAuthType: + result |= rest.AuthGNAP + case zcapAuthType: + result |= rest.AuthZCAP + default: + return rest.AuthNone, fmt.Errorf("%s is not a valid authorization type", authType) + } + } + + return result, nil +} + func createFlags(startCmd *cobra.Command) { startCmd.Flags().String(hostFlagName, "", hostFlagUsage) startCmd.Flags().String(hostMetricsFlagName, "", hostMetricsFlagUsage) @@ -420,7 +454,7 @@ func createFlags(startCmd *cobra.Command) { startCmd.Flags().String(kmsCacheTTLFlagName, "10m", kmsCacheTTLFlagUsage) startCmd.Flags().String(shamirSecretCacheTTLFlagName, "10m", shamirSecretCacheTTLFlagUsage) startCmd.Flags().String(enableCacheFlagName, "true", enableCacheFlagUsage) - startCmd.Flags().String(disableAuthFlagName, "false", disableAuthFlagUsage) + startCmd.Flags().String(authTypeFlagName, "GNAP,ZCAP", authTypeFlagUsage) startCmd.Flags().String(disableHTTPSIGFlagName, "false", disableHTTPSIGFlagUsage) startCmd.Flags().String(enableCORSFlagName, "false", enableCORSFlagUsage) startCmd.Flags().String(logLevelFlagName, "info", logLevelFlagUsage) diff --git a/cmd/kms-server/startcmd/start.go b/cmd/kms-server/startcmd/start.go index 84f74c10..f2c33244 100644 --- a/cmd/kms-server/startcmd/start.go +++ b/cmd/kms-server/startcmd/start.go @@ -236,7 +236,7 @@ func startServer(srv server, params *serverParameters) error { //nolint:funlen ShamirSecretLockCreator: &shamirSecretLockCreator{}, CryptBoxCreator: &cryptoBoxCreator{}, ZCAPService: zcapService, - EnableZCAPs: !params.disableAuth, + EnableZCAPs: params.authType.HasFlag(rest.AuthZCAP), HeaderSigner: zcapService, TLSConfig: tlsConfig, BaseKeyStoreURL: baseKeyStoreURL, @@ -271,7 +271,7 @@ func startServer(srv server, params *serverParameters) error { //nolint:funlen gnapRSClient *rs.Client ) - if !params.disableAuth { + if params.authType.HasFlag(rest.AuthGNAP) { privateJWK, publicJWK, err = createGNAPSigningJWK(params.gnapSigningKeyPath) if err != nil { return fmt.Errorf("create gnap signing jwk: %w", err) @@ -294,18 +294,19 @@ func startServer(srv server, params *serverParameters) error { //nolint:funlen for _, h := range rest.New(cmd).GetRESTHandlers() { var handler http.Handler = h.Handler() - if !params.disableAuth && !h.Auth().HasFlag(rest.AuthNone) { + if !params.authType.HasFlag(rest.AuthNone) && !h.Auth().HasFlag(rest.AuthNone) { middlewares := make([]authmw.Middleware, 0) - if h.Auth().HasFlag(rest.AuthOAuth2) { - middlewares = append(middlewares, &oauthmw.Middleware{}) - } - - if h.Auth().HasFlag(rest.AuthZCAP) { - middlewares = append(middlewares, &zcapmw.Middleware{Config: zcapConfig, Action: h.Action()}) + if params.authType.HasFlag(rest.AuthZCAP) { + if h.Auth().HasFlag(rest.AuthOAuth2) { + middlewares = append(middlewares, &oauthmw.Middleware{}) + } + if h.Auth().HasFlag(rest.AuthZCAP) { + middlewares = append(middlewares, &zcapmw.Middleware{Config: zcapConfig, Action: h.Action()}) + } } - if h.Auth().HasFlag(rest.AuthGNAP) { + if params.authType.HasFlag(rest.AuthGNAP) && h.Auth().HasFlag(rest.AuthGNAP) { gmw, err := gnapmw.NewMiddleware( gnapRSClient, publicJWK, diff --git a/cmd/kms-server/startcmd/start_test.go b/cmd/kms-server/startcmd/start_test.go index d8c7fcce..9dd0a9f4 100644 --- a/cmd/kms-server/startcmd/start_test.go +++ b/cmd/kms-server/startcmd/start_test.go @@ -512,6 +512,47 @@ func TestStartCmdWithKMSCacheTTLParam(t *testing.T) { }) } +func TestStartCmdWithAuthTypeParam(t *testing.T) { + t.Run("Success with ZCAP and GNAP set", func(t *testing.T) { + startCmd, err := Cmd(&mockServer{}) + require.NoError(t, err) + + args := requiredArgs(storageTypeMemOption) + args = append(args, "--"+authTypeFlagName, "ZCAP,GNAP") + + startCmd.SetArgs(args) + + err = startCmd.Execute() + require.NoError(t, err) + }) + + t.Run("Success with none set", func(t *testing.T) { + startCmd, err := Cmd(&mockServer{}) + require.NoError(t, err) + + args := requiredArgs(storageTypeMemOption) + args = append(args, "--"+authTypeFlagName, "") + + startCmd.SetArgs(args) + + err = startCmd.Execute() + require.NoError(t, err) + }) + + t.Run("Fail with unknown auth type", func(t *testing.T) { + startCmd, err := Cmd(&mockServer{}) + require.NoError(t, err) + + args := requiredArgs(storageTypeMemOption) + args = append(args, "--"+authTypeFlagName, "some-unknown-auth-type") + + startCmd.SetArgs(args) + + err = startCmd.Execute() + require.Error(t, err) + }) +} + func TestStartKMSService(t *testing.T) { const invalidStorageOption = "invalid" @@ -620,7 +661,7 @@ func setEnvVars(t *testing.T) { err = os.Setenv(secretLockKeyPathEnvKey, secretLockKeyFile) require.NoError(t, err) - err = os.Setenv(disableAuthEnvKey, "true") + err = os.Setenv(authTypeEnvKey, "") require.NoError(t, err) } @@ -639,7 +680,7 @@ func unsetEnvVars(t *testing.T) { err = os.Unsetenv(secretLockKeyPathEnvKey) require.NoError(t, err) - err = os.Unsetenv(disableAuthEnvKey) + err = os.Unsetenv(authTypeEnvKey) require.NoError(t, err) } diff --git a/test/bdd/features/kms_cli.feature b/test/bdd/features/kms_cli.feature index 6b2f26ed..736c6a1b 100644 --- a/test/bdd/features/kms_cli.feature +++ b/test/bdd/features/kms_cli.feature @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # -@all +@all_ @kms_cli Feature: Using kms CLI @kms_cli diff --git a/test/bdd/fixtures/docker-compose.yml b/test/bdd/fixtures/docker-compose.yml index 9b1b72f3..f8ab21f8 100644 --- a/test/bdd/fixtures/docker-compose.yml +++ b/test/bdd/fixtures/docker-compose.yml @@ -115,7 +115,7 @@ services: - KMS_DATABASE_TYPE=mongodb - KMS_DATABASE_URL=mongodb://mongodb.example.com:27017 - KMS_DATABASE_PREFIX=orbkms_ - - KMS_AUTH_DISABLE=true + - KMS_AUTH_TYPE= - KMS_GNAP_HTTPSIG_DISABLE=false - KMS_CACHE_ENABLE=true - KMS_LOG_LEVEL=debug