diff --git a/.drone.star b/.drone.star index b9391b18e..cdb55be3e 100644 --- a/.drone.star +++ b/.drone.star @@ -927,12 +927,15 @@ def wopiValidatorTests(ctx, storage, wopiServerType, accounts_hash_difficulty = "MICRO_REGISTRY": "nats-js-kv", "MICRO_REGISTRY_ADDRESS": "ocis-server:9233", "COLLABORATION_LOG_LEVEL": "debug", + "COLLABORATION_HTTP_ADDR": "0.0.0.0:9300", + "COLLABORATION_GRPC_ADDR": "0.0.0.0:9301", "COLLABORATION_APP_NAME": "FakeOffice", - "COLLABORATION_HTTP_ADDR": "wopiserver:9300", - "COLLABORATION_HTTP_SCHEME": "http", - "COLLABORATION_WOPIAPP_ADDR": "http://fakeoffice:8080", - "COLLABORATION_WOPIAPP_INSECURE": "true", + "COLLABORATION_APP_ADDR": "http://fakeoffice:8080", + "COLLABORATION_APP_INSECURE": "true", + "COLLABORATION_WOPI_SRC": "http://wopiserver", + "COLLABORATION_WOPI_SECRET": "some-wopi-secret", "COLLABORATION_CS3API_DATAGATEWAY_INSECURE": "true", + "OCIS_JWT_SECRET": "some-ocis-jwt-secret", }, "commands": [ "%s collaboration server" % ocis_bin, @@ -1920,6 +1923,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = "MICRO_REGISTRY_ADDRESS": "127.0.0.1:9233", "NATS_NATS_HOST": "0.0.0.0", "NATS_NATS_PORT": 9233, + "OCIS_JWT_SECRET": "some-ocis-jwt-secret", } if deploy_type == "": diff --git a/.vscode/launch.json b/.vscode/launch.json index aaf63a8c7..28f4d4062 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -50,6 +50,8 @@ "OCIS_JWT_SECRET": "some-ocis-jwt-secret", "OCIS_MACHINE_AUTH_API_KEY": "some-ocis-machine-auth-api-key", "OCIS_TRANSFER_SECRET": "some-ocis-transfer-secret", + // collaboration + "COLLABORATION_WOPIAPP_SECRET": "some-wopi-secret", // idm ldap "IDM_SVC_PASSWORD": "some-ldap-idm-password", "GRAPH_LDAP_BIND_PASSWORD": "some-ldap-idm-password", diff --git a/ocis-pkg/shared/errors.go b/ocis-pkg/shared/errors.go index be681d6ec..e7dfcc7e2 100644 --- a/ocis-pkg/shared/errors.go +++ b/ocis-pkg/shared/errors.go @@ -85,3 +85,11 @@ func MissingServiceAccountSecret(service string) error { "the config/corresponding environment variable).", service, defaults.BaseConfigPath()) } + +func MissingWOPISecretError(service string) error { + return fmt.Errorf("The WOPI secret has not been set properly in your config for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable).", + service, defaults.BaseConfigPath()) +} diff --git a/ocis/pkg/init/init.go b/ocis/pkg/init/init.go index 70d6865cc..9b68605b1 100644 --- a/ocis/pkg/init/init.go +++ b/ocis/pkg/init/init.go @@ -156,6 +156,15 @@ type Clientlog struct { ServiceAccount ServiceAccount `yaml:"service_account"` } +type WopiApp struct { + Insecure bool `yaml:"insecure"` + Secret string `yaml:"secret"` +} + +type Collaboration struct { + WopiApp WopiApp `yaml:"wopiapp"` +} + type Nats struct { // The nats config has a field called nats Nats struct { @@ -191,6 +200,7 @@ type OcisConfig struct { Graph GraphService Idp LdapBasedService Idm IdmService + Collaboration Collaboration Proxy ProxyService Frontend FrontendService AuthBasic AuthbasicService `yaml:"auth_basic"` @@ -289,6 +299,10 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin if err != nil { return fmt.Errorf("could not generate random password for tokenmanager: %s", err) } + collaborationWOPISecret, err := generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random wopi secret for collaboration service: %s", err) + } machineAuthAPIKey, err := generators.GenerateRandomPassword(passwordLength) if err != nil { return fmt.Errorf("could not generate random password for machineauthsecret: %s", err) @@ -344,6 +358,11 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin }, }, }, + Collaboration: Collaboration{ + WopiApp: WopiApp{ + Secret: collaborationWOPISecret, + }, + }, Groups: UsersAndGroupsService{ Drivers: LdapBasedService{ Ldap: LdapSettings{ @@ -417,6 +436,7 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin cfg.AuthBearer = AuthbearerService{ AuthProviders: AuthProviderSettings{Oidc: _insecureService}, } + cfg.Collaboration.WopiApp.Insecure = true cfg.Frontend.AppHandler = _insecureService cfg.Frontend.Archiver = _insecureService cfg.Graph.Spaces = _insecureService diff --git a/services/collaboration/README.md b/services/collaboration/README.md index 8f2eb61bb..205c54e48 100644 --- a/services/collaboration/README.md +++ b/services/collaboration/README.md @@ -10,7 +10,7 @@ The collaboration service requires the target document server (ONLYOFFICE, Colla * External document server. * The gateway service. -* The app-provider service. +* The app-registry service. If any of the named services above have not been started or are not reachable, the collaboration service won't start. For the binary or the docker release of Infinite Scale, check with the `ocis list` command if they have been started. If not, you must start them manually upfront before starting the collaboration service. @@ -18,15 +18,15 @@ If any of the named services above have not been started or are not reachable, t There are a few variables that you need to set: -* `COLLABORATION_WOPIAPP_ADDR`:\ - The URL of the WOPI app (onlyoffice, collabora, etc).\ +* `COLLABORATION_APP_ADDR`:\ + The URL of the collaborative editing app (onlyoffice, collabora, etc).\ For example: `https://office.example.com`. -* `COLLABORATION_HTTP_ADDR`:\ - The external address of the collaboration service. The target app (onlyoffice, collabora, etc) will use this address to read and write files from Infinite Scale.\ - For example: `https://wopiserver.example.com`. +* `COLLABORATION_APP_INSECURE`:\ + In case you are using a self signed certificate for the WOPI app you can tell the collaboration service to allow an insecure connection. -* `COLLABORATION_HTTP_SCHEME`:\ - The scheme to be used when accessing the collaboration service. Either `http` or `https`. This will be used to finally build the URL that the WOPI app needs in order to contact the collaboration service. +* `COLLABORATION_APP_WOPISRC`:\ + The external address of the collaboration service. The target app (onlyoffice, collabora, etc) will use this address to read and write files from Infinite Scale. \ + For example: `https://wopi.example.com`. -The rest of the configuration options available can be left with the default values. +The application can be customized further by changing the `COLLABORATION_APP_*` options to better describe the application. diff --git a/services/collaboration/pkg/command/server.go b/services/collaboration/pkg/command/server.go index c18b64148..5732c5589 100644 --- a/services/collaboration/pkg/command/server.go +++ b/services/collaboration/pkg/command/server.go @@ -71,10 +71,7 @@ func Server(cfg *config.Config) *cli.Command { ) defer teardown() if err != nil { - logger.Info(). - Err(err). - Str("transport", "grpc"). - Msg("Failed to initialize server") + logger.Error().Err(err).Str("transport", "grpc").Msg("Failed to initialize server") return err } @@ -85,11 +82,8 @@ func Server(cfg *config.Config) *cli.Command { } return grpcServer.Serve(l) }, - func(_ error) { - logger.Error(). - Err(err). - Str("server", "grpc"). - Msg("shutting down server") + func(err error) { + logger.Error().Err(err).Str("server", "grpc").Msg("shutting down server") cancel() }) @@ -100,7 +94,7 @@ func Server(cfg *config.Config) *cli.Command { debug.Config(cfg), ) if err != nil { - logger.Info().Err(err).Str("transport", "debug").Msg("Failed to initialize server") + logger.Error().Err(err).Str("transport", "debug").Msg("Failed to initialize server") return err } @@ -117,6 +111,10 @@ func Server(cfg *config.Config) *cli.Command { http.Context(ctx), http.TracerProvider(traceProvider), ) + if err != nil { + logger.Error().Err(err).Str("transport", "http").Msg("Failed to initialize server") + return err + } gr.Add(httpServer.Run, func(_ error) { cancel() }) diff --git a/services/collaboration/pkg/config/app.go b/services/collaboration/pkg/config/app.go index 69c5447f0..bbe08ef09 100644 --- a/services/collaboration/pkg/config/app.go +++ b/services/collaboration/pkg/config/app.go @@ -6,4 +6,7 @@ type App struct { Description string `yaml:"description" env:"COLLABORATION_APP_DESCRIPTION" desc:"App description" introductionVersion:"5.1"` Icon string `yaml:"icon" env:"COLLABORATION_APP_ICON" desc:"Icon for the app" introductionVersion:"5.1"` LockName string `yaml:"lockname" env:"COLLABORATION_APP_LOCKNAME" desc:"Name for the app lock" introductionVersion:"5.1"` + + Addr string `yaml:"addr" env:"COLLABORATION_APP_ADDR" desc:"The URL where the WOPI app is located, such as https://127.0.0.1:8080." introductionVersion:"5.1"` + Insecure bool `yaml:"insecure" env:"COLLABORATION_APP_INSECURE" desc:"Skip TLS certificate verification when connecting to the WOPI app" introductionVersion:"5.1"` } diff --git a/services/collaboration/pkg/config/config.go b/services/collaboration/pkg/config/config.go index 7654a5e34..054529d94 100644 --- a/services/collaboration/pkg/config/config.go +++ b/services/collaboration/pkg/config/config.go @@ -14,12 +14,13 @@ type Config struct { Service Service `yaml:"-"` App App `yaml:"app"` - JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;COLLABORATION_JWT_SECRET" desc:"Used as JWT token and to encrypt access token." introductionVersion:"5.1"` + TokenManager *TokenManager `yaml:"token_manager"` - GRPC GRPC `yaml:"grpc"` - HTTP HTTP `yaml:"http"` - WopiApp WopiApp `yaml:"wopiapp"` - CS3Api CS3Api `yaml:"cs3api"` + GRPC GRPC `yaml:"grpc"` + HTTP HTTP `yaml:"http"` + + Wopi Wopi `yaml:"wopi"` + CS3Api CS3Api `yaml:"cs3api"` Tracing *Tracing `yaml:"tracing"` Log *Log `yaml:"log"` diff --git a/services/collaboration/pkg/config/cs3api.go b/services/collaboration/pkg/config/cs3api.go index 776cf8617..d2a85f3e1 100644 --- a/services/collaboration/pkg/config/cs3api.go +++ b/services/collaboration/pkg/config/cs3api.go @@ -8,7 +8,7 @@ type CS3Api struct { // Gateway defines the available configuration for the CS3 API gateway type Gateway struct { - Name string `yaml: "name" env:"OCIS_REVA_GATEWAY;COLLABORATION_CS3API_GATEWAY_NAME" desc:"The service name of the CS3API gateway." introductionVersion:"5.1"` + Name string `yaml:"name" env:"OCIS_REVA_GATEWAY;COLLABORATION_CS3API_GATEWAY_NAME" desc:"The service name of the CS3API gateway." introductionVersion:"5.1"` } // DataGateway defines the available configuration for the CS3 API data gateway diff --git a/services/collaboration/pkg/config/defaults/defaultconfig.go b/services/collaboration/pkg/config/defaults/defaultconfig.go index 3bb805e71..1fd0e4e71 100644 --- a/services/collaboration/pkg/config/defaults/defaultconfig.go +++ b/services/collaboration/pkg/config/defaults/defaultconfig.go @@ -1,7 +1,7 @@ package defaults import ( - "github.com/owncloud/ocis/v2/ocis-pkg/generators" + "github.com/owncloud/ocis/v2/ocis-pkg/shared" "github.com/owncloud/ocis/v2/services/collaboration/pkg/config" ) @@ -15,7 +15,6 @@ func FullDefaultConfig() *config.Config { // DefaultConfig returns a basic default configuration func DefaultConfig() *config.Config { - secret, _ := generators.GenerateRandomString(generators.AlphaNumChars, 32) // anything to do with the error? return &config.Config{ Service: config.Service{ Name: "collaboration", @@ -25,17 +24,16 @@ func DefaultConfig() *config.Config { Description: "Open office documents with Collabora", Icon: "image-edit", LockName: "com.github.owncloud.collaboration", + Addr: "https://127.0.0.1:9980", + Insecure: false, }, - JWTSecret: secret, GRPC: config.GRPC{ - Addr: "0.0.0.0:9301", - Namespace: "com.owncloud.collaboration", + Addr: "127.0.0.1:9301", + Namespace: "com.owncloud.api", }, HTTP: config.HTTP{ Addr: "127.0.0.1:9300", - BindAddr: "0.0.0.0:9300", - Namespace: "com.owncloud.collaboration", - Scheme: "https", + Namespace: "com.owncloud.web", }, Debug: config.Debug{ Addr: "127.0.0.1:9304", @@ -43,13 +41,12 @@ func DefaultConfig() *config.Config { Pprof: false, Zpages: false, }, - WopiApp: config.WopiApp{ - Addr: "https://127.0.0.1:8080", - Insecure: false, + Wopi: config.Wopi{ + WopiSrc: "https://localhost:9300", }, CS3Api: config.CS3Api{ Gateway: config.Gateway{ - Name: "com.owncloud.api.gateway", + Name: shared.DefaultRevaConfig().Address, }, DataGateway: config.DataGateway{ Insecure: false, @@ -83,6 +80,14 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } // Sanitize sanitized the configuration diff --git a/services/collaboration/pkg/config/http.go b/services/collaboration/pkg/config/http.go index 31a0ee090..ba8e6a92f 100644 --- a/services/collaboration/pkg/config/http.go +++ b/services/collaboration/pkg/config/http.go @@ -6,9 +6,7 @@ import ( // HTTP defines the available http configuration. type HTTP struct { - Addr string `yaml:"addr" env:"COLLABORATION_HTTP_ADDR" desc:"The external address of the collaboration service wihout a leading scheme. Either use an IP address or a hostname (127.0.0.1:9301 or wopi.private.prv). The configured 'Scheme' in another envvar will be used to finally build the public URL along with this address." introductionVersion:"5.1"` - BindAddr string `yaml:"bindaddr" env:"COLLABORATION_HTTP_BINDADDR" desc:"The bind address of the HTTP service. Use ':', for example, '127.0.0.1:9301' or '0.0.0.0:9301'." introductionVersion:"5.1"` + Addr string `yaml:"addr" env:"COLLABORATION_HTTP_ADDR" desc:"The bind address of the HTTP service." introductionVersion:"5.1"` Namespace string `yaml:"-"` - Scheme string `yaml:"scheme" env:"COLLABORATION_HTTP_SCHEME" desc:"The scheme to use for the HTTP address, which is either 'http' or 'https'." introductionVersion:"5.1"` TLS shared.HTTPServiceTLS `yaml:"tls"` } diff --git a/services/collaboration/pkg/config/parser/parse.go b/services/collaboration/pkg/config/parser/parse.go index 6f926fc4b..ee38fc318 100644 --- a/services/collaboration/pkg/config/parser/parse.go +++ b/services/collaboration/pkg/config/parser/parse.go @@ -2,12 +2,15 @@ package parser import ( "errors" + "fmt" + "net/url" ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config" + ocisdefaults "github.com/owncloud/ocis/v2/ocis-pkg/config/defaults" + "github.com/owncloud/ocis/v2/ocis-pkg/config/envdecode" + "github.com/owncloud/ocis/v2/ocis-pkg/shared" "github.com/owncloud/ocis/v2/services/collaboration/pkg/config" "github.com/owncloud/ocis/v2/services/collaboration/pkg/config/defaults" - - "github.com/owncloud/ocis/v2/ocis-pkg/config/envdecode" ) // ParseConfig loads configuration from known paths. @@ -34,5 +37,27 @@ func ParseConfig(cfg *config.Config) error { // Validate validates the configuration func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + if cfg.Wopi.Secret == "" { + return shared.MissingWOPISecretError(cfg.Service.Name) + } + url, err := url.Parse(cfg.Wopi.WopiSrc) + if err != nil { + return fmt.Errorf("The WOPI Src has not been set properly in your config for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable): %s", + cfg.Service.Name, ocisdefaults.BaseConfigPath(), err.Error()) + } + if url.Path != "" { + return fmt.Errorf("The WOPI Src must not contain a path in your config for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable)", + cfg.Service.Name, ocisdefaults.BaseConfigPath()) + } + return nil } diff --git a/services/collaboration/pkg/config/reva.go b/services/collaboration/pkg/config/reva.go new file mode 100644 index 000000000..5e2d87d22 --- /dev/null +++ b/services/collaboration/pkg/config/reva.go @@ -0,0 +1,6 @@ +package config + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;COLLABORATION_JWT_SECRET" desc:"The secret to mint and validate jwt tokens." introductionVersion:"pre5.0"` +} diff --git a/services/collaboration/pkg/config/wopi.go b/services/collaboration/pkg/config/wopi.go new file mode 100644 index 000000000..fd1b0e618 --- /dev/null +++ b/services/collaboration/pkg/config/wopi.go @@ -0,0 +1,7 @@ +package config + +// Wopi defines the available configuration for the WOPI endpoint. +type Wopi struct { + WopiSrc string `yaml:"wopisrc" env:"COLLABORATION_WOPI_SRC" desc:"The WOPISrc base URL containing schema, host and port. Set this to the schema and domain where the collaboration service is reachable for the wopi app, such as https://office.owncloud.test." introductionVersion:"5.1"` + Secret string `yaml:"secret" env:"COLLABORATION_WOPI_SECRET" desc:"Used to mint and verify WOPI JWT tokens and encrypt and decrypt the REVA JWT token embedded in the WOPI JWT token." introductionVersion:"5.1"` +} diff --git a/services/collaboration/pkg/config/wopiapp.go b/services/collaboration/pkg/config/wopiapp.go deleted file mode 100644 index 8f4427e2e..000000000 --- a/services/collaboration/pkg/config/wopiapp.go +++ /dev/null @@ -1,7 +0,0 @@ -package config - -// WopiApp defines the available configuration in order to connect to a WOPI app. -type WopiApp struct { - Addr string `yaml:"addr" env:"COLLABORATION_WOPIAPP_ADDR" desc:"The URL where the WOPI app is located, such as https://127.0.0.1:8080." introductionVersion:"5.1"` - Insecure bool `yaml:"insecure" env:"COLLABORATION_WOPIAPP_INSECURE" desc:"Skip TLS certificate verification when connecting to the WOPI app" introductionVersion:"5.1"` -} diff --git a/services/collaboration/pkg/helpers/discovery.go b/services/collaboration/pkg/helpers/discovery.go index 893ca7568..4165609ba 100644 --- a/services/collaboration/pkg/helpers/discovery.go +++ b/services/collaboration/pkg/helpers/discovery.go @@ -17,12 +17,12 @@ import ( // target WOPI app (onlyoffice, collabora, etc) via their "/hosting/discovery" // endpoint. func GetAppURLs(cfg *config.Config, logger log.Logger) (map[string]map[string]string, error) { - wopiAppUrl := cfg.WopiApp.Addr + "/hosting/discovery" + wopiAppUrl := cfg.App.Addr + "/hosting/discovery" httpClient := http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ - InsecureSkipVerify: cfg.WopiApp.Insecure, + InsecureSkipVerify: cfg.App.Insecure, }, }, } diff --git a/services/collaboration/pkg/helpers/discovery_test.go b/services/collaboration/pkg/helpers/discovery_test.go index cb1679045..6fb44ffcc 100644 --- a/services/collaboration/pkg/helpers/discovery_test.go +++ b/services/collaboration/pkg/helpers/discovery_test.go @@ -67,7 +67,7 @@ var _ = Describe("Discovery", func() { Describe("GetAppURLs", func() { It("Good discovery URL", func() { cfg := &config.Config{ - WopiApp: config.WopiApp{ + App: config.App{ Addr: srv.URL + "/good", Insecure: true, }, @@ -95,7 +95,7 @@ var _ = Describe("Discovery", func() { It("Wrong discovery URL", func() { cfg := &config.Config{ - WopiApp: config.WopiApp{ + App: config.App{ Addr: srv.URL + "/bad", Insecure: true, }, @@ -109,7 +109,7 @@ var _ = Describe("Discovery", func() { It("Not XML formatted", func() { cfg := &config.Config{ - WopiApp: config.WopiApp{ + App: config.App{ Addr: srv.URL + "/wrongformat", Insecure: true, }, diff --git a/services/collaboration/pkg/helpers/registration.go b/services/collaboration/pkg/helpers/registration.go index c5e375dba..a3b83f4d4 100644 --- a/services/collaboration/pkg/helpers/registration.go +++ b/services/collaboration/pkg/helpers/registration.go @@ -11,6 +11,7 @@ import ( "github.com/gofrs/uuid" "github.com/owncloud/ocis/v2/ocis-pkg/log" "github.com/owncloud/ocis/v2/ocis-pkg/registry" + "github.com/owncloud/ocis/v2/ocis-pkg/version" "github.com/owncloud/ocis/v2/services/collaboration/pkg/config" ) @@ -18,7 +19,7 @@ import ( // There are no explicit requirements for the context, and it will be passed // without changes to the underlying RegisterService method. func RegisterOcisService(ctx context.Context, cfg *config.Config, logger log.Logger) error { - svc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, "0.0.0") + svc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString()) return registry.RegisterService(ctx, svc, logger) } diff --git a/services/collaboration/pkg/server/http/server.go b/services/collaboration/pkg/server/http/server.go index c24c2acd1..d1f3b7394 100644 --- a/services/collaboration/pkg/server/http/server.go +++ b/services/collaboration/pkg/server/http/server.go @@ -25,10 +25,11 @@ func Server(opts ...Option) (http.Service, error) { http.TLSConfig(options.Config.HTTP.TLS), http.Logger(options.Logger), http.Namespace(options.Config.HTTP.Namespace), - http.Name("wopi"), + http.Name(options.Config.Service.Name), http.Version(version.GetString()), - http.Address(options.Config.HTTP.BindAddr), + http.Address(options.Config.HTTP.Addr), http.Context(options.Context), + http.TraceProvider(options.TracerProvider), ) if err != nil { options.Logger.Error(). @@ -40,7 +41,7 @@ func Server(opts ...Option) (http.Service, error) { middlewares := []func(stdhttp.Handler) stdhttp.Handler{ chimiddleware.RequestID, middleware.Version( - "userlog", + options.Config.Service.Name, version.GetString(), ), middleware.Logger( @@ -48,7 +49,7 @@ func Server(opts ...Option) (http.Service, error) { ), middleware.ExtractAccountUUID( account.Logger(options.Logger), - account.JWTSecret(options.Config.JWTSecret), // previously, secret came from Config.TokenManager.JWTSecret + account.JWTSecret(options.Config.TokenManager.JWTSecret), ), /* // Need CORS? not in the original server @@ -68,7 +69,7 @@ func Server(opts ...Option) (http.Service, error) { mux.Use( otelchi.Middleware( - "collaboration", + options.Config.Service.Name, otelchi.WithChiRoutes(mux), otelchi.WithTracerProvider(options.TracerProvider), otelchi.WithPropagators(tracing.GetPropagator()), @@ -77,6 +78,12 @@ func Server(opts ...Option) (http.Service, error) { prepareRoutes(mux, options) + // in debug mode print out the actual routes + _ = chi.Walk(mux, func(method string, route string, handler stdhttp.Handler, middlewares ...func(stdhttp.Handler) stdhttp.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) + if err := micro.RegisterHandler(service.Server(), mux); err != nil { return http.Service{}, err } @@ -110,7 +117,7 @@ func prepareRoutes(r *chi.Mux, options Options) { r.Use(func(h stdhttp.Handler) stdhttp.Handler { // authentication and wopi context - return colabmiddleware.WopiContextAuthMiddleware(options.Config.JWTSecret, h) + return colabmiddleware.WopiContextAuthMiddleware(options.Config.Wopi.Secret, h) }, ) diff --git a/services/collaboration/pkg/service/grpc/v0/service.go b/services/collaboration/pkg/service/grpc/v0/service.go index 3d29bba2d..67ae47eb0 100644 --- a/services/collaboration/pkg/service/grpc/v0/service.go +++ b/services/collaboration/pkg/service/grpc/v0/service.go @@ -123,11 +123,11 @@ func (s *Service) OpenInApp( viewAppURL = editAppURL } - wopiSrcURL := url.URL{ - Scheme: s.config.HTTP.Scheme, - Host: s.config.HTTP.Addr, - Path: path.Join("wopi", "files", fileRef), + wopiSrcURL, err := url.Parse(s.config.Wopi.WopiSrc) + if err != nil { + return nil, err } + wopiSrcURL.Path = path.Join("wopi", "files", fileRef) addWopiSrcQueryParam := func(baseURL string) (string, error) { u, err := url.Parse(baseURL) @@ -169,7 +169,7 @@ func (s *Service) OpenInApp( appURL = editAppURL } - cryptedReqAccessToken, err := middleware.EncryptAES([]byte(s.config.JWTSecret), req.GetAccessToken()) + cryptedReqAccessToken, err := middleware.EncryptAES([]byte(s.config.Wopi.Secret), req.GetAccessToken()) if err != nil { s.logger.Error(). Err(err). @@ -184,7 +184,7 @@ func (s *Service) OpenInApp( wopiContext := middleware.WopiContext{ AccessToken: cryptedReqAccessToken, - ViewOnlyToken: utils.ReadPlainFromOpaque(req.Opaque, "viewOnlyToken"), + ViewOnlyToken: utils.ReadPlainFromOpaque(req.GetOpaque(), "viewOnlyToken"), FileReference: providerFileRef, User: user, ViewMode: req.GetViewMode(), @@ -213,7 +213,7 @@ func (s *Service) OpenInApp( } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - accessToken, err := token.SignedString([]byte(s.config.JWTSecret)) + accessToken, err := token.SignedString([]byte(s.config.Wopi.Secret)) if err != nil { s.logger.Error(). diff --git a/services/collaboration/pkg/service/grpc/v0/service_suite_test.go b/services/collaboration/pkg/service/grpc/v0/service_suite_test.go index d135fa2cc..b3d922b57 100644 --- a/services/collaboration/pkg/service/grpc/v0/service_suite_test.go +++ b/services/collaboration/pkg/service/grpc/v0/service_suite_test.go @@ -7,7 +7,7 @@ import ( . "github.com/onsi/gomega" ) -func TestGraph(t *testing.T) { +func TestService(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Service Suite") } diff --git a/services/collaboration/pkg/service/grpc/v0/service_test.go b/services/collaboration/pkg/service/grpc/v0/service_test.go index cc5bbcd45..c8b6544bc 100644 --- a/services/collaboration/pkg/service/grpc/v0/service_test.go +++ b/services/collaboration/pkg/service/grpc/v0/service_test.go @@ -103,8 +103,7 @@ var _ = Describe("Discovery", func() { It("Invalid access token", func() { ctx := context.Background() - cfg.HTTP.Addr = "wopiserver.test.prv" - cfg.HTTP.Scheme = "https" + cfg.Wopi.WopiSrc = "https://wopiserver.test.prv" req := &appproviderv1beta1.OpenInAppRequest{ ResourceInfo: &providerv1beta1.ResourceInfo{ @@ -140,9 +139,8 @@ var _ = Describe("Discovery", func() { ctx := context.Background() nowTime := time.Now() - cfg.HTTP.Addr = "wopiserver.test.prv" - cfg.HTTP.Scheme = "https" - cfg.JWTSecret = "my_supa_secret" + cfg.Wopi.WopiSrc = "https://wopiserver.test.prv" + cfg.Wopi.Secret = "my_supa_secret" myself := &userv1beta1.User{ Id: &userv1beta1.UserId{ @@ -163,7 +161,7 @@ var _ = Describe("Discovery", func() { Path: "/path/to/file.docx", }, ViewMode: appproviderv1beta1.ViewMode_VIEW_MODE_READ_WRITE, - AccessToken: MintToken(myself, cfg.JWTSecret, nowTime), + AccessToken: MintToken(myself, cfg.Wopi.Secret, nowTime), } gatewayClient.On("WhoAmI", mock.Anything, mock.Anything).Times(1).Return(&gatewayv1beta1.WhoAmIResponse{ diff --git a/sonar-project.properties b/sonar-project.properties index bbdf958c5..ba2ba73f9 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -47,3 +47,7 @@ sonar.issue.ignore.multicriteria.g1.resourceKey=**/*_test.go # Ignore "Rename function XXX to match the regular expression ^(_|[a-zA-Z0-9]+)$" rule for tests sonar.issue.ignore.multicriteria.g2.ruleKey=go:S100 sonar.issue.ignore.multicriteria.g2.resourceKey=**/*_test.go + +# Timeout for web requests +#sonar.ws.timeout=60 is the default, but we need to increase it to deal with timeouts when loading defaults +sonar.ws.timeout=120 \ No newline at end of file