diff --git a/.mailmap b/.mailmap index c12c593fb7..b33dec8f29 100644 --- a/.mailmap +++ b/.mailmap @@ -1,2 +1,3 @@ Aritz Brosa zazola Giuseppe Lo Presti Giuseppe +Michael D'Silva diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 21ef0d583b..541b4dad4f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,5 +8,6 @@ - Ilja Neumann - Jörn Friedrich Dreyer - Michael D'Silva +- Michael D'Silva - Mohitty - Thomas Boerger diff --git a/cmd/reva/common.go b/cmd/reva/common.go index de00099d69..0e97fe2101 100644 --- a/cmd/reva/common.go +++ b/cmd/reva/common.go @@ -77,10 +77,6 @@ func readConfig() (*config, error) { } func writeConfig(c *config) error { - if c.AuthHeader == "" { - c.AuthHeader = "x-access-token" - } - data, err := json.Marshal(c) if err != nil { return err @@ -89,8 +85,7 @@ func writeConfig(c *config) error { } type config struct { - Host string `json:"host"` - AuthHeader string `json:"auth_header"` + Host string `json:"host"` } func read(r *bufio.Reader) (string, error) { diff --git a/cmd/reva/gen/gen.go b/cmd/reva/gen/gen.go index 2a0c61c0bb..ddb685f668 100644 --- a/cmd/reva/gen/gen.go +++ b/cmd/reva/gen/gen.go @@ -104,13 +104,6 @@ skip_methods = ["/status.php"] [http.middlewares.auth.token_managers.jwt] secret = "{{.TokenSecret}}" -[http.middlewares.auth.token_strategies.header] -header = "X-Access-Token" - -[http.middlewares.auth.token_writers.header] -header = "X-Access-Token" - - # GRPC interceptors [grpc.interceptors.trace] @@ -126,15 +119,11 @@ priority = 300 [grpc.interceptors.auth] priority = 400 # keys for grpc metadata are always lowercase, so interceptors headers need to use lowercase. -header = "x-access-token" token_strategy = "header" token_manager = "jwt" # GenerateAccessToken contains the credentials in the payload. Skip auth, otherwise services cannot obtain a token. skip_methods = ["/cs3.authproviderv1beta1.AuthService/GenerateAccessToken"] -[grpc.interceptors.auth.token_strategies.header] -header = "X-Access-Token" - [grpc.interceptors.auth.token_managers.jwt] secret = "{{.TokenSecret}}" diff --git a/cmd/reva/grpc.go b/cmd/reva/grpc.go index 28f82d1dba..ddc0e49444 100644 --- a/cmd/reva/grpc.go +++ b/cmd/reva/grpc.go @@ -30,8 +30,6 @@ import ( "google.golang.org/grpc/metadata" ) -const defaultHeader = "x-access-token" - func getAuthContext() context.Context { ctx := context.Background() // read token from file @@ -41,7 +39,7 @@ func getAuthContext() context.Context { return ctx } ctx = token.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, defaultHeader, t) + ctx = metadata.AppendToOutgoingContext(ctx, token.TokenHeader, t) return ctx } diff --git a/cmd/revad/runtime/runtime.go b/cmd/revad/runtime/runtime.go index 8333cf0578..26a0e8d907 100644 --- a/cmd/revad/runtime/runtime.go +++ b/cmd/revad/runtime/runtime.go @@ -33,6 +33,7 @@ import ( "github.com/cs3org/reva/pkg/logger" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/sharedconf" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -44,6 +45,7 @@ import ( // Run runs a reva server with the given config file and pid file. func Run(mainConf map[string]interface{}, pidFile string) { + parseSharedConfOrDie(mainConf["shared"]) coreConf := parseCoreConfOrDie(mainConf["core"]) logConf := parseLogConfOrDie(mainConf["log"]) @@ -333,6 +335,13 @@ func parseCoreConfOrDie(v interface{}) *coreConf { return c } +func parseSharedConfOrDie(v interface{}) { + if err := sharedconf.Decode(v); err != nil { + fmt.Fprintf(os.Stderr, "error decoding shared config: %s\n", err.Error()) + os.Exit(1) + } +} + func parseLogConfOrDie(v interface{}) *logConf { c := &logConf{} if err := mapstructure.Decode(v, c); err != nil { diff --git a/docs/old/README.md b/docs/old/README.md deleted file mode 100644 index 54f26a75b6..0000000000 --- a/docs/old/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# REVA Documentation - -:warning: REVA is a very young project and documentation is subject to change very often! - -* [Installing REVA](./installing-reva.md) -* [Building REVA from Sources](./building-reva.md) -* [Beginner's Guide](./beginner-guide.md) -* [Controlling REVA](./controlling-reva.md) -* [Command-line parameters](./command-line.md) - -## Guides - -* [Getting started with REVA](./guides/getting-started.md) - -## Config reference - -* [Core](./config/core.md) -* [Log](./config/log.md) -* [HTTP](./config/http.md) -* [GRPC](./config/grpc.md) - -**HTTP services** - -* [helloworld](./config/http/services/helloworld.md) -* [datagateway](./config/http/services/datagateway.md) -* [dataprovider](./config/http/services/dataprovider.md) -* [prometheussvc](./config/http/services/prometheus.md) -* [ocdav](./config/http/services/ocdav.md) -* [ocs](./config/http/services/ocs.md) -* [oidcprovider](./config/http/services/oidcprovider.md) -* [wellknown](./config/http/services/wellknown.md) - -**HTTP middleware** - -* [auth](./config/http/middleware/auth.md) -* [cors](./config/http/middleware/cors.md) -* [log](./config/http/middleware/log.md) - -**GRPC Services** - -* [authprovider](./config/grpc/services/authprovider.md) -* [authregistry](./config/grpc/services/authregistry.md) -* [gateway](./config/grpc/services/gateway.md) -* [helloworld](./config/grpc/services/helloworld.md) -* [storageprovider](./config/grpc/services/storageprovider.md) -* [storageregistry](./config/grpc/services/storageregistry.md) -* [userprovider](./config/grpc/services/userprovider.md) -* [usershareprovider](./config/grpc/services/usershareprovider.md) - -**GRPC interceptors** - -* [auth](./config/grpc/interceptors/auth.md) - diff --git a/docs/old/_config.yml b/docs/old/_config.yml deleted file mode 100644 index 457d7a5473..0000000000 --- a/docs/old/_config.yml +++ /dev/null @@ -1 +0,0 @@ -remote_theme: pmarsceill/just-the-docs diff --git a/docs/old/beginner-guide.md b/docs/old/beginner-guide.md deleted file mode 100644 index ffd29da8a6..0000000000 --- a/docs/old/beginner-guide.md +++ /dev/null @@ -1,95 +0,0 @@ -# Beginner's Guide - -This guide gives a basic introduction to revad and describes some simple tasks that can be done with it. -This guide assumes that revad is already installed on the reader's machine. -If this is not, see [Installing REVA](./installing-reva.md). - -This guide describes how to start and stop the **REVA daemon (revad)**, and reload its configuration, explains the structure of the configuration -file and describes how to set up revad to serve some basic services. - -By default, the configuration file is named revad.toml and placed in the directory /etc/revad/revad.toml. - -## Starting, Stopping, and Reloading Configuration - -To start revad, run the executable file: - -``` -revad -c revad.toml -p /var/tmp/revad.pid -``` - -Once revad is started, it can be controlled by invoking the executable with the -s parameter. Use the following syntax: - -``` -revad -s -p /var/tmp/revad.pid -``` - -Where signal may be one of the following: - -* stop — fast shutdown (aborts in-flight requests) -* quit — graceful shutdown -* reload — reloading the configuration file (forks a new process) - - For example, to stop revad gracefully, the following command can be executed: - -``` -revad -s quit -p /var/tmp/revad.pid -``` - -*This command should be executed under the same user that started revad.* - -Changes made in the configuration file will not be applied until the command to reload configuration is sent to revad or it is restarted. To reload configuration, execute: - -``` -revad -s reload -p /var/tmp/revad.pid -``` - -Once the main process receives the signal to reload configuration, it checks the syntax validity of the new configuration file and tries to apply the configuration provided in it. If this is a success, the main process forks a new process. The new forked process will gracefully kill the parent process. During a period of time until all ongoing requests are served, both processes will share the same network socket, the old parent process will serve ongoing requests and the new process will serve only new requests. No requests are dropped during the reload. If the provided configuration is invalid, the forked process will die and the master process will continue serving requests. - -A signal may also be sent to the revad process with the help of Unix tools such as the *kill* utility. In this case a signal is sent directly to a process with a given process ID. The process ID of the revad master process is written to the pid file, as configured with the *-s* flag. For example, if the master process ID is 1610, to send the QUIT signal resulting in revad’s graceful shutdown, execute: - -``` -kill -s QUIT 1610 -``` - -For getting the list of all running revad processes, the *ps* utility may be used, for example, in the following way: - -``` -ps -ax | grep revad -``` - -For more information on sending signals to revad, see [Controlling REVA](./controlling-reva.md). - -## Configuration File’s Structure -revad configuration file is written in [TOML](https://github.com/toml-lang/toml) language. - -revad consists of services which are controlled by directives specified in the configuration file. - -An example configuration file is the following: - -``` -[http] -enabled_services = ["helloworldsvc"] -``` -Running revad, will output some lines similar to these: - -``` -4:44PM INF main.go:94 > version= commit= branch= go_version= build_date= build_platform= pid=27856 -4:44PM INF main.go:95 > running on 4 cpus pid=27856 -4:44PM INF grace/grace.go:181 > pidfile saved at: /tmp/gonzalhu/revad-44b42674-2f10-4d06-b681-328b5a9b2581.pid pid=27856 pkg=grace -4:44PM INF httpserver/httpserver.go:233 > http service enabled: helloworldsvc@/ pid=27856 pkg=httpserver -4:44PM INF httpserver/httpserver.go:134 > http server listening at http://localhost:9998 pid=27856 pkg=httpserver -``` - -Revad will listen by default at http://localhost:9998, curl-ing this address will render the message *Hello World!*. -The *helloworldsvc* is one of the many services available in revad. To modify the configuration for this service a new directive is added to the configuration: - -``` -[http] -enabled_services = ["helloworldsvc"] - -[http.services.helloworldsvc] -message = "Ola Mundo!" -``` - -Reloading revad (```revad -s reload -p /var/tmp/revad.pid```) will render the new message. - diff --git a/docs/old/building-reva.md b/docs/old/building-reva.md deleted file mode 100644 index e0f4ed2515..0000000000 --- a/docs/old/building-reva.md +++ /dev/null @@ -1,11 +0,0 @@ -# Building REVA - -To build REVA the Go compiler needs to be installed. See [Install Go](https://golang.org/doc/install) to install -the Go programming language that installs the Go compiler. - -``` -git clone https://github.com/cs3org/reva -cd reva -make deps -make -``` diff --git a/docs/old/command-line.md b/docs/old/command-line.md deleted file mode 100644 index a7ceab7c79..0000000000 --- a/docs/old/command-line.md +++ /dev/null @@ -1,16 +0,0 @@ -# Command line parameters - -revad supports the following command-line parameters: - -``` -Usage of ./revad: - -c string - set configuration file (default "/etc/revad/revad.toml") - -p string - pid file. If empty defaults to a random file in the OS temporary directory - -s string - send signal to a master process: stop, quit, reload - -t test configuration and exit - -version - show version and exit -``` diff --git a/docs/old/config/core.md b/docs/old/config/core.md deleted file mode 100644 index a62b4ad1c1..0000000000 --- a/docs/old/config/core.md +++ /dev/null @@ -1,53 +0,0 @@ -# Core functionality - -Example configuration: - -``` -[core] -max_cpus = 2 -tracing_enabled = true -``` - -## Directives - -``` -Syntax: max_cpus = uint | "uint%" -Default: max_cpus = "100%" -``` -If max_cpus is set it determines the available cpus to schedule revad processes. - -``` -Syntax: tracing_enabled = boolean -Default: tracing_enabled = false -``` - -``` -Syntax: tracing_endpoint = string -Default: tracing_endpoint = "localhost:6831" -``` - -``` -Syntax: tracing_collector = string -Default: tracing_collector = "http://localhost:14268/api/traces" -``` - -``` -Syntax: tracing_service_name = string -Default: tracing_service_name = "revad" -``` - -``` -Syntax: disable_http = false | true -Default: disable_http = false -``` - -If disable_http is set to false, revad will not listen on the specified http network and address and -http services will not be exposed by revad. - -``` -Syntax: disable_grpc = false | true -Default: disable_grpc = false -``` - -If disable_grpc is set to false, revad will not listen on the specified grpc network and address and -grpc services will not be exposed by revad. diff --git a/docs/old/config/grpc.md b/docs/old/config/grpc.md deleted file mode 100644 index be53be58f0..0000000000 --- a/docs/old/config/grpc.md +++ /dev/null @@ -1,51 +0,0 @@ -# gRPC functionality - -Example configuration: - -``` -[grpc] -network = tcp -address = 0.0.0.0:9999 -enabled_services = ["storageprovidersvc"] - -[grpc.services.storageprovidersvc] -driver = "local" -mount_path = "/localfs" -mount_id = "123e4567-e89b-12d3-a456-426655440000" -tmp_folder = "/var/tmp" - -[grpc.services.storageprovidersvc.drivers.local] -root = "/var/data" -``` - -## Directives - -``` -Syntax: network = tcp -Default: network = tcp -``` -network specifies what network type to listen for requests. The only supported -network type for the moment is a tcp socket. - -``` -Syntax: address = string -Default: address = "0.0.0.0:9999" -``` - -address specifies the listening address for connections. - -``` -Syntax: enabled_services = [string, string, ...] -Default: enabled_services = [] -``` -enabled_services specifies the grpc services exposed by revad. -The value is a list containing the names of the services. -By default, no service is exposed. - -``` -Syntax: shutdown_deadline = int -Default: shutdown_deadline = 60 -``` -shutdown_deadline specifies how much time in seconds to wait for the -grpc server to shutdown. Once the deadline is reached, ongoing requests that -did not finish will be aborted. diff --git a/docs/old/config/grpc/interceptors/auth.md b/docs/old/config/grpc/interceptors/auth.md deleted file mode 100644 index 06f11c2c11..0000000000 --- a/docs/old/config/grpc/interceptors/auth.md +++ /dev/null @@ -1,48 +0,0 @@ -# GRPC interceptor: auth - -This interceptor authenticates requests to -GRPC services. - -To enable the interceptor: - -``` -[grpc] -enabled_interceptors = ["auth"] -``` - -Example configuration: - -``` -[grpc.interceptors.auth] -token_manager = "jwt" -#header = "x-access-token" -skip_methods = [ - # allow calls that happen during authentication - "/cs3.gatewayv0alpha.GatewayService/Authenticate", - "/cs3.gatewayv0alpha.GatewayService/WhoAmI", - "/cs3.gatewayv0alpha.GatewayService/GetUser", - "/cs3.gatewayv0alpha.GatewayService/ListAuthProviders", - "/cs3.authregistryv0alpha.AuthRegistryService/ListAuthProviders", - "/cs3.authregistryv0alpha.AuthRegistryService/GetAuthProvider", - "/cs3.authproviderv0alpha.AuthProviderService/Authenticate", - "/cs3.userproviderv0alpha.UserProviderService/GetUser", -] - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" -``` - -## Directives - -``` -Syntax: token_manager = string -Default: token_manager = "jwt" -``` -token_manager specifies the strategy to use verify the access token. -Available token managers shipped with REVA can be consulted at the end of this section. -The default manager is to verify it using JWT. -**The token manager configured for the authentication service and the token manager for -this middleware MUST be the same**. - -TODO: header -TODO: skip_methods diff --git a/docs/old/config/grpc/services/authprovider.md b/docs/old/config/grpc/services/authprovider.md deleted file mode 100644 index 069c88ae59..0000000000 --- a/docs/old/config/grpc/services/authprovider.md +++ /dev/null @@ -1,141 +0,0 @@ -# gRPC Service: authprovider - -To enable the service: - -``` -[grpc] -enabled_services = ["authprovider"] -``` - -Example configuration: - -``` -[grpc.services.authprovider] -auth_manager = "demo" -token_manager = "jwt" -user_manager = "demo" -``` - -## Directives - -``` -Syntax: auth_manager = string -Default: auth_manager = "demo" -``` - -auth_manager specifies the auth driver to use for the authentication service. -Available drivers shipped with REVA can be consulted at the end of this section. -The default driver (demo) is a hardcoded in-memory list of well-known physicists. - -``` -Syntax: token_manager = string -Default: token_manager = "demo" -``` - -token_manager specifies the token driver to use for the authentication service. Available drivers shipped with REVA can be consulted at the end of this section. -The default driver (jwt) forges [JWT](https://tools.ietf.org/html/rfc7519) tokens. - -``` -Syntax: user_manager = string -Default: user_manager = "demo" -``` - -user_manager specifies the user manager to use for obtaining user information -like display names and groups associated to an user. -Available managers shipped with REVA can be consulted at the end of this section. -The default driver (demo) is a hardcoded in-memory catalog of well-known physicists. - -## Auth managers - -### Demo -The demo driver authenticates against a hardcoded in-memory catalog -of well-known physicists. -This is the list of credentials: - -``` -einstein => relativity -marie => radioactivity -richard => superfluidity -``` - -### JSON -The json driver allows using a json file to authenticate users. -TODO: example json config - -### LDAP -The LDAP driver authenticates against an LDAP server. - -Example configuration: - -``` -[grpc.services.authsvc.auth_managers.ldap" -hostname = "example.org" -port = 389 -base_dn = "CN=Users,DC=example,DC=org" -filter = "(&(objectClass=person)(objectClass=user)(cn=%s))" -bind_username = "foo" -bind_password = "bar" -``` - -#### Directives - -``` -Syntax: hostname = string -Default: hostname = "" -``` - -hostname specifies the hostname of the LDAP server. - -``` -Syntax: port = int -Default: port = 389 -``` -port specifies the port of the LDAP server. - -``` -Syntax: base_dn = string -Default: base_dn = "" -``` - -base_dn specifies the Base DN to use to query the LDAP server. - -``` -Syntax: filter = string -Default: filter = "" -``` -filter specifies the LDAP filter to authenticate users. -The filter needs to contains a '%s' placeholder where the username will be set -in the filter. - -``` -Syntax: bind_username = string -Default: bind_username = "" -``` - -bind_username specifies the username to bind agains the LDAP server. - -``` -Syntax: bind_password = string -Default: bind_password = "" -``` - -bind_password specifies the password to use to bind agains the LDAP server. - -## Token managers - -### JWT -The jwt manager forges [JWT](https://tools.ietf.org/html/rfc7519) tokens. - -#### Directives - -``` -Syntax: secret = string -Default: secret = "" -``` -secret specifies the secret to use to sign a JWT token. - -## User managers - -### Demo -The demo manager contains a hard-coded in-memory catalog of user information -of well-known physicists. This manager is to be used with the *demo* auth manager. diff --git a/docs/old/config/grpc/services/storageprovider.md b/docs/old/config/grpc/services/storageprovider.md deleted file mode 100644 index 64e6d11747..0000000000 --- a/docs/old/config/grpc/services/storageprovider.md +++ /dev/null @@ -1,201 +0,0 @@ -# gRPC Service: storageprovider - -To enable the service: - -``` -[grpc] -enabled_services = ["storageprovider"] -``` - -Example configuration: - -``` -[grpc.services.storageprovider] -driver = "local" -mount_path = "/localfs" -mount_id = "123e4567-e89b-12d3-a456-426655440000" -tmp_folder = "/var/tmp" - -[grpc.services.storageprovider.drivers.local] -root = "/var/data" -``` - -## Directives - -``` -Syntax: mount_path = string -Default: mount_path = "" -``` -mount_path specifies where to mount the storage provider -in the global REVA namespace. This directive needs to be specified -to run the service. - -``` -Syntax: mount_id = string -Default: mount_id = "" -``` -mount_id specifies the identifier to append to internal object ids -so they become routable accross the REVA global namespace. This directive -needs to be specified to run the service. - -``` -Syntax: tmp_folder = string -Default: tmp_folder = "/tmp" -``` -tmp_folder specifies where temporary files will be stored -on the local filesystem. The default is to use the -system default for a temporary folder (```echo $TMPDIR```). - -``` -Syntax: driver = string -Default: driver = "local" -``` - -driver specifies the filesystem driver to use for the storage provider. -Available drivers shipped with REVA can be consulted at the end of this section. -The default is to use a local filesystem to store the files. -storageprovidersvc specifies the location of the storage provider. - -## Storage drivers - -### Local filesystem -The local driver stores the files in a local filesytem. - -Example configuration: - -``` -[grpc.services.storageprovidersvc.drivers.local] -root = "/var/data" -``` - -#### Directives - -``` -Syntax: root = string -Default: root = "/tmp" -``` - -root specifies the directory in the local filesystem for storing data. - - -### EOS driver - [CERN Open Storage](http://eos.web.cern.ch/) -The EOS driver stores the files in a remote EOS storage system. - - -Example configuration: - -``` -[grpc.services.storageprovidersvc.drivers.eos] -namespace = "/eos/user/" -master_url = "root://eosuser.example.org" -``` - -#### Directives - -``` -Syntax: namespace = string -Default: namespace = "/eos" -``` -namespace speficies the namespace on the remote EOS -storage system to perform storage operations. - -``` -Syntax: eos_binary = string -Default: eos_binary = "/usr/bin/eos" -``` -eos_binary specifies the location of the eos client binary. - -``` -Syntax: xrdcopy_binary = string -Default: xrdcopy_binary = "/usr/bin/xrdcopy" -``` - -xrdcopy_binary specifies the location of the xrdcopy client binary. - -``` -Syntax: master_url = string -Default: master_url = "root://example.org" -``` -master_url specifies the master EOS MGM url. - -``` -Syntax: slave_url = string -Default: slave_url = "root://example.org" -``` -slave_url specifies the slave EOS MGM url. - -``` -Syntax: cache_directory = string -Default: cache_directory = "/tmp" -``` - -cache_directory specifies where to store temporary files. -The default value is system default for a temporary folder (```echo $TMPDIR```). - -``` -Syntax: show_hidden_sys_files = true | false -Default: show_hidden_sys_files = false -``` - -If show_hidden_sys_files is set to true, system files -used by EOS are exposed to the clients. System files follow the pattern -*.sys.** like version folders (.sys.v#.*) or atomic files (.sys.a#.). - - -``` -Syntax: force_single_user_mode = true | false -Default: force_single_user_mode = false -``` - -If force_single_user_mode is set all EOS command sent to the EOS -storage system will be sent as a single user specified by the *single_username* -directive. This directive is usefull when the access to EOS is done by -web servers like Apache and all the commands run as www-data or apache unix user. - -``` -Syntax: single_username = string -Default: single_username = "" -``` - -single_username specifies the unix account for run EOS commands. - - -### Owncloud data directory -The `owncloud` driver stores the files in a local filesytem using the owncloud data directory layout. Files will be assigned a uuid, stored in extended attributes and cahced via redis. - -Example configuration: - -``` -[grpc.services.storageprovidersvc.drivers.owncloud] -datadirectory = "/data" -``` - -#### Directives - -``` -Syntax: datadirectory = string -Default: datadirectory = "" -``` - -datadirectory specifies the directory in the local filesystem for storing data. - -``` -Syntax: scan = boolean -Default: scan = true -``` - -scan will scan files on the first request to index file ids into the configured redis server - -``` -Syntax: autocreate = boolean -Default: autocreate = true -``` - -autocreate will create the home dir and necessary subfolders for new users - -``` -Syntax: redis = string -Default: redis = ":6379" -``` - -redis is used to store fileid to path mappings \ No newline at end of file diff --git a/docs/old/config/http.md b/docs/old/config/http.md deleted file mode 100644 index 3ea5d06ca6..0000000000 --- a/docs/old/config/http.md +++ /dev/null @@ -1,46 +0,0 @@ -# HTTP functionality - -Example configuration: - -``` -[http] -network = tcp -address = 0.0.0.0:9998 -enabled_services = ["helloworldsvc"] - -[http.services.helloworldsvc] -hello_message = "Ola Mundo!" -``` - -## Directives - -``` -Syntax: network = tcp -Default: network = tcp -``` -network specifies what network type to listen for requests. The only supported -network type for the moment is a tcp socket. - -``` -Syntax: address = string -Default: address = "0.0.0.0:9998" -``` - -address specifies the listening address for connections. - -``` -Syntax: enabled_services = [string, string, ...] -Default: enabled_services = [] -``` -enabled_services specifies the http services exposed by revad. -The value is a list containing the names of the services. -By default, not service is exposed. - -``` -Syntax: enabled_middlewares = [string, string, ...] -Default: enabled_middlewares = ["log", "trace"] -``` -enabled_middlewares specifies the http middlwares used on the -HTTP request->response chain. -The value is a list containing the names of the middlewares. -By default, the log and trace middlewares are enabled. diff --git a/docs/old/config/http/middleware/auth.md b/docs/old/config/http/middleware/auth.md deleted file mode 100644 index c52eec5612..0000000000 --- a/docs/old/config/http/middleware/auth.md +++ /dev/null @@ -1,190 +0,0 @@ -# HTTP Middleware: auth - -This middleware authenticates requests to -HTTP services. - -The logic is as follows: when a requests comes, the token strategy is triggered -to obtain an access token from the request. If a token is found, authenticaton -is not triggered. If a token is not found, the credentials strategy is -triggered to obtain user credentials (basic auth, OpenIDConnect, ...). -Then these credentials are validated against the authentication service -and if they are valid, an access token is obtained. This access token is written -to the response using a token writer strategy (reponse header, response cookie, ...). -Once the access token is obtained either because is set on the request or because -authentication was successful, the token is verified using the token manager -strategy (jwt) to obtain the user context and pass it to outgoing requests. - - -To enable the middleware: - -``` -[http] -enabled_middlewares = ["auth"] -``` - -Example configuration: - -``` -[http.middlewares.auth] -gateway = "localhost:9999" -auth_type = "basic" -credential_strategy = "basic" -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" - -[http.middlewares.auth.token_managers.jwt] -secret = "bar" - -[http.middlewares.auth.token_strategies.header] -header = "X-Access-Token" - -[http.middlewares.auth.token_writers.header] -header = "X-Access-Token" -``` - -## Directives - -``` -Syntax: gateway = string -Default: gateway = "0.0.0.0:9999" -``` -gateway specifies the location of the gateway service. - -``` -Syntax: auth_type = string -Default: auth_type = "" -``` -auth_type specifies the type of authprovider the gateway should look up using the configured authregistry. Must be set (`basic` or `oidc` make sense, but those are arbitrary strings the are just used to do a lookup of the actual authprovider url) - -``` -Syntax: credential_strategy = string -Default: credential_strategy = "basic" -``` -credential_strategy specifies the strategy to use to obtain -user credentials. -Available strategies shipped with REVA can be consulted at the end of this section. -The default strategy is [Basic Auth](https://tools.ietf.org/html/rfc7617). - -``` -Syntax: token_strategy = string -Default: token_strategy = "header" -``` -token_strategy specifies the strategy to use to obtain -the access token from the HTTP request. -Available strategies shipped with REVA can be consulted at the end of this section. -The default strategy is obtain the token from an HTTP header. - -``` -Syntax: token_writer = string -Default: token_writer = "header" -``` -token_writer specifies the strategy to use write the -access token once is obtained to the HTTP response so clients -can re-send it subsequent requests to avoid performing expensive authentication -calls to the authentication service. -Available writer strategies shipped with REVA can be consulted at the end of this section. -The default strategy is write the access token in an HTTP response header. - -``` -Syntax: token_manager = string -Default: token_manager = "jwt" -``` -token_manager specifies the strategy to use verify the access token. -Available token managers shipped with REVA can be consulted at the end of this section. -The default manager is to verify it using JWT. -**The token manager configured for the authentication service and the token manager for -this middleware MUST be the same**. - - -TODO: skip_methods - -## Credential strategies - -### Basic Authentication -This strategy obtains the credentials from Basic Auth. - -To enable the strategy: - -``` -[http.middlewares.auth] -credential_strategy = "basic" -``` - -### OpenID Connect - **Work in Progress** -This strategy obtains the open id connect token as the credentials -that is passed to the authentication service to be verified -agains the configured identity provider public keys. - -To enable the strategy: - -``` -[http.middlewares.auth] -credential_strategy = "oidc" -``` - -## Token strategies - -### Header -This token strategy obtains the access token from an HTTP request header. - -To enable the strategy: - -``` -[http.middlewares.auth] -token_strategy = "header" -``` -#### Directives - -``` -Syntax: header = string -Default: header = "" -``` -header specifies header name that contains the token. - -## Token writers - -### Header -This writer strategy writes the access token to an HTTP response header -specified by tbe **header** directive. - -To enable the strategy: - -``` -[http.middlewares.auth] -token_writer = "header" - -[http.middlewares.auth.token_writers.header] -header = "X-Access-Token" -``` - -#### Directives - -``` -Syntax: header = string -Default: header = "" -``` -header specifies header name to use to write the token. - -## Token managers - -### JWT -This token manager verifies the token using the JWT shared secret. - -To enable the strategy: - -``` -[http.middlewares.auth] -token_manager = "jwt" - -[http.middlewares.auth.token_managers.jwt] -secret = "bar" -``` - -#### Directives - -``` -Syntax: secret = string -Default: secret = "" -``` -secret specifies the shared secret to verify the JWT token. diff --git a/docs/old/config/http/middleware/cors.md b/docs/old/config/http/middleware/cors.md deleted file mode 100644 index 7d4b9da44e..0000000000 --- a/docs/old/config/http/middleware/cors.md +++ /dev/null @@ -1,23 +0,0 @@ -# HTTP Middleware: cors - -The cors middleware takes care of CORS headers. It is needed to allow authenticating users using oidc, which will make cross origin resource POST requests when using the recommended autorization code flow. - -If you hide the idp, phoenix and reva behind a reverse proxy and serve them all from the same domain you may be able to disable it. - -To enable the middleware: - -``` -[http] -enabled_middlewares = ["cors"] -``` - -Example configuration: - -``` -[http.middlewares.cors] -allowed_origins = ["*"] # allow requests from everywhere -allowed_methods = ["OPTIONS", "GET", "PUT", "POST", "DELETE", "MKCOL", "PROPFIND", "PROPPATCH", "MOVE", "COPY", "REPORT", "SEARCH"] -allowed_headers = ["Origin", "Accept", "Depth", "Content-Type", "X-Requested-With", "Authorization", "Ocs-Apirequest", "If-None-Match"] -allow_credentials = true -options_passthrough = false -``` diff --git a/docs/old/config/http/middleware/log.md b/docs/old/config/http/middleware/log.md deleted file mode 100644 index da6373b6d8..0000000000 --- a/docs/old/config/http/middleware/log.md +++ /dev/null @@ -1,3 +0,0 @@ -# HTTP Middleware: log - -The logging middleware is always enabled with the highest priority. It will always receive requests first. \ No newline at end of file diff --git a/docs/old/config/http/services/helloworld.md b/docs/old/config/http/services/helloworld.md deleted file mode 100644 index e9f1e90bcc..0000000000 --- a/docs/old/config/http/services/helloworld.md +++ /dev/null @@ -1,40 +0,0 @@ -# HTTP Service: helloworld - -This service is for demo purposes. -It exposes a single endpoint that renders a -hello message that can be changed in the configuration file. - -To enable the service: - -``` -[http] -enabled_services = ["helloworld"] -``` - -Example configuration: - -``` -[http.services.helloworld] -hello_message = "Ola Mundo!" -``` - -## Directives - -``` -Syntax: prefix = string -Default: prefix = "helloworld" -``` - -`prefix` specifies where the service should be exposed. -For example, if the prefix is "myservice", it will be -reachable at http://localhost:9998/myservice - - -``` -Syntax: message = string -Default: message = "Hello World!" -``` - -`message` defines the message that will be rendered under the -http endpoint configured by the **prefix** directive. - diff --git a/docs/old/config/http/services/ocdav.md b/docs/old/config/http/services/ocdav.md deleted file mode 100644 index dfa597eda2..0000000000 --- a/docs/old/config/http/services/ocdav.md +++ /dev/null @@ -1,52 +0,0 @@ -# HTTP Service: ocdav - -This service exposes an [ownCloud](https://ownlcloud.org/) -WebDAV endpoint. This service allows ownCloud sync clients to connect -to this endpoint to synchronize files against the configured storage provider. -This service also allows to mount the storage provider using a WebDAV mount -from many operative systems, like Finder for MacOS, Network Drive for Windows or -davfs2 on Linux. - -To enable the service: - -``` -[http] -enabled_services = ["ocdav"] -``` - -Example configuration: - -``` -[http.services.ocdav] -prefix = "webdav" -``` - -## Directives - -``` -Syntax: prefix = string -Default: prefix = "webdav" -``` - -prefix specifies where the service should be exposed. -For example, if the prefix is "myservice", it will be -reachable at [http://localhost:9998/myservice](http://localhost:9998/myservice) - - -``` -Syntax: chunk_folder = string -Default: chunk_folder = "/tmp" -``` - -chunk_folder specifies where file chunks will be stored -on the local filesystem. The default is to use the -system default for a temporary folder (```echo $TMPDIR```). - -``` -Syntax: storageprovidersvc = string -Default: storageprovidersvc = 0.0.0.0:9999 -``` - -storageprovidersvc specifies the location of the storage provider. -The ocdavsvc service acts as a protocol translator between WebDAV and -the gRPC CS3 API for StorageProvider. diff --git a/docs/old/config/http/services/prometheus.md b/docs/old/config/http/services/prometheus.md deleted file mode 100644 index 1495988254..0000000000 --- a/docs/old/config/http/services/prometheus.md +++ /dev/null @@ -1,29 +0,0 @@ -# HTTP Service: prometheus - -This service exposes a [Prometheus](https://prometheus.io/) -telemetry endpoint so metrics can be consumed. - -To enable the service: - -``` -[http] -enabled_services = ["prometheus"] -``` - -Example configuration: - -``` -[http.services.prometheus] -prefix = "metrics" -``` - -## Directives - -``` -Syntax: prefix = string -Default: prefix = "metrics" -``` - -prefix specifies where the service should be exposed. -For example, if the prefix is "myservice", it will be -reachable at http://localhost:9998/myservice diff --git a/docs/old/config/log.md b/docs/old/config/log.md deleted file mode 100644 index f1e20a8713..0000000000 --- a/docs/old/config/log.md +++ /dev/null @@ -1,39 +0,0 @@ -# Log functionality - -Example configuration: - -``` -[log] -level = "debug" -mode = "json" -output = "/var/log/revad.log" -``` - -## Directives - -``` -Syntax: level = string -Default: level = "debug" -``` - -`level` defines the log level, eg. "debug", "warn", "info" - -``` -Syntax: output = string -Default: output = "stderr" -``` - -output sets the output for writting logs. The "stdout" and "stderr" strings have special meaning -as they will set the log output to stdout and stderr respectively. revad will create the filename -specified in the directive if it does not exists. revad does not perform any log rotate logic, this task -is delegated to tools like *logrotate(8)* configured by the system administrator. - -``` -Syntax: mode = "dev" | "prod" -Default: mode = "dev" -``` - -mode sets the format for the logs. dev mode sets the output to be consumed by humans on a terminal. -prod mode sets the output format to JSON so it can be parsed by machines and send to central logging systems -like Kibana. - diff --git a/docs/old/controlling-reva.md b/docs/old/controlling-reva.md deleted file mode 100644 index 26824460d2..0000000000 --- a/docs/old/controlling-reva.md +++ /dev/null @@ -1,51 +0,0 @@ -# Controlling REVA - -revad can be controlled with signals. The process ID of the master process is written to the file */var/run/revad.pid* by default. This name may be changed with the *-p* flag: - -``` --p string - pid file (default "/var/run/revad.pid") -``` - -The master process supports the following signals: - -* TERM, INT: fast shutdown -* QUIT: graceful shutdown -* HUP: changing configuration, starting new process with the new configuration, graceful shutdown of old parent processes - -## Changing Configuration - -In order for revad to re-read the configuration file, a HUP signal should be sent to the master process. -The master process forks a new child that checks the configuration file for syntax validity, -then tries to apply new configuration, and inherits listening sockets. -If this fails, it kills itself and the parent process continues to work with old configuration. -If this succeeds, the forked child sends a message to old parent process requesting it to shut down gracefully. -Parent process close listening sockets and continue to service old clients. -After all clients are serviced, old process is shut down. - -Let’s illustrate this by example. Imagine that revad is run on Darwin and the command: - -``` -ps axw -o pid,user,%cpu,command | egrep '(revad|PID)' -``` - -produces the following output: - -``` -PID USER %CPU COMMAND -46011 gonzalhu 0.0 ./revad -c revad.toml -p revad.pid -``` - -If HUP is sent to the master process, the output becomes: - -``` -PID USER %CPU COMMAND -46491 gonzalhu 0.0 ./revad -c revad.toml -p revad.pid -``` - -## Upgrading Executable on the Fly - -In order to upgrade the server executable, the new executable file -should be put in place of an old file first. After that, an HUP signal should be -sent to the master process. - The master process run the new executable file that in turn starts a new child process. diff --git a/docs/old/guides/getting-started.md b/docs/old/guides/getting-started.md deleted file mode 100644 index f20417cfa2..0000000000 --- a/docs/old/guides/getting-started.md +++ /dev/null @@ -1,161 +0,0 @@ -# Getting started with REVA - -This guide assumes that you have REVA already installed in your system. - -## Basic configuration - -``` -$ echo "" > ~/revad.toml -$ revad -c ~/revad.toml -9:20AM INF dev/reva/cmd/revad/main.go:94 > version= commit= branch= go_version= build_date= build_platform= pid=2177 -9:20AM INF dev/reva/cmd/revad/main.go:95 > running on 4 cpus pid=2177 -9:20AM INF dev/reva/cmd/revad/main.go:118 > nothing to do, no grpc/http enabled_services declared in config pid=2177 -``` - -An empty configuration will output those lines, stating that no services have been enabled and therefore the program exists. -Let's change the log output format to JSON. - -``` -$ cat ~/revad.toml -[log] -mode = "json" -``` - -``` -$ revad -c ~/revad.toml -{"level":"info","pid":9355,"time":"2019-10-16T09:22:17+02:00","caller":"/home/gonzalhu/dev/reva/cmd/revad/main.go:94","message":"version= commit= branch= go_version= build_date= build_platform="} -{"level":"info","pid":9355,"time":"2019-10-16T09:22:17+02:00","caller":"/home/gonzalhu/dev/reva/cmd/revad/main.go:95","message":"running on 4 cpus"} -{"level":"info","pid":9355,"time":"2019-10-16T09:22:17+02:00","caller":"/home/gonzalhu/dev/reva/cmd/revad/main.go:118","message":"nothing to do, no grpc/http enabled_services declared in config"} -``` - -REVA by default will use all the available CPU cores, let's change that to use only 50%: - -``` -[core] -max_cpus = "50%" -``` - -``` -$ revad -c ~/revad.toml -9:25AM INF dev/reva/cmd/revad/main.go:94 > version= commit= branch= go_version= build_date= build_platform= pid=19783 -9:25AM INF dev/reva/cmd/revad/main.go:95 > running on 2 cpus pid=19783 -9:25AM INF dev/reva/cmd/revad/main.go:118 > nothing to do, no grpc/http enabled_services declared in config pid=19783 - -``` - - -## HTTP services - -Let's enable the helloworld service: - -``` -$ cat revad.toml -[http] -enabled_services = ["helloworldsvc"] -``` - -``` -$ revad -c ~/revad.toml -9:27AM INF dev/reva/cmd/revad/main.go:94 > version= commit= branch= go_version= build_date= build_platform= pid=24558 -9:27AM INF dev/reva/cmd/revad/main.go:95 > running on 4 cpus pid=24558 -9:27AM INF dev/reva/cmd/revad/grace/grace.go:181 > pidfile saved at: /tmp/gonzalhu/revad-ea51bb72-2d20-403e-a7db-73843e530115.pid pid=24558 pkg=grace -9:27AM INF dev/reva/cmd/revad/httpserver/httpserver.go:233 > http service enabled: helloworldsvc@/ pid=24558 pkg=httpserver -9:27AM INF dev/reva/cmd/revad/httpserver/httpserver.go:134 > http server listening at http://localhost:9998 pid=24558 pkg=httpserver -``` - -When the directive `enabled_services` is declared and the value is not empty, REVA will start an HTTP server with the declared services, in this case, the helloworld service. - -When REVA starts it will create a PID (process ID file), that will contain the PID of the REVA process, this file is needed to do reloads of the service as explained in [Controlling REVA](/controlling-reva.md). If no `-p flag` is specified, REVA will create the PID file in the operating system temporary directory, in this example: `/tmp/gonzalhu/revad-ea51bb72-2d20-403e-a7db-73843e530115.pid`. - -The line `http service enabled: helloworldsvc@/` indicated that the helloworld service has been enabled and it can be reach at the root URL (`/`). - -We can `curl` this endpoint: - -``` -$ curl http://localhost:9998 -Hello World! -``` - -In the log lines of the server we see the result of the HTTP request: - -``` -9:34AM INF dev/reva/cmd/revad/svcs/httpsvcs/handlers/log/log.go:112 > http end="16/Oct/2019:09:34:11 +0200" host=127.0.0.1 method=GET pid=13968 pkg=httpserver proto=HTTP/1.1 size=12 start="16/Oct/2019:09:34:11 +0200" status=200 time_ns=67614 traceid=af56a393712698d362b0939b2caabb72 uri=/ url=/ -``` - -The helloworld service allows to change the message being returned with the `message` directive: - -``` -$ cat revad.toml -[http] -enabled_services = ["helloworldsvc"] - -[http.services.helloworldsvc] -message = "Ola Mundo!" -``` - -## GRPC services - -REVA offers the possibility to expose GRPC services, let's do an example with the GRPC helloworld service: - -``` -$ cat ~/revad.toml -[grpc] -enable_reflection = true # needed to query GRPC services dynamically without having the protobuf definitions. -enabled_services = ["helloworldsvc"] -``` - -``` -$ revad -c ~/revad.toml -9:44AM INF dev/reva/cmd/revad/main.go:94 > version= commit= branch= go_version= build_date= build_platform= pid=13514 -9:44AM INF dev/reva/cmd/revad/main.go:95 > running on 4 cpus pid=13514 -9:44AM INF dev/reva/cmd/revad/grace/grace.go:181 > pidfile saved at: /tmp/gonzalhu/revad-68d20c91-1d3a-4e1c-a2a3-e9216e2f63d5.pid pid=13514 pkg=grace -9:44AM INF dev/reva/cmd/revad/grpcserver/grpcserver.go:177 > grpc service enabled: helloworldsvc pid=13514 pkg=grpcserver -9:44AM INF dev/reva/cmd/revad/grpcserver/grpcserver.go:141 > grpc server listening at tcp:0.0.0.0:9999 pid=13514 pkg=grpcserver -``` - -To query the GRPC endpoint we need another tool, we'll use [grpcurl](https://github.com/fullstorydev/grpcurl), make sure you have it installed. - -We can list the available services: - -``` -$ grpcurl -plaintext localhost:9999 list -grpc.reflection.v1alpha.ServerReflection -revad.helloworld.HelloWorldService -``` - -And we can ask the server the available methods for a service: - -``` -$ grpcurl -plaintext localhost:9999 describe revad.helloworld.HelloWorldService -revad.helloworld.HelloWorldService is a service: -service HelloWorldService { - rpc Hello ( .revad.helloworld.HelloRequest ) returns ( .revad.helloworld.HelloResponse ); -} -``` - -Let's query the method: - -``` -$ grpcurl -plaintext localhost:9999 'revad.helloworld.HelloWorldService/Hello' -{ - "message": "Hello Mr. Nobody" -} - -``` - -The HelloWorldService accepts a message for its Hello method: - -``` -$ grpcurl -plaintext localhost:9999 describe revad.helloworld.HelloRequest -revad.helloworld.HelloRequest is a message: -message HelloRequest { - string name = 1; -} -``` - -``` -$ grpcurl -plaintext -d '{"name": "Alice"}' localhost:9999 'revad.helloworld.HelloWorldService/Hello' -{ - "message": "Hello Alice" -} -``` diff --git a/docs/old/installing-reva.md b/docs/old/installing-reva.md deleted file mode 100644 index 83dbb582b6..0000000000 --- a/docs/old/installing-reva.md +++ /dev/null @@ -1,7 +0,0 @@ -# Installing REVA - -REVA is written in Go and is shipped as a statically compiled single binary. -Releases are available in the [Releases](https://github.com/cs3org/reva/releases) page. - -REVA can also be compiled from source files. While more flexible, this approach may be complex -for a beginner. For more information, see [Building REVA](./building-reva.md). diff --git a/examples/authprovider.toml b/examples/authprovider.toml deleted file mode 100644 index 8e63d4ff97..0000000000 --- a/examples/authprovider.toml +++ /dev/null @@ -1,25 +0,0 @@ -[core] -log_file = "stderr" -log_mode = "dev" -max_cpus = "100%" -disable_http = true - -[log] -level = "debug" -mode = "console" - -[grpc] -network = "tcp" -address = "0.0.0.0:9998" -enabled_services = [ -"authsvc" -] - -[grpc.services.authsvc] -auth_manager = "oidc" - -[grpc.services.authsvc.auth_managers.oidc] -provider = "http://0.0.0.0:10000" -insecure = true -client_id = "phoenix" -client_secret = "foobar" diff --git a/examples/backend.toml b/examples/backend.toml deleted file mode 100644 index 29a8f68f4a..0000000000 --- a/examples/backend.toml +++ /dev/null @@ -1,74 +0,0 @@ -[core] -max_cpus = "2" - -[log] -level = "debug" - -[grpc] -network = "tcp" -address = "0.0.0.0:9999" -enabled_services = ["storageprovidersvc", "authsvc", "storageregistrysvc", "preferencessvc", "usershareprovidersvc"] -enabled_interceptors = ["auth"] - -[grpc.services.usershareprovidersvc] -driver = "memory" - -[grpc.services.storageprovidersvc] -driver = "local" -mount_path = "/" -mount_id = "123e4567-e89b-12d3-a456-426655440000" -# we point to the datagatewaysvc. -data_server_url = "http://localhost:9998/data" - -[grpc.services.storageprovidersvc.available_checksums] -md5 = 100 -unset = 1000 - -[grpc.services.storageprovidersvc.drivers.local] -root = "/var/tmp/reva/data" - -[grpc.services.authsvc] -auth_manager = "demo" -token_manager = "jwt" -user_manager = "demo" - -[grpc.services.authsvc.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[grpc.services.storageregistrysvc] -driver = "static" - -[grpc.services.storageregistrysvc.drivers.static.rules] -"/" = "localhost:9999" -"123e4567-e89b-12d3-a456-426655440000" = "localhost:9999" - -[grpc.interceptors.auth] -token_manager = "jwt" -skip_methods = ["/cs3.authv0alpha.AuthService/GenerateAccessToken", "/cs3.authv0alpha.AuthService/WhoAmI"] - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[http] -address = "0.0.0.0:9998" -enabled_services = ["datasvc"] -enabled_middlewares = ["auth"] - -[http.middlewares.auth] -gatewaysvc = "0.0.0.0:9999" -credential_strategy = "basic" -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" -skip_methods = ["/owncloud/status.php", "/metrics"] - -[http.middlewares.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[http.services.datasvc] -driver = "local" -prefix = "data" -temp_folder = "/var/tmp/" - -[http.services.datasvc.drivers.local] -root = "/var/tmp/reva/data" diff --git a/examples/oidc-provider.toml b/examples/oidc-provider.toml deleted file mode 100644 index 69ca298c2b..0000000000 --- a/examples/oidc-provider.toml +++ /dev/null @@ -1,30 +0,0 @@ -# This oidc-provider.toml config starts an authprovider that uses the oidc introspection endpoint to authenticate requests -# See https://tools.ietf.org/html/rfc7662 for the spec -[core] -log_file = "stderr" -log_mode = "dev" -max_cpus = "100%" -disable_http = true - -[log] -level = "debug" -mode = "console" - -[grpc] -address = "0.0.0.0:9998" -enabled_services = [ - "authprovider" -] - -[grpc.services.authprovider] -auth_manager = "oidc" -userprovidersvc = "http://localhost:10000" - -[grpc.services.authprovider.auth_managers.oidc] -provider = "http://localhost:10000" -insecure = true -# credentials used for the introspection endpoint with basic auth -# also rate limit the endpoint: https://tools.ietf.org/html/rfc7662#section-4 -# TODO(jfd) introduce rate limits -client_id = "reva" -client_secret = "foobar" diff --git a/examples/phoenix.oidc.config.json b/examples/phoenix.oidc.config.json deleted file mode 100644 index 0e122ddabf..0000000000 --- a/examples/phoenix.oidc.config.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "__doc": "install https://github.com/owncloud/ocis-phoenix, then run this with `./ocis-phoenix-testing-linux-amd64 server --http-addr localhost:8300 --config-file phoenix.oidc.config.json --log-level debug`", - "server": "http://localhost:10000", - "theme": "owncloud", - "version": "0.1.0", - "openIdConnect": { - "metadataUrl": "http://localhost:10000/.well-known/openid-configuration", - "authority": "http://localhost:10000", - "client_id": "phoenix", - "response_type": "code", - "scope": "openid profile email" - }, - "apps": [ - "files", - "markdown-editor", - "pdf-viewer" - ] - } diff --git a/examples/separate/frontend.toml b/examples/separate/frontend.toml index b16dac9e33..8aeece11f1 100644 --- a/examples/separate/frontend.toml +++ b/examples/separate/frontend.toml @@ -1,10 +1,14 @@ +[shared] +jwt_secret = "Pive-Fumkiu4" +gatewaysvc = "localhost:19000" + # This frontend.toml config file will start a reva service that: # - serves as the entrypoint for owncloud APIs. # - serves http endpoints on port 20080 -# - /owncloud - ocdav -# - /ocs - ocs -# - /oauth2 - oidcprovider -# - /.well-known - wellknown service to announce openid-configuration +# - / --------------- ocdav +# - /ocs ------------ ocs +# - /oauth2 --------- oidcprovider +# - /.well-known ---- wellknown service to announce openid-configuration # - TODO(diocas): ocm # - authenticates requests using oidc bearer auth and basic auth as fallback # - serves the grpc services on port 18002 @@ -14,74 +18,26 @@ address = "0.0.0.0:20099" [grpc.services.authprovider] auth_manager = "oidc" -[grpc.services.authprovider.auth_managers.oidc] # If you want to use your own openid provider change this config +[grpc.services.authprovider.auth_managers.oidc] issuer = "http://localhost:20080" -[grpc.interceptors.auth] -token_manager = "jwt" - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - [http] address = "0.0.0.0:20080" -[http.middlewares.auth] -gateway = "localhost:19000" -credential_chain = ["basic", "bearer"] -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" - -[http.middlewares.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - [http.middlewares.cors] -allowed_origins = ["*"] -allowed_methods = [ - "OPTIONS", - "GET", - "PUT", - "POST", - "DELETE", - "MKCOL", - "PROPFIND", - "PROPPATCH", - "MOVE", - "COPY", - "REPORT", - "SEARCH" -] -allowed_headers = [ - "Origin", - "Accept", - "Depth", - "Content-Type", - "X-Requested-With", - "Authorization", - "Ocs-Apirequest", - "If-Match", - "If-None-Match", - "Destination", - "Overwrite" -] allow_credentials = true -options_passthrough = false [http.services.wellknown] issuer = "http://localhost:20080" authorization_endpoint = "http://localhost:20080/oauth2/auth" token_endpoint = "http://localhost:20080/oauth2/token" -#jwks_uri = "" revocation_endpoint = "http://localhost:20080/oauth2/auth" introspection_endpoint = "http://localhost:20080/oauth2/introspect" userinfo_endpoint = "http://localhost:20080/oauth2/userinfo" -#end_session_endpoint = [http.services.oidcprovider] prefix = "oauth2" -gateway = "localhost:19000" issuer = "http://localhost:20080" [http.services.oidcprovider.clients.phoenix] @@ -95,16 +51,14 @@ public = true # force PKCS for public clients [http.services.ocdav] # serve ocdav on the root path prefix = "" -chunk_folder = "/var/tmp/revad/chunks" +chunk_folder = "/var/tmp/reva/chunks" # for user lookups -gateway = "localhost:19000" # prefix the path of requests to /dav/files with this namespace # While owncloud has only listed usernames at this endpoint CERN has # been exposing more than just usernames. For owncloud deployments we # can prefix the path to jail the requests to the correct CS3 namespace. # In this deployment we mounted the owncloud storage provider at /oc. It # expects a username as the first path segment. -files_namespace = "/" # currently, only the desktop client will use this endpoint, but only if # the dav.chunking capability is available # TODO implement a path wrapper that rewrites `` into the path @@ -113,10 +67,10 @@ files_namespace = "/" # for eos we need to rewrite the path # TODO strip the username from the path so the CS3 namespace can be mounted # at the files/ endpoint? what about migration? separate reva instance +files_namespace = "/oc" # similar to the dav/files endpoint we can configure a prefix for the old webdav endpoint # we use the old webdav endpoint to present the cs3 namespace -webdav_namespace = "/" # note: this changes the tree that is rendered at remote.php/webdav from the users home to the cs3 namespace # use webdav_namespace = "/home" to use the old namespace that only exposes the users files # this endpoint should not affect the desktop client sync but will present different folders for the other clients: @@ -124,12 +78,7 @@ webdav_namespace = "/" # - the ios ios uses the core.webdav-root capability which points to remote.php/webdav in oc10 # - the oc js sdk is hardcoded to the remote.php/webdav so it will see the new tree # - TODO android? no sync ... but will see different tree - -[http.services.ocs] -# prefix = "ocs" -# for user lookups and sharing -gateway = "localhost:19000" - +webdav_namespace = "/home" # options for the /ocs/v1.php/config endpoint [http.services.ocs.config] @@ -143,26 +92,31 @@ ssl = "false" [http.services.ocs.capabilities.capabilities.core] poll_interval = 60 webdav_root = "remote.php/webdav" + [http.services.ocs.capabilities.capabilities.core.status] installed = true maintenance = false needsDbUpgrade = false -version = "10.0.11.5" -versionstring = "10.0.11" +version = "10.1.0.5" +versionstring = "10.1.0" edition = "community" productname = "reva" hostname = "" + [http.services.ocs.capabilities.capabilities.checksums] supported_types = ["SHA256"] preferred_upload_type = "SHA256" + [http.services.ocs.capabilities.capabilities.files] private_links = false bigfilechunking = false blacklisted_files = [] undelete = true versioning = true + [http.services.ocs.capabilities.capabilities.dav] chunking = "1.0" + [http.services.ocs.capabilities.capabilities.files_sharing] api_enabled = true resharing = true @@ -172,6 +126,7 @@ share_with_group_members_only = true share_with_membership_groups_only = true default_permissions = 22 search_min_length = 3 + [http.services.ocs.capabilities.capabilities.files_sharing.public] enabled = true send_mail = true @@ -179,27 +134,35 @@ social_share = true upload = true multiple = true supports_upload_only = true + [http.services.ocs.capabilities.capabilities.files_sharing.public.password] enforced = true + [http.services.ocs.capabilities.capabilities.files_sharing.public.password.enforced_for] read_only = true read_write = true upload_only = true + [http.services.ocs.capabilities.capabilities.files_sharing.public.expire_date] enabled = true + [http.services.ocs.capabilities.capabilities.files_sharing.user] send_mail = true + [http.services.ocs.capabilities.capabilities.files_sharing.user_enumeration] enabled = true group_members_only = true + [http.services.ocs.capabilities.capabilities.files_sharing.federation] outgoing = true incoming = true + [http.services.ocs.capabilities.capabilities.notifications] endpoints = ["list", "get", "delete"] + [http.services.ocs.capabilities.version] edition = "reva" major = 10 -minor = 0 -micro = 11 -string = "10.0.11" +minor = 1 +micro = 0 +string = "10.1.0" diff --git a/examples/separate/gateway.toml b/examples/separate/gateway.toml index 2a6c9621f0..d101376510 100644 --- a/examples/separate/gateway.toml +++ b/examples/separate/gateway.toml @@ -1,3 +1,7 @@ +[shared] +jwt_secret = "Pive-Fumkiu4" +gatewaysvc = "localhost:19000" + # This gateway.toml config file will start a reva service that: # - serves as a gateway for all requests # - looks up the storageprovider using a storageregistry @@ -8,12 +12,6 @@ [grpc] address = "0.0.0.0:19000" -[grpc.interceptors.auth] -token_manager = "jwt" - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - [grpc.services.gateway] # registries authregistrysvc = "localhost:19000" @@ -31,55 +29,33 @@ commit_share_to_storage_grant = true datagateway = "http://localhost:19001/data" transfer_shared_secret = "replace-me-with-a-transfer-secret" # for direct uploads transfer_expires = 6 # give it a moment -token_manager = "jwt" - -[grpc.services.gateway.token_managers.jwt] -secret = "Pive-Fumkiu4" +#disable_home_creation_on_login = true [grpc.services.authregistry] driver = "static" [grpc.services.authregistry.drivers.static.rules] -# started with the users.toml -basic = "localhost:18000" -# started with the frontend.toml -bearer = "localhost:20099" +basic = "localhost:18000" # started with the users.toml +bearer = "localhost:20099" # started with the frontend.toml [grpc.services.storageregistry] driver = "static" -[grpc.services.storageregistry.drivers.static.rules] -# this is the list of namespaces that build the cs3 namespace -# - every storage as mounted in the root +[grpc.services.storageregistry.drivers.static] +home_provider = "/home" +[grpc.services.storageregistry.drivers.static.rules] # mount a home storage provider that uses a context based path wrapper # to jail users into their home dir "/home" = "localhost:12000" -# the home storage cannot be access by fileid, because it is 'virtual' -# check the storage-home.toml. it uses the same storageid, so id based requests are routed to the next storage -# mount a storage provider without a path wrapper for direct access to files +# mount a storage provider without a path wrapper for direct access to users. "/oc" = "localhost:11000" "123e4567-e89b-12d3-a456-426655440000" = "localhost:11000" -"/" = "localhost:11100" -"123e4567-e89b-12d3-a456-426655440001" = "localhost:11100" - # another mount point might be "/projects/" [http] address = "0.0.0.0:19001" [http.services.datagateway] -prefix = "data" -gateway = "" # TODO not needed? transfer_shared_secret = "replace-me-with-a-transfer-secret" - -[http.middlewares.auth] -gatewaysvc = "0.0.0.0:19000" -credential_chain = ["basic", "bearer"] -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" - -[http.middlewares.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" diff --git a/examples/separate/shares.toml b/examples/separate/shares.toml index 2c073e5901..2da5b8ee65 100644 --- a/examples/separate/shares.toml +++ b/examples/separate/shares.toml @@ -1,17 +1,13 @@ +[shared] +jwt_secret = "Pive-Fumkiu4" + # GRPC: # - serves user and public link shares [grpc] address = "0.0.0.0:17000" -[grpc.interceptors.auth] -token_manager = "jwt" - [grpc.services.usershareprovider] driver = "memory" [grpc.services.publicshareprovider] driver = "memory" - - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" diff --git a/examples/separate/storage-home.toml b/examples/separate/storage-home.toml index fff7457533..9c93ad1888 100644 --- a/examples/separate/storage-home.toml +++ b/examples/separate/storage-home.toml @@ -1,4 +1,8 @@ # This storage-home.toml config file will start a reva service that: +[shared] +jwt_secret = "Pive-Fumkiu4" +gatewaysvc = "localhost:19000" + # - authenticates grpc storage provider requests using the internal jwt token # - authenticates http upload and download requests requests using basic auth # - serves the home storage provider on grpc port 12000 @@ -9,55 +13,31 @@ # their home directory [grpc] -network = "tcp" address = "0.0.0.0:12000" -[grpc.interceptors.auth] -token_manager = "jwt" - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - # This is a storage proider that grants direct acces to the wrapped storage +# TODO same storage id as the /oc/ storage provider +# if we have an id, we can directly go to that storage, no need to wrap paths +# we have a locally running dataprovider +# this is where clients can find it +# the context path wrapper reads tho username from the context and prefixes the relative storage path with it [grpc.services.storageprovider] driver = "owncloud" -# the context path wrapper reads tho username from the context and prefixes the relative storage path with it -path_wrapper = "context" mount_path = "/home" -# TODO same storage id as the /oc/ storage provider -# if we have an id, we can directly go to that storage, no need to wrap paths mount_id = "123e4567-e89b-12d3-a456-426655440000" -# we have a locally running dataprovider expose_data_server = true -# this is where clients can find it +path_wrapper = "context" data_server_url = "http://localhost:12001/data" - -[grpc.services.storageprovider.available_checksums] -md5 = 100 -unset = 1000 +enable_home_creation = true [grpc.services.storageprovider.drivers.owncloud] datadirectory = "/var/tmp/reva/data" -[grpc.services.storageprovider.path_wrappers.context] -prefix = "" - [http] address = "0.0.0.0:12001" -[http.middlewares.auth] -gatewaysvc = "localhost:19000" -credential_chain = ["basic", "bearer"] -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" - -[http.middlewares.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - [http.services.dataprovider] driver = "owncloud" -prefix = "data" temp_folder = "/var/tmp/" [http.services.dataprovider.drivers.owncloud] diff --git a/examples/separate/storage-oc.toml b/examples/separate/storage-oc.toml index 046d9ebef2..2ae464fe18 100644 --- a/examples/separate/storage-oc.toml +++ b/examples/separate/storage-oc.toml @@ -1,55 +1,34 @@ # This storage.toml config file will start a reva service that: +[shared] +jwt_secret = "Pive-Fumkiu4" +gatewaysvc = "localhost:19000" + # - authenticates grpc storage provider requests using the internal jwt token # - authenticates http upload and download requests requests using basic auth # - serves the storage provider on grpc port 11000 # - serves http dataprovider for this storage on port 11001 # - /data - dataprovider: file up and download [grpc] -network = "tcp" address = "0.0.0.0:11000" -[grpc.interceptors.auth] -token_manager = "jwt" - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - # This is a storage proider that grants direct acces to the wrapped storage +# we have a locally running dataprovider [grpc.services.storageprovider] driver = "owncloud" mount_path = "/oc" mount_id = "123e4567-e89b-12d3-a456-426655440000" -# we have a locally running dataprovider expose_data_server = true -# this is where clients can find it data_server_url = "http://localhost:11001/data" -[grpc.services.storageprovider.available_checksums] -md5 = 100 -unset = 1000 - [grpc.services.storageprovider.drivers.owncloud] datadirectory = "/var/tmp/reva/data" [http] address = "0.0.0.0:11001" -enabled_services = ["dataprovider"] -enabled_middlewares = ["auth"] - -[http.middlewares.auth] -gatewaysvc = "localhost:19000" -credential_chain = ["basic", "bearer"] -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" - -[http.middlewares.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" [http.services.dataprovider] driver = "owncloud" -prefix = "data" temp_folder = "/var/tmp/" [http.services.dataprovider.drivers.owncloud] diff --git a/examples/separate/storage-root.toml b/examples/separate/storage-root.toml deleted file mode 100644 index 53d06c489b..0000000000 --- a/examples/separate/storage-root.toml +++ /dev/null @@ -1,40 +0,0 @@ -# This storage-root.toml config file will start a reva service that: -# - authenticates grpc storage provider requests using the internal jwt token -# - serves a root storage provider on grpc port 11100 - -# it is used to render the root namespace. you need to create a folder -# layout in "/var/tmp/reva/root" that matches the storage registry: -# tree /var/tmp/reva/root should give for this example -# /var/tmp/reva/root -# ├── home -# └── oc -# that will allow you to list the existing namespaces. -# TODO either make the gateway return a proper ListCollection for the root, -# TODO or implement a virtual storage that implements this -[grpc] -network = "tcp" -address = "0.0.0.0:11100" - -[grpc.interceptors.auth] -token_manager = "jwt" - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - -# This is a storage proider that grants direct acces to the wrapped storage -[grpc.services.storageprovider] -driver = "local" -mount_path = "/" -# if we have an id, we can directly go to that storage, no need to wrap paths -mount_id = "123e4567-e89b-12d3-a456-426655440001" - -[grpc.services.storageprovider.available_checksums] -md5 = 100 -unset = 1000 - -[grpc.services.storageprovider.drivers.local] -root = "/var/tmp/reva/root" - -[grpc.services.storageprovider.path_wrappers.context] -prefix = "" - diff --git a/examples/separate/users.toml b/examples/separate/users.toml index 3a4accd235..7b24885c56 100644 --- a/examples/separate/users.toml +++ b/examples/separate/users.toml @@ -1,16 +1,12 @@ +[shared] +jwt_secret = "Pive-Fumkiu4" + # This users.toml config file will start a reva service that: # - handles user metadata and user preferences # - serves the grpc services on port 18000 [grpc] -network = "tcp" address = "0.0.0.0:18000" -[grpc.interceptors.auth] -token_manager = "jwt" - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - [grpc.services.authprovider] auth_manager = "json" diff --git a/examples/standalone.oidc.toml b/examples/standalone.oidc.toml deleted file mode 100644 index cfcaee2c95..0000000000 --- a/examples/standalone.oidc.toml +++ /dev/null @@ -1,222 +0,0 @@ -# This standalone.oidc.toml config file will start a reva service that: -# - authenticates requests using openid connect -# - serves http requests on port 10000 -# - / - ocdav: owncloud webdav api -# - /data - dataprovider: file up and download -# - /oauth2 - an openid connect provider implementation for development -# - /.well-known - used for openid connect discovery -# - /metrics - prometheus: metrics -# - serves grpc requests on port 9999 -# - authprovider - provides basic auth -# - storageprovider - handles storage metadata -# - usershareprovider - provides user shares -# - userprovider - provides user matadata (used to look up email, displayname etc after a login) -# - preferences - provides user preferences -# - gateway: to lookup services and authenticate requests -# - authregistry - used by the gateway to look up auth providers -# - storageregistry - used by the gateway to look up storage providers - -[core] -max_cpus = "2" # defaults to runtime.NumCPU() -#tracing_enabled = false -#tracing_endpoint = "localhost:6831" -#tracing_collector = "http://localhost:14268/api/traces" -#tracing_service_name = "revad" - -[log] -level = "debug" -#mode = "console" # "console" or "json" -#output = "./standalone.log" - -[http] -#network = "tcp" -# allow access from any host, not only localhost -address = "0.0.0.0:10000" # "localhost:9998" -enabled_services = ["dataprovider", "ocdav", "prometheus", "wellknown", "oidcprovider", "ocs"] -enabled_middlewares = ["cors", "auth"] - -[http.middlewares.auth] -gateway = "localhost:9999" -auth_type = "oidc" # used to look up the authprovider in the authregistry by the gateway -credential_strategy = "oidc" -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" -skip_methods = [ - "/favicon.ico", - "/status.php", - "/oauth2", - "/oauth2/auth", - "/oauth2/token", - # TODO protect the introspection endpoint from external requests. - # should only be reachable by internal services, which is why the - # oidc-provider.toml has clientid and secret that are used for a basic auth - "/oauth2/introspect", - "/oauth2/userinfo", - "/oauth2/sessions", - "/.well-known/openid-configuration", - "/metrics" -] - -[http.middlewares.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[http.middlewares.cors] -allowed_origins = ["*"] -allowed_methods = ["OPTIONS", "GET", "PUT", "POST", "DELETE", "MKCOL", "PROPFIND", "PROPPATCH", "MOVE", "COPY", "REPORT", "SEARCH"] -allowed_headers = ["Origin", "Accept", "Depth", "Content-Type", "X-Requested-With", "Authorization", "Ocs-Apirequest", "If-None-Match"] -allow_credentials = true -options_passthrough = false - -[http.services.wellknown] -issuer = "http://localhost:10000" -authorization_endpoint = "http://localhost:10000/oauth2/auth" -token_endpoint = "http://localhost:10000/oauth2/token" -#jwks_uri = "" -revocation_endpoint = "http://localhost:10000/oauth2/auth" -introspection_endpoint = "http://localhost:10000/oauth2/introspect" -userinfo_endpoint = "http://localhost:10000/oauth2/userinfo" -#end_session_endpoint = - -[http.services.oidcprovider] -prefix = "oauth2" -gateway = "localhost:9999" -auth_type = "basic" -issuer = "http://localhost:10000" - -[http.services.oidcprovider.clients.phoenix] -id = "phoenix" -redirect_uris = ["http://localhost:8300/oidc-callback.html", "http://localhost:8300/"] -grant_types = ["implicit", "refresh_token", "authorization_code", "password", "client_credentials"] -response_types = ["code"] # use authorization code flow, see https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead for details -scopes = ["openid", "profile", "email", "offline"] -public = true # force PKCS for public clients - -[http.services.oidcprovider.clients.reva] -id = "reva" -grant_types = ["implicit", "refresh_token", "authorization_code", "password", "client_credentials"] -response_types = ["code"] # use authorization code flow -# private clients can use a secret -client_secret = "$2a$10$IxMdI6d.LIRZPpSfEwNoeu4rY3FhDREsxFJXikcgdRRAStxUlsuEO" # = "foobar" -scopes = ["openid", "profile", "email", "offline"] - -# to debug the oidc provider allow https://oidcdebugger.com -[http.services.oidcprovider.clients.oidcdebugger] -id = "oidcdebugger" -redirect_uris = ["https://oidcdebugger.com/debug"] -grant_types = ["implicit", "refresh_token", "authorization_code", "password", "client_credentials"] -response_types = ["id_token token", "code"] -client_secret = "$2a$10$IxMdI6d.LIRZPpSfEwNoeu4rY3FhDREsxFJXikcgdRRAStxUlsuEO" # = "foobar" -scopes = ["openid", "profile", "email", "offline"] - -[http.services.dataprovider] -driver = "local" -prefix = "data" -tmp_folder = "/var/tmp/" - -[http.services.dataprovider.drivers.local] -root = "/var/tmp/reva/data" - -[http.services.ocdav] -prefix = "" -chunk_folder = "/var/tmp/revad/chunks" -gateway = "localhost:9999" - -[grpc] -#network = "tcp" -# allow access from any host, not only localhost -address = "0.0.0.0:9999" # "localhost:9999" -enabled_services = [ - "authprovider", # provides basic auth - "storageprovider", # handles storage metadata - "usershareprovider", # provides user shares - "userprovider", # provides user matadata (used to look up email, displayname etc after a login) - "preferences", # provides user preferences - "gateway", # to lookup services and authenticate requests - "authregistry", # used by the gateway to look up auth providers - "storageregistry", # used by the gateway to look up storage providers -] -enabled_interceptors = ["auth"] - -[grpc.interceptors.auth] -token_manager = "jwt" -#header = "x-access-token" -skip_methods = [ - # we need to allow calls that happen during authentication - "/cs3.gateway.v1beta1.GatewayAPI/Authenticate", - "/cs3.gateway.v1beta1.GatewayAPI/WhoAmI", - "/cs3.gateway.v1beta1.GatewayAPI/GetUser", - "/cs3.gateway.v1beta1.GatewayAPI/ListAuthProviders", - "/cs3.auth.registry.v1beta1.RegistryAPI/ListAuthProviders", - "/cs3.auth.registry.v1beta1.RegistryAPI/GetAuthProvider", - "/cs3.auth.provider.v1beta1.ProviderAPI/Authenticate", - "/cs3.identity.user.v1beta1.UserAPI/GetUser", -] - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[grpc.services.userprovider] -driver = "json" - -[grpc.services.userprovider.drivers.json] -users = "./examples/users.demo.json" - -[grpc.services.authregistry] -driver = "static" - -[grpc.services.authregistry.drivers.static.rules] -basic = "localhost:9999" -# needs to be started as a second service using the oidc-provider.toml -oidc = "localhost:9998" - -[grpc.services.usershareprovider] -driver = "memory" - -[grpc.services.storageprovider] -driver = "local" -mount_path = "/" -mount_id = "123e4567-e89b-12d3-a456-426655440000" -data_server_url = "http://localhost:10000/data" -expose_data_server = true - -[grpc.services.storageprovider.available_checksums] -md5 = 100 -unset = 1000 - -[grpc.services.storageprovider.drivers.local] -root = "/var/tmp/reva/data" - -# cannot be started in the same process because it has to serve the same -# "/cs3.auth.provider.v1beta1.ProviderAPI/Authenticate" request as the oidcprovider -[grpc.services.authprovider] -auth_manager = "json" -userprovidersvc = "localhost:9999" - -[grpc.services.authprovider.auth_managers.json] -users = "./examples/users.demo.json" - -[grpc.services.storageregistry] -driver = "static" - -[grpc.services.storageregistry.drivers.static.rules] -"/" = "localhost:9999" -"123e4567-e89b-12d3-a456-426655440000" = "localhost:9999" - -[grpc.services.gateway] -authregistrysvc = "localhost:9999" -storageregistrysvc = "localhost:9999" -appregistrysvc = "localhost:9999" -preferencessvc = "localhost:9999" -usershareprovidersvc = "localhost:9999" -publicshareprovidersvc = "localhost:9999" -ocmshareprovidersvc = "localhost:9999" -userprovidersvc = "localhost:9999" -commit_share_to_storage_grant = true -datagateway = "http://localhost:10000/data" -transfer_shared_secret = "replace-me-with-a-transfer-secret" -transfer_expires = 6 # give it a moment -token_manager = "jwt" - -[grpc.services.gateway.token_managers.jwt] -secret = "Pive-Fumkiu4" diff --git a/examples/standalone.toml b/examples/standalone.toml deleted file mode 100644 index 9d5a119d5e..0000000000 --- a/examples/standalone.toml +++ /dev/null @@ -1,166 +0,0 @@ -# This standalone.toml config file will start a reva service that: -# - authenticates requests using basic auth -# - serves http requests on port 10000 -# - /owncloud - ocdav: owncloud webdav api -# - /data - dataprovider: file up and download -# - /metrics - prometheus: metrics -# - serves grpc requests on port 9999 -# - authprovider - provides basic auth -# - storageprovider - handles storage metadata -# - usershareprovider - provides user shares -# - userprovider - provides user matadata (used to look up email, displayname etc after a login) -# - preferences - provides user preferences -# - gateway: to lookup services and authenticate requests -# - authregistry - used by the gateway to look up auth providers -# - storageregistry - used by the gateway to look up storage providers - -[core] -max_cpus = "2" # defaults to runtime.NumCPU() -#tracing_enabled = false -#tracing_endpoint = "localhost:6831" -#tracing_collector = "http://localhost:14268/api/traces" -#tracing_service_name = "revad" - -[log] -level = "debug" -#mode = "console" # "console" or "json" -#output = "./standalone.log" - -[http] -#network = "tcp" -# allow access from any host, not only localhost -address = "0.0.0.0:10000" # "localhost:9998" -enabled_services = ["ocdav", "dataprovider", "prometheus"] # [] -enabled_middlewares = ["cors", "auth"] # [] - -[http.middlewares.auth] -gateway = "localhost:9999" -auth_type = "basic" # used to look up the authprovider in the authregistry by the gateway -credential_strategy = "basic" -token_strategy = "header" -token_writer = "header" -token_manager = "jwt" -skip_methods = ["/owncloud/status.php", "/metrics"] # [] - -[http.middlewares.auth.token_strategies.header] -header = "X-Access-Token" -[http.middlewares.auth.token_writers.header] -header = "X-Access-Token" - -[http.middlewares.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[http.services.dataprovider] -driver = "local" -prefix = "data" -temp_folder = "/var/tmp/" - -[http.services.dataprovider.drivers.local] -root = "/var/tmp/reva/data" - -[http.services.ocdav] -prefix = "owncloud" -chunk_folder = "/var/tmp/revad/chunks" -gateway = "localhost:9999" - -[grpc] -#network = "tcp" -# allow access from any host, not only localhost -address = "0.0.0.0:9999" # "localhost:9999" -enabled_services = [ - "authprovider", # provides basic auth - "storageprovider", # handles storage metadata - "usershareprovider", # provides user shares - "userprovider", # provides user matadata (used to look up email, displayname etc after a login) - "preferences", # provides user preferences - "gateway", # to lookup services and authenticate requests - "authregistry", # used by the gateway to look up auth providers - "storageregistry", # used by the gateway to look up storage providers -] -enabled_interceptors = ["auth"] - -[grpc.interceptors.auth] -token_manager = "jwt" -#header = "x-access-token" -skip_methods = [ - # we need to allow calls that happen during authentication - "/cs3.gateway.v1beta1.GatewayAPI/Authenticate", - "/cs3.gateway.v1beta1.GatewayAPI/WhoAmI", - "/cs3.gateway.v1beta1.GatewayAPI/GetUser", - "/cs3.gateway.v1beta1.GatewayAPI/ListAuthProviders", - "/cs3.auth.registry.v1beta1.RegistryAPI/ListAuthProviders", - "/cs3.auth.registry.v1beta1.RegistryAPI/GetAuthProvider", - "/cs3.auth.provider.v1beta1.ProviderAPI/Authenticate", - "/cs3.identity.user.v1beta1.UserAPI/GetUser", -] - -[grpc.interceptors.auth.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[grpc.services.usershareprovider] -driver = "memory" - -[grpc.services.storageprovider] -driver = "local" -mount_path = "/" -mount_id = "123e4567-e89b-12d3-a456-426655440000" -data_server_url = "http://localhost:10000/data" -# make the gateway return the storageprovider reported by the storageprovider -expose_data_server = true - -[grpc.services.storageprovider.available_checksums] -md5 = 100 -unset = 1000 - -[grpc.services.storageprovider.drivers.local] -root = "/var/tmp/reva/data" - -# the authprovider handles basic auth -[grpc.services.authprovider] -auth_manager = "json" -userprovidersvc = "localhost:9999" - -[grpc.services.authprovider.auth_managers.json] -users = "./examples/users.demo.json" - -[grpc.services.authprovider.token_managers.jwt] -secret = "Pive-Fumkiu4" - -[grpc.services.userprovider] -driver = "json" - -[grpc.services.userprovider.drivers.json] -users = "./examples/users.demo.json" - -[grpc.services.authregistry] -driver = "static" - -[grpc.services.authregistry.drivers.static.rules] -basic = "localhost:9999" -oidc = "localhost:9998" - -[grpc.services.storageregistry] -driver = "static" - -[grpc.services.storageregistry.drivers.static.rules] -"/" = "localhost:9999" -"123e4567-e89b-12d3-a456-426655440000" = "localhost:9999" - - -[grpc.services.gateway] -authregistrysvc = "localhost:9999" -storageregistrysvc = "localhost:9999" -appregistrysvc = "localhost:9999" -preferencessvc = "localhost:9999" -usershareprovidersvc = "localhost:9999" -publicshareprovidersvc = "localhost:9999" -ocmshareprovidersvc = "localhost:9999" -userprovidersvc = "localhost:9999" -commit_share_to_storage_grant = true -datagateway = "http://localhost:10000/data" -transfer_shared_secret = "replace-me-with-a-transfer-secret" -transfer_expires = 6 # give it a moment -token_manager = "jwt" - -[grpc.services.gateway.token_managers.jwt] -secret = "Pive-Fumkiu4" diff --git a/examples/users.demo.json b/examples/users.demo.json deleted file mode 100644 index 9b3e5f3ef3..0000000000 --- a/examples/users.demo.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "id": { - "opaque_id": "4c510ada-c86b-4815-8820-42cdf82c3d51", - "idp": "http://localhost:10000" - }, - "username": "einstein", - "secret": "relativity", - "mail": "einstein@example.org", - "display_name": "Albert Einstein", - "groups": ["sailing-lovers", "violin-haters", "physics-lovers"] - }, - { - "id": { - "opaque_id": "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", - "idp": "http://localhost:10000" - }, - "username": "marie", - "secret": "radioactivity", - "mail": "marie@example.org", - "display_name": "Marie Curie", - "groups": ["radium-lovers", "polonium-lovers", "physics-lovers"] - }, - { - "id": { - "opaque_id": "932b4540-8d16-481e-8ef4-588e4b6b151c", - "idp": "http://localhost:10000" - }, - "username": "richard", - "secret": "superfluidity", - "mail": "richard@example.org", - "display_name": "Richard Feynman", - "groups": ["quantum-lovers", "philosophy-haters", "physics-lovers"] - } -] diff --git a/examples/users.oidc.json b/examples/users.oidc.json deleted file mode 100644 index db6e889417..0000000000 --- a/examples/users.oidc.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "id": { - "opaque_id": "c6e5995d6c7fa1986b830b78b478e6c2", - "idp": "localhost:10000" - }, - "username": "aaliyah_abernathy", - "secret": "secret", - "mail": "aaliyah_abernathy@owncloudqa.com", - "display_name": "Aaliyah Abernathy" - }, - { - "id": { - "opaque_id": "9fb5f8d212cbf3fc55f1bf67d97ed05d", - "idp": "localhost:10000" - }, - "username": "aaliyah_adams", - "secret": "secret", - "mail": "aaliyah_adams@owncloudqa.com", - "display_name": "Aaliyah Adams" - }, - { - "id": { - "opaque_id": "a84075b398fe6a0aee1155f8ead13331", - "idp": "localhost:10000" - }, - "username": "aaliyah_anderson", - "secret": "secret", - "mail": "aaliyah_anderson@owncloudqa.com", - "display_name": "Aaliyah Anderson" - } -] diff --git a/go.mod b/go.mod index 4d2f8e8504..14f3130b95 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/aws/aws-sdk-go v1.26.7 github.com/cheggaaa/pb v1.0.28 github.com/coreos/go-oidc v2.1.0+incompatible - github.com/cs3org/go-cs3apis v0.0.0-20191128165347-19746c015c83 + github.com/cs3org/go-cs3apis v0.0.0-20200115100126-824a5f718250 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/fatih/color v1.7.0 // indirect github.com/go-openapi/strfmt v0.19.2 // indirect @@ -24,6 +24,7 @@ require ( github.com/pkg/errors v0.8.1 github.com/pkg/xattr v0.4.1 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect + github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 // indirect github.com/rs/cors v1.7.0 github.com/rs/zerolog v1.17.2 go.opencensus.io v0.22.1 diff --git a/go.sum b/go.sum index ad37ea0156..3a1f845b9f 100644 --- a/go.sum +++ b/go.sum @@ -1,35 +1,19 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -contrib.go.opencensus.io/exporter/jaeger v0.1.0 h1:WNc9HbA38xEQmsI40Tjd/MNU/g8byN2Of7lwIjv0Jdc= -contrib.go.opencensus.io/exporter/jaeger v0.1.0/go.mod h1:VYianECmuFPwU37O699Vc1GOcy+y8kOsfaxHRImmjbA= contrib.go.opencensus.io/exporter/jaeger v0.2.0 h1:nhTv/Ry3lGmqbJ/JGvCjWxBl5ozRfqo86Ngz59UAlfk= contrib.go.opencensus.io/exporter/jaeger v0.2.0/go.mod h1:ukdzwIYYHgZ7QYtwVFQUjiT28BJHiMhTERo32s6qVgM= contrib.go.opencensus.io/exporter/prometheus v0.1.0 h1:SByaIoWwNgMdPSgl5sMqM2KDE5H/ukPWBRo314xiDvg= contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.25.41 h1:/hj7nZ0586wFqpwjNpzWiUTwtaMgxAZNZKHay80MdXw= -github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.26.2 h1:MzYLmCeny4bMQcAbYcucIduVZKp0sEf1eRLvHpKI5Is= -github.com/aws/aws-sdk-go v1.26.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.26.3 h1:szQdfJcUBAhQT0zZEx4sxoDuWb7iScoucxCiVxDmaBk= -github.com/aws/aws-sdk-go v1.26.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.26.4 h1:vQ1XmULJriCx8QTmvtEl511rskbZeTkr0xq59ky3kfI= -github.com/aws/aws-sdk-go v1.26.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.26.6 h1:LinjO5+t9K/TyrZbSU1BaVJ5wIG3DlX5SffZ32Eg+kU= -github.com/aws/aws-sdk-go v1.26.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.26.7 h1:ObjEnmzvSdYy8KVd3me7v/UMyCn81inLy2SyoIPoBkg= github.com/aws/aws-sdk-go v1.26.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= @@ -41,23 +25,22 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/cs3org/go-cs3apis v0.0.0-20191128165347-19746c015c83 h1:9bcp1jc6+36XUfuOae/w0BVrbzeVKBp/OqhTfCal40U= -github.com/cs3org/go-cs3apis v0.0.0-20191128165347-19746c015c83/go.mod h1:IsVGyZrOLUQD48JIhlM/xb3Vz6He5o2+W0ZTfUGY+IU= +github.com/cs3org/go-cs3apis v0.0.0-20200113082535-e58b99ae8f80 h1:ui+ztsFshmOv1yR3HRPaDRz1J/G6VQLd0ZUaBG33fWU= +github.com/cs3org/go-cs3apis v0.0.0-20200113082535-e58b99ae8f80/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20200113170445-f5790f408edc h1:qY/nHxpK3mJHkmWveEpwQCWHeNBjlDgk+o4t/5QeZM4= +github.com/cs3org/go-cs3apis v0.0.0-20200113170445-f5790f408edc/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20200115100126-824a5f718250 h1:N/WWs9OegcgFlsUo7/iahxq+e3luhZKu0B8wLrWBsTQ= +github.com/cs3org/go-cs3apis v0.0.0-20200115100126-824a5f718250/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/elazarl/goproxy v0.0.0-20181003060214-f58a169a71a5/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= @@ -69,8 +52,6 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= @@ -81,7 +62,6 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -98,14 +78,12 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -125,11 +103,6 @@ github.com/moul/http2curl v0.0.0-20170919181001-9ac6cf4d929b/go.mod h1:8UbvGypXm github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oleiade/reflections v1.0.0 h1:0ir4pc6v8/PJ0yw5AEtMddfXpWBXg9cnG7SgSoJuCgY= github.com/oleiade/reflections v1.0.0/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/openzipkin/zipkin-go v0.1.6 h1:yXiysv1CSK7Q5yjGy1710zZGnsbMUIjluWBxtLXHPBo= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/ory/fosite v0.30.2 h1:1HQZPXQ+PdeIe27H9Fjfvxem5uxVc/diIwUDk5XTEM4= github.com/ory/fosite v0.30.2/go.mod h1:Lq9qQ9Sl6mcea2Tt8J7PU+wUeFYPZ+vg7N3zPVKGbN8= github.com/ory/go-convenience v0.1.0 h1:zouLKfF2GoSGnJwGq+PE/nJAE6dj2Zj5QlTgmMTsTS8= @@ -137,7 +110,6 @@ github.com/ory/go-convenience v0.1.0/go.mod h1:uEY/a60PL5c12nYz4V5cHY03IBmwIAEm8 github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -166,7 +138,6 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nL github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -190,7 +161,6 @@ github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= @@ -206,7 +176,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -232,10 +201,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181021155630-eda9bb28ed51/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190415081028-16da32be82c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -246,7 +213,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -255,9 +221,6 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.3.2 h1:iTp+3yyl/KOtxa/d1/JUE0GGSoR6FuW5udver22iwpw= -google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0 h1:KKgc1aqhV8wDPbDzlDtpvyjZFY3vjz85FP7p4wcQUyI= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -272,13 +235,10 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8 google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -288,14 +248,11 @@ gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUy gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU= gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= gopkg.in/square/go-jose.v2 v2.1.9/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/grpc/interceptors/auth/auth.go b/internal/grpc/interceptors/auth/auth.go index 162fc6f104..2dea0604f5 100644 --- a/internal/grpc/interceptors/auth/auth.go +++ b/internal/grpc/interceptors/auth/auth.go @@ -36,14 +36,9 @@ import ( "google.golang.org/grpc/status" ) -const ( - defaultHeader = "x-access-token" -) - type config struct { // TODO(labkode): access a map is more performant as uri as fixed in length // for SkipMethods. - Header string `mapstructure:"header"` TokenManager string `mapstructure:"token_manager"` TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` } @@ -66,14 +61,10 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI return nil, err } - if conf.Header == "" { - conf.Header = defaultHeader - } - if conf.TokenManager == "" { - err := errors.New("auth: token manager is not configured for interceptor") - return nil, err + conf.TokenManager = "jwt" } + h, ok := tokenmgr.NewFuncs[conf.TokenManager] if !ok { return nil, errors.New("auth: token manager does not exist: " + conf.TokenManager) @@ -97,10 +88,10 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI span.AddAttributes(trace.BoolAttribute("auth_enabled", true)) - tkn, _ := token.ContextGetToken(ctx) + tkn, ok := token.ContextGetToken(ctx) - if tkn == "" { - log.Warn().Msg("access token not found") + if !ok || tkn == "" { + log.Warn().Msg("access token not found or empty") return nil, status.Errorf(codes.Unauthenticated, "auth: core access token not found") } @@ -134,8 +125,8 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe return nil, err } - if conf.Header == "" { - conf.Header = defaultHeader + if conf.TokenManager == "" { + conf.TokenManager = "jwt" } h, ok := tokenmgr.NewFuncs[conf.TokenManager] @@ -157,9 +148,9 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe return handler(srv, ss) } - tkn, _ := token.ContextGetToken(ctx) + tkn, ok := token.ContextGetToken(ctx) - if tkn == "" { + if !ok || tkn == "" { log.Warn().Msg("access token not found") return status.Errorf(codes.Unauthenticated, "auth: core access token not found") } diff --git a/internal/grpc/interceptors/token/token.go b/internal/grpc/interceptors/token/token.go index e428763809..7487087b95 100644 --- a/internal/grpc/interceptors/token/token.go +++ b/internal/grpc/interceptors/token/token.go @@ -26,24 +26,21 @@ import ( "google.golang.org/grpc/metadata" ) -const defaultHeader = "x-access-token" - // NewUnary returns a new unary interceptor that adds // the token to the context. func NewUnary() grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - var tkn string md, ok := metadata.FromIncomingContext(ctx) if ok && md != nil { - if val, ok := md[defaultHeader]; ok { + if val, ok := md[token.TokenHeader]; ok { if len(val) > 0 && val[0] != "" { - tkn = val[0] + tkn := val[0] + ctx = token.ContextSetToken(ctx, tkn) + ctx = metadata.AppendToOutgoingContext(ctx, token.TokenHeader, tkn) } } } - ctx = metadata.AppendToOutgoingContext(ctx, defaultHeader, tkn) - ctx = token.ContextSetToken(ctx, tkn) return handler(ctx, req) } return interceptor @@ -55,18 +52,17 @@ func NewStream() grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() - var tkn string md, ok := metadata.FromIncomingContext(ss.Context()) if ok && md != nil { - if val, ok := md[defaultHeader]; ok { + if val, ok := md[token.TokenHeader]; ok { if len(val) > 0 && val[0] != "" { - tkn = val[0] + tkn := val[0] + ctx = token.ContextSetToken(ctx, tkn) + ctx = metadata.AppendToOutgoingContext(ctx, token.TokenHeader, tkn) } } } - ctx = metadata.AppendToOutgoingContext(ctx, defaultHeader, tkn) - ctx = token.ContextSetToken(ctx, tkn) wrapped := newWrappedServerStream(ctx, ss) return handler(srv, wrapped) } diff --git a/internal/grpc/services/gateway/authprovider.go b/internal/grpc/services/gateway/authprovider.go index e74a12711b..0f148a74d1 100644 --- a/internal/grpc/services/gateway/authprovider.go +++ b/internal/grpc/services/gateway/authprovider.go @@ -25,11 +25,14 @@ import ( registry "github.com/cs3org/go-cs3apis/cs3/auth/registry/v1beta1" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + tokenpkg "github.com/cs3org/reva/pkg/token" "github.com/pkg/errors" + "google.golang.org/grpc/metadata" ) func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest) (*gateway.AuthenticateResponse, error) { @@ -82,39 +85,6 @@ func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest }, nil } - // TODO(labkode): we don't ned to call the user manager in the auth phase - // as the auth must provide a valid user. The mapping between user credentials and - // unique claims is done at the Authenticate logic an not here. - /* - userClient, err := pool.GetUserProviderServiceClient(s.c.UserProviderEndpoint) - if err != nil { - log.Err(err).Msg("error getting user provider client") - return &gateway.AuthenticateResponse{ - Status: status.NewInternal(ctx, err, "error getting user provider service client"), - }, nil - } - - getUserReq := &user.GetUserRequest{ - UserId: uid, - } - - getUserRes, err := userClient.GetUser(ctx, getUserReq) - if err != nil { - err = errors.Wrap(err, "authsvc: error in GetUser") - res := &gateway.AuthenticateResponse{ - Status: status.NewUnauthenticated(ctx, err, "error getting user information"), - } - return res, nil - } - - if getUserRes.Status.Code != rpc.Code_CODE_OK { - err := status.NewErrorFromCode(getUserRes.Status.Code, "authsvc") - return &gateway.AuthenticateResponse{ - Status: status.NewUnauthenticated(ctx, err, "error getting user information"), - }, nil - } - - */ user := res.User token, err := s.tokenmgr.MintToken(ctx, user) @@ -126,6 +96,38 @@ func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest return res, nil } + if s.c.DisableHomeCreationOnLogin { + gwRes := &gateway.AuthenticateResponse{ + Status: status.NewOK(ctx), + User: res.User, + Token: token, + } + return gwRes, nil + } + + // we need to pass the token to authenticate the CreateHome request. + // TODO(labkode): appending to existing context will not pass the token. + ctx = tokenpkg.ContextSetToken(ctx, token) + ctx = metadata.AppendToOutgoingContext(ctx, tokenpkg.TokenHeader, token) // TODO(jfd): hardcoded metadata key. use PerRPCCredentials? + + // create home directory + createHomeReq := &storageprovider.CreateHomeRequest{} + createHomeRes, err := s.CreateHome(ctx, createHomeReq) + if err != nil { + log.Err(err).Msg("error calling CreateHome") + return &gateway.AuthenticateResponse{ + Status: status.NewInternal(ctx, err, "error creating user home"), + }, nil + } + + if createHomeRes.Status.Code != rpc.Code_CODE_OK { + err := status.NewErrorFromCode(createHomeRes.Status.Code, "gateway") + log.Err(err).Msg("error calling Createhome") + return &gateway.AuthenticateResponse{ + Status: status.NewInternal(ctx, err, "error creating user home"), + }, nil + } + gwRes := &gateway.AuthenticateResponse{ Status: status.NewOK(ctx), User: res.User, diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index e6d2a82344..99290a6235 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -47,6 +47,7 @@ type config struct { UserProviderEndpoint string `mapstructure:"userprovidersvc"` CommitShareToStorageGrant bool `mapstructure:"commit_share_to_storage_grant"` CommitShareToStorageRef bool `mapstructure:"commit_share_to_storage_ref"` + DisableHomeCreationOnLogin bool `mapstructure:"disable_home_creation_on_login"` DataGatewayEndpoint string `mapstructure:"datagateway"` TransferSharedSecret string `mapstructure:"transfer_shared_secret"` TranserExpires int64 `mapstructure:"transfer_expires"` @@ -71,6 +72,15 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { return nil, err } + // set defaults + if c.ShareFolder == "" { + c.ShareFolder = "shares" + } + + if c.TokenManager == "" { + c.TokenManager = "jwt" + } + // ensure DataGatewayEndpoint is a valid URI if c.DataGatewayEndpoint == "" { return nil, errors.New("datagateway is not defined") diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index eed36c8496..dbe3e222e4 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -27,6 +27,7 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -65,20 +66,90 @@ func (s *svc) sign(ctx context.Context, target string) (string, error) { return tkn, nil } -func (s *svc) GetHome(ctx context.Context, ref *registry.GetHomeRequest) (*registry.GetHomeResponse, error) { +func (s *svc) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) (*provider.CreateHomeResponse, error) { + log := appctx.GetLogger(ctx) + + homeReq := &provider.GetHomeRequest{} + homeRes, err := s.GetHome(ctx, homeReq) + if err != nil { + log.Err(err).Msgf("gateway: error calling GetHome") + return &provider.CreateHomeResponse{ + Status: status.NewInternal(ctx, err, "error creating home"), + }, nil + } + + if homeRes.Status.Code != rpc.Code_CODE_OK { + err := status.NewErrorFromCode(homeRes.Status.Code, "gateway") + log.Err(err).Msg("gateway: bad grpc code") + return &provider.CreateHomeResponse{ + Status: status.NewInternal(ctx, err, "error calling GetHome"), + }, nil + } + + c, err := s.findByPath(ctx, homeRes.Path) + if err != nil { + log.Err(err).Msg("gateway: error finding storage provider") + if _, ok := err.(errtypes.IsNotFound); ok { + return &provider.CreateHomeResponse{ + Status: status.NewNotFound(ctx, "storage provider not found"), + }, nil + } + return &provider.CreateHomeResponse{ + Status: status.NewInternal(ctx, err, "error finding storage provider"), + }, nil + } + + res, err := c.CreateHome(ctx, req) + if err != nil { + log.Err(err).Msg("gateway: error creating home on storage provider") + return &provider.CreateHomeResponse{ + Status: status.NewInternal(ctx, err, "error calling CreateHome"), + }, nil + } + + return res, nil + +} +func (s *svc) GetHome(ctx context.Context, req *provider.GetHomeRequest) (*provider.GetHomeResponse, error) { c, err := pool.GetStorageRegistryClient(s.c.StorageRegistryEndpoint) if err != nil { err = errors.Wrap(err, "gateway: error getting storage registry client") - return nil, err + return &provider.GetHomeResponse{ + Status: status.NewInternal(ctx, err, "error finding storage registry"), + }, nil } res, err := c.GetHome(ctx, ®istry.GetHomeRequest{}) - if err != nil { err = errors.Wrap(err, "gateway: error calling GetHome") - return nil, err + return &provider.GetHomeResponse{ + Status: status.NewInternal(ctx, err, "error calling GetHome"), + }, nil } - return res, nil + + if res.Status.Code != rpc.Code_CODE_OK { + err := status.NewErrorFromCode(res.Status.Code, "gateway") + return &provider.GetHomeResponse{ + Status: status.NewInternal(ctx, err, "error calling GetHome"), + }, nil + } + + storageClient, err := pool.GetStorageProviderServiceClient(res.Provider.Address) + if err != nil { + err = errors.Wrap(err, "gateway: error getting storage provider client") + return &provider.GetHomeResponse{ + Status: status.NewInternal(ctx, err, "error getting home"), + }, nil + } + + homeRes, err := storageClient.GetHome(ctx, req) + if err != nil { + err = errors.Wrap(err, "gateway: error getting GetHome from storage provider") + return &provider.GetHomeResponse{ + Status: status.NewInternal(ctx, err, "error getting home"), + }, nil + } + return homeRes, nil } func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*gateway.InitiateFileDownloadResponse, error) { diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index 746f5b22ea..a6b299487b 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -26,7 +26,6 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" @@ -389,19 +388,8 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update share := getShareRes.Share - // get user home - storageRegClient, err := pool.GetStorageRegistryClient(s.c.StorageRegistryEndpoint) - if err != nil { - log.Err(err).Msg("gateway: error getting storage registry client") - return &collaboration.UpdateReceivedShareResponse{ - Status: &rpc.Status{ - Code: rpc.Code_CODE_INTERNAL, - }, - }, nil - } - - homeReq := ®istry.GetHomeRequest{} - homeRes, err := storageRegClient.GetHome(ctx, homeReq) + homeReq := &provider.GetHomeRequest{} + homeRes, err := s.GetHome(ctx, homeReq) if err != nil { err := errors.Wrap(err, "gateway: error calling GetHome") return &collaboration.UpdateReceivedShareResponse{ @@ -410,8 +398,6 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update } // reference path is the home path + some name - // TODO(labkode): where shares should be created, here we can define the folder in the gateway - // so the target path on the home storage provider will be: // CreateReferene(cs3://home/shares/x) // CreateReference(cs3://eos/user/g/gonzalhu/.shares/x) // CreateReference(cs3://eos/user/.hidden/g/gonzalhu/shares/x) @@ -421,9 +407,12 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update // It is the responsibility of the gateway to resolve these references and merge the response back // from the main request. // TODO(labkode): the name of the share should be the filename it points to by default. - refPath := path.Join(homeRes.Path, req.Ref.String()) + + // TODO(labkode): create share folder if it does not exist. Maybe at home directory creation time (login)? + refPath := path.Join(homeRes.Path, s.c.ShareFolder, req.Ref.String()) createRefReq := &provider.CreateReferenceRequest{ - Path: refPath, + Path: refPath, + // cs3 is the Scheme and %s/%s is the Opaque parts of a net.URL. TargetUri: fmt.Sprintf("cs3:%s/%s", share.Share.ResourceId.GetStorageId(), share.Share.ResourceId.GetOpaqueId()), } diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index 3e199d3cf0..16bd78b7b5 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -46,16 +46,17 @@ func init() { } type config struct { - MountPath string `mapstructure:"mount_path"` - MountID string `mapstructure:"mount_id"` - Driver string `mapstructure:"driver"` - Drivers map[string]map[string]interface{} `mapstructure:"drivers"` - PathWrapper string `mapstructure:"path_wrapper"` - PathWrappers map[string]map[string]interface{} `mapstructure:"path_wrappers"` - TmpFolder string `mapstructure:"tmp_folder"` - DataServerURL string `mapstructure:"data_server_url"` - ExposeDataServer bool `mapstructure:"expose_data_server"` // if true the client will be able to upload/download directly to it - AvailableXS map[string]uint32 `mapstructure:"available_checksums"` + MountPath string `mapstructure:"mount_path"` + MountID string `mapstructure:"mount_id"` + Driver string `mapstructure:"driver"` + Drivers map[string]map[string]interface{} `mapstructure:"drivers"` + PathWrapper string `mapstructure:"path_wrapper"` + PathWrappers map[string]map[string]interface{} `mapstructure:"path_wrappers"` + TmpFolder string `mapstructure:"tmp_folder"` + DataServerURL string `mapstructure:"data_server_url"` + ExposeDataServer bool `mapstructure:"expose_data_server"` // if true the client will be able to upload/download directly to it + EnableHomeCreation bool `mapstructure:"enable_home_creation"` + AvailableXS map[string]uint32 `mapstructure:"available_checksums"` } type service struct { @@ -111,6 +112,11 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { return nil, err } + // set sane defaults + if len(c.AvailableXS) == 0 { + c.AvailableXS = map[string]uint32{"md5": 100, "unset": 1000} + } + // use os temporary folder if empty tmpFolder := c.TmpFolder if tmpFolder == "" { @@ -282,6 +288,50 @@ func (s *service) GetPath(ctx context.Context, req *provider.GetPathRequest) (*p return res, nil } +func (s *service) GetHome(ctx context.Context, req *provider.GetHomeRequest) (*provider.GetHomeResponse, error) { + home, err := s.storage.GetHome(ctx) + if err != nil { + st := status.NewInternal(ctx, err, "error getting home") + return &provider.GetHomeResponse{ + Status: st, + }, nil + } + + home = path.Join(s.mountPath, home) + + res := &provider.GetHomeResponse{ + Status: status.NewOK(ctx), + Path: home, + } + return res, nil +} + +func (s *service) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) (*provider.CreateHomeResponse, error) { + log := appctx.GetLogger(ctx) + if !s.conf.EnableHomeCreation { + err := errtypes.NotSupported("storageprovider: create home directories not enabled") + log.Err(err).Msg("storageprovider: home creation is disabled") + st := status.NewUnimplemented(ctx, err, "creating home directories is disabled by configuration") + return &provider.CreateHomeResponse{ + Status: st, + }, nil + + } + if err := s.storage.CreateHome(ctx); err != nil { + st := status.NewInternal(ctx, err, "error creating home") + log.Err(err).Msg("storageprovider: error calling CreateHome of storage driver") + return &provider.CreateHomeResponse{ + Status: st, + }, nil + } + + res := &provider.CreateHomeResponse{ + Status: status.NewOK(ctx), + } + return res, nil + +} + func (s *service) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { newRef, err := s.unwrap(ctx, req.Ref) if err != nil { diff --git a/internal/grpc/services/storageregistry/storageregistry.go b/internal/grpc/services/storageregistry/storageregistry.go index 2fd9398cf3..c9a03a35c2 100644 --- a/internal/grpc/services/storageregistry/storageregistry.go +++ b/internal/grpc/services/storageregistry/storageregistry.go @@ -140,8 +140,8 @@ func (s *service) GetHome(ctx context.Context, req *registrypb.GetHomeRequest) ( } res := ®istrypb.GetHomeResponse{ - Status: status.NewOK(ctx), - Path: p, + Status: status.NewOK(ctx), + Provider: p, } return res, nil } diff --git a/internal/http/interceptors/auth/auth.go b/internal/http/interceptors/auth/auth.go index 072222e0d6..cabadbd682 100644 --- a/internal/http/interceptors/auth/auth.go +++ b/internal/http/interceptors/auth/auth.go @@ -33,6 +33,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token" tokenmgr "github.com/cs3org/reva/pkg/token/manager/registry" "github.com/cs3org/reva/pkg/user" @@ -42,13 +43,9 @@ import ( "google.golang.org/grpc/metadata" ) -const ( - defaultHeader = "x-access-token" -) - type config struct { Priority int `mapstructure:"priority"` - GatewaySvc string `mapstructure:"gateway"` + GatewaySvc string `mapstructure:"gatewaysvc"` // TODO(jdf): Realm is optional, will be filled with request host if not given? Realm string `mapstructure:"realm"` CredentialChain []string `mapstructure:"credential_chain"` @@ -77,6 +74,25 @@ func New(m map[string]interface{}, unprotected []string) (global.Middleware, err return nil, err } + conf.GatewaySvc = sharedconf.GetGatewaySVC(conf.GatewaySvc) + + // set defaults + if conf.TokenStrategy == "" { + conf.TokenStrategy = "header" + } + + if conf.TokenWriter == "" { + conf.TokenWriter = "header" + } + + if conf.TokenManager == "" { + conf.TokenManager = "jwt" + } + + if len(conf.CredentialChain) == 0 { + conf.CredentialChain = []string{"basic", "bearer"} + } + credChain := []auth.CredentialStrategy{} for i := range conf.CredentialChain { f, ok := registry.NewCredentialFuncs[conf.CredentialChain[i]] @@ -224,7 +240,7 @@ func New(m map[string]interface{}, unprotected []string) (global.Middleware, err // store user and core access token in context. ctx = user.ContextSetUser(ctx, u) ctx = token.ContextSetToken(ctx, tkn) - ctx = metadata.AppendToOutgoingContext(ctx, defaultHeader, tkn) // TODO(jfd): hardcoded metadata key. use PerRPCCredentials? + ctx = metadata.AppendToOutgoingContext(ctx, token.TokenHeader, tkn) // TODO(jfd): hardcoded metadata key. use PerRPCCredentials? r = r.WithContext(ctx) h.ServeHTTP(w, r) diff --git a/internal/http/interceptors/auth/token/strategy/header/header.go b/internal/http/interceptors/auth/token/strategy/header/header.go index 00a234977c..980a9a7cbc 100644 --- a/internal/http/interceptors/auth/token/strategy/header/header.go +++ b/internal/http/interceptors/auth/token/strategy/header/header.go @@ -23,46 +23,20 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/auth/token/registry" "github.com/cs3org/reva/pkg/auth" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" -) - -const ( - defaultHeader = "X-Access-Token" + "github.com/cs3org/reva/pkg/token" ) func init() { registry.Register("header", New) } -type config struct { - Header string `mapstructure:"header"` -} type strategy struct { header string } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - - if c.Header == "" { - c.Header = defaultHeader - } - - return c, nil -} - // New returns a new auth strategy that checks for basic auth. func New(m map[string]interface{}) (auth.TokenStrategy, error) { - conf, err := parseConfig(m) - if err != nil { - return nil, err - } - return &strategy{header: conf.Header}, nil + return &strategy{header: token.TokenHeader}, nil } func (s *strategy) GetToken(r *http.Request) string { diff --git a/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go b/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go index 513314f276..664810029d 100644 --- a/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go +++ b/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go @@ -23,38 +23,20 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/auth/tokenwriter/registry" "github.com/cs3org/reva/pkg/auth" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/token" ) func init() { registry.Register("header", New) } -type config struct { - Header string `mapstructure:"header"` -} - type strategy struct { header string } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{Header: "X-Access-Token"} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns a new token writer strategy that stores token in a header. func New(m map[string]interface{}) (auth.TokenWriter, error) { - conf, err := parseConfig(m) - if err != nil { - return nil, err - } - return &strategy{header: conf.Header}, nil + return &strategy{header: token.TokenHeader}, nil } func (s *strategy) WriteToken(token string, w http.ResponseWriter) { diff --git a/internal/http/interceptors/cors/cors.go b/internal/http/interceptors/cors/cors.go index f6bbfc0add..236f0fe074 100644 --- a/internal/http/interceptors/cors/cors.go +++ b/internal/http/interceptors/cors/cors.go @@ -35,6 +35,7 @@ func init() { type config struct { AllowCredentials bool `mapstructure:"allow_credentials"` OptionsPassthrough bool `mapstructure:"options_passthrough"` + Debug bool `mapstructure:"debug"` MaxAge int `mapstructure:"max_age"` Priority int `mapstructure:"priority"` AllowedMethods []string `mapstructure:"allowed_methods"` @@ -64,9 +65,11 @@ func New(m map[string]interface{}) (global.Middleware, int, error) { } if len(conf.AllowedHeaders) == 0 { - conf.AllowedHeaders = []string{"Origin", "Accept", "Content-Type", "X-Requested-With", "Authorization", "Ocs-Apirequest", "If-None-Match"} + conf.AllowedHeaders = []string{"Origin", "Accept", "Content-Type", "Depth", "Authorization", "Ocs-Apirequest", "If-None-Match", "If-Match", "Destination", "Overwrite", "X-Request-Id", "X-Requested-With"} } + // TODO(jfd): use log from request context, otherwise fmt will be used to log, + // preventing us from pinging the log to eg jq c := cors.New(cors.Options{ AllowCredentials: conf.AllowCredentials, AllowedHeaders: conf.AllowedHeaders, @@ -75,9 +78,7 @@ func New(m map[string]interface{}) (global.Middleware, int, error) { ExposedHeaders: conf.ExposedHeaders, MaxAge: conf.MaxAge, OptionsPassthrough: conf.OptionsPassthrough, - Debug: false, - // TODO(jfd): use log from request context, otherwise fmt will be used to log, - // preventing us from pinging the log to eg jq + Debug: conf.Debug, }) return c.Handler, conf.Priority, nil diff --git a/internal/http/services/datagateway/datagateway.go b/internal/http/services/datagateway/datagateway.go index 776e5728fe..9de16d729a 100644 --- a/internal/http/services/datagateway/datagateway.go +++ b/internal/http/services/datagateway/datagateway.go @@ -48,7 +48,6 @@ type transferClaims struct { } type config struct { Prefix string `mapstructure:"prefix"` - GatewayEndpoint string `mapstructure:"gateway"` TransferSharedSecret string `mapstructure:"transfer_shared_secret"` } @@ -64,6 +63,10 @@ func New(m map[string]interface{}) (global.Service, error) { return nil, err } + if conf.Prefix == "" { + conf.Prefix = "data" + } + s := &svc{conf: conf} s.setHandler() return s, nil diff --git a/internal/http/services/dataprovider/dataprovider.go b/internal/http/services/dataprovider/dataprovider.go index 0b1d1bac21..66e6fac18b 100644 --- a/internal/http/services/dataprovider/dataprovider.go +++ b/internal/http/services/dataprovider/dataprovider.go @@ -55,6 +55,10 @@ func New(m map[string]interface{}) (global.Service, error) { return nil, err } + if conf.Prefix == "" { + conf.Prefix = "data" + } + if conf.TmpFolder == "" { conf.TmpFolder = os.TempDir() } diff --git a/internal/http/services/oidcprovider/oidcprovider.go b/internal/http/services/oidcprovider/oidcprovider.go index 5bf00ce0af..1f9013a324 100644 --- a/internal/http/services/oidcprovider/oidcprovider.go +++ b/internal/http/services/oidcprovider/oidcprovider.go @@ -24,18 +24,18 @@ import ( "net/http" "time" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/sharedconf" + "github.com/mitchellh/mapstructure" "github.com/ory/fosite" "github.com/ory/fosite/compose" "github.com/ory/fosite/handler/openid" "github.com/ory/fosite/storage" "github.com/ory/fosite/token/jwt" "github.com/pkg/errors" - - userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" - "github.com/cs3org/reva/pkg/appctx" - "github.com/cs3org/reva/pkg/rhttp/global" - "github.com/cs3org/reva/pkg/rhttp/router" - "github.com/mitchellh/mapstructure" ) func init() { @@ -44,7 +44,7 @@ func init() { type config struct { Prefix string `mapstructure:"prefix"` - GatewayEndpoint string `mapstructure:"gateway"` + GatewayEndpoint string `mapstructure:"gatewaysvc"` Clients map[string]map[string]interface{} `mapstructure:"clients"` Issuer string `mapstructure:"issuer"` } @@ -80,6 +80,8 @@ func New(m map[string]interface{}) (global.Service, error) { c.Prefix = "oauth2" } + c.GatewayEndpoint = sharedconf.GetGatewaySVC(c.GatewayEndpoint) + clients, err := getClients(c.Clients) if err != nil { return nil, errors.Wrap(err, "oidcprovider: error parsing oidc clients") diff --git a/internal/http/services/oidcprovider/userinfo.go b/internal/http/services/oidcprovider/userinfo.go index 12ba81f30c..d67df6a979 100644 --- a/internal/http/services/oidcprovider/userinfo.go +++ b/internal/http/services/oidcprovider/userinfo.go @@ -58,7 +58,7 @@ func (s *svc) doUserinfo(w http.ResponseWriter, r *http.Request) { internalToken := session.internalToken // To include in the context. ctx = token.ContextSetToken(ctx, internalToken) - ctx = metadata.AppendToOutgoingContext(ctx, "x-access-token", internalToken) // TODO(labkode): this sucks. + ctx = metadata.AppendToOutgoingContext(ctx, token.TokenHeader, internalToken) // TODO(labkode): this sucks. sub := session.GetSubject() fmt.Printf("internal token: %s subject: %s session:%+v", internalToken, sub, session) diff --git a/internal/http/services/owncloud/ocdav/move.go b/internal/http/services/owncloud/ocdav/move.go index a402ffe464..899bc7f781 100644 --- a/internal/http/services/owncloud/ocdav/move.go +++ b/internal/http/services/owncloud/ocdav/move.go @@ -68,7 +68,7 @@ func (s *svc) doMove(w http.ResponseWriter, r *http.Request, ns string) { } urlPath := dstURL.Path - baseURI := r.Context().Value("baseuri").(string) + baseURI := r.Context().Value(ctxKeyBaseURI).(string) log.Info().Str("url_path", urlPath).Str("base_uri", baseURI).Msg("move urls") // TODO replace with HasPrefix: i := strings.Index(urlPath, baseURI) diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go index 42a41ff62b..428038173f 100644 --- a/internal/http/services/owncloud/ocdav/ocdav.go +++ b/internal/http/services/owncloud/ocdav/ocdav.go @@ -33,6 +33,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/sharedconf" "github.com/mitchellh/mapstructure" ) @@ -52,7 +53,7 @@ type Config struct { FilesNamespace string `mapstructure:"files_namespace"` WebdavNamespace string `mapstructure:"webdav_namespace"` ChunkFolder string `mapstructure:"chunk_folder"` - GatewaySvc string `mapstructure:"gateway"` + GatewaySvc string `mapstructure:"gatewaysvc"` } type svc struct { @@ -68,6 +69,8 @@ func New(m map[string]interface{}) (global.Service, error) { return nil, err } + conf.GatewaySvc = sharedconf.GetGatewaySVC(conf.GatewaySvc) + if conf.ChunkFolder == "" { conf.ChunkFolder = os.TempDir() } diff --git a/internal/http/services/owncloud/ocdav/options.go b/internal/http/services/owncloud/ocdav/options.go index c3aec8270e..9db8de933c 100644 --- a/internal/http/services/owncloud/ocdav/options.go +++ b/internal/http/services/owncloud/ocdav/options.go @@ -27,13 +27,6 @@ func (s *svc) doOptions(w http.ResponseWriter, r *http.Request, ns string) { allow += " MOVE, UNLOCK, PROPFIND, MKCOL, REPORT, SEARCH," allow += " PUT" // TODO(jfd): only for files ... but we cannot create the full path without a user ... which we only have when credentials are sent - w.Header().Add("Vary", "Origin") - w.Header().Add("Vary", "Access-Control-Request-Method") - w.Header().Add("Vary", "Access-Control-Request-Headers") - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Credentials", "true") - w.Header().Set("Access-Control-Allow-Methods", allow) - w.Header().Set("Access-Control-Allow-Headers", "Authorization, X-Requested-With, Content-Type, Depth, Ocs-Apirequest, If-Match, If-None-Match, Destination") w.Header().Set("Content-Type", "application/xml") w.Header().Set("Allow", allow) w.Header().Set("DAV", "1, 2") diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 8a79826d98..5f8ed04946 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -32,7 +32,6 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" "github.com/cs3org/reva/internal/http/utils" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -161,7 +160,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s return } - getHomeRes, err := gc.GetHome(ctx, ®istry.GetHomeRequest{}) + getHomeRes, err := gc.GetHome(ctx, &provider.GetHomeRequest{}) if err != nil { log.Error().Err(err).Msg("error calling GetHomeProvider") w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/owncloud/ocs/capabilities.go b/internal/http/services/owncloud/ocs/capabilities.go index ac657e1796..c354502fd9 100644 --- a/internal/http/services/owncloud/ocs/capabilities.go +++ b/internal/http/services/owncloud/ocs/capabilities.go @@ -96,7 +96,7 @@ func (h *CapabilitiesHandler) init(c *Config) { h.c.Capabilities.Checksums = &CapabilitiesChecksums{} } if h.c.Capabilities.Checksums.SupportedTypes == nil { - h.c.Capabilities.Checksums.SupportedTypes = []string{"SHA1"} + h.c.Capabilities.Checksums.SupportedTypes = []string{"SHA256"} } if h.c.Capabilities.Checksums.PreferredUploadType == "" { h.c.Capabilities.Checksums.PreferredUploadType = "SHA1" diff --git a/internal/http/services/owncloud/ocs/ocs.go b/internal/http/services/owncloud/ocs/ocs.go index c271f4f048..9d1ba195fb 100644 --- a/internal/http/services/owncloud/ocs/ocs.go +++ b/internal/http/services/owncloud/ocs/ocs.go @@ -24,6 +24,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/sharedconf" "github.com/mitchellh/mapstructure" ) @@ -36,7 +37,7 @@ type Config struct { Prefix string `mapstructure:"prefix"` Config ConfigData `mapstructure:"config"` Capabilities CapabilitiesData `mapstructure:"capabilities"` - GatewaySvc string `mapstructure:"gateway"` + GatewaySvc string `mapstructure:"gatewaysvc"` } type svc struct { @@ -55,6 +56,8 @@ func New(m map[string]interface{}) (global.Service, error) { conf.Prefix = "ocs" } + conf.GatewaySvc = sharedconf.GetGatewaySVC(conf.GatewaySvc) + s := &svc{ c: conf, V1Handler: new(V1Handler), diff --git a/internal/http/services/owncloud/ocs/users.go b/internal/http/services/owncloud/ocs/users.go index 39f8d56da8..de8d19ca59 100644 --- a/internal/http/services/owncloud/ocs/users.go +++ b/internal/http/services/owncloud/ocs/users.go @@ -65,10 +65,13 @@ func (h *UsersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { DisplayName: u.DisplayName, Email: u.Mail, }) + return case "groups": WriteOCSSuccess(w, r, &GroupsData{}) + return default: WriteOCSError(w, r, MetaNotFound.StatusCode, "Not found", nil) + return } } diff --git a/pkg/eosclient/eosclient.go b/pkg/eosclient/eosclient.go index 8c4fbfbfd6..eb39991a84 100644 --- a/pkg/eosclient/eosclient.go +++ b/pkg/eosclient/eosclient.go @@ -74,7 +74,7 @@ type Attribute struct { } func (a *Attribute) serialize() string { - return fmt.Sprintf("%s.%s=%q", a.Type, a.Key, a.Key) + return fmt.Sprintf("%s.%s=%s", a.Type, a.Key, a.Val) } func (a *Attribute) isValid() bool { @@ -200,9 +200,6 @@ func (c *Client) execute(ctx context.Context, cmd *exec.Cmd) (string, string, er err = nil case 2: err = errtypes.NotFound(errBuf.String()) - case 22: - // eos reports back error code 22 when the user is not allowed to enter the instance - err = errtypes.NotFound(errBuf.String()) } } } @@ -212,13 +209,14 @@ func (c *Client) execute(ctx context.Context, cmd *exec.Cmd) (string, string, er log.Info().Str("args", args).Str("env", env).Int("exit", exitStatus).Msg("eos cmd") if err != nil && exitStatus != 2 { // don't wrap the errtypes.NotFoundError - err = errors.Wrap(err, "error while executing command") + err = errors.Wrap(err, "eosclient: error while executing command") } return outBuf.String(), errBuf.String(), err } -// exec executes the command and returns the stdout, stderr and return code +// exec executes only EOS commands the command and returns the stdout, stderr and return code. +// execute() executes arbitrary commands. func (c *Client) executeEOS(ctx context.Context, cmd *exec.Cmd) (string, string, error) { log := appctx.GetLogger(ctx) @@ -250,7 +248,7 @@ func (c *Client) executeEOS(ctx context.Context, cmd *exec.Cmd) (string, string, err = errtypes.NotFound(errBuf.String()) case 22: // eos reports back error code 22 when the user is not allowed to enter the instance - err = errtypes.NotFound(errBuf.String()) + err = errtypes.PermissionDenied(errBuf.String()) } } } @@ -260,7 +258,7 @@ func (c *Client) executeEOS(ctx context.Context, cmd *exec.Cmd) (string, string, log.Info().Str("args", args).Str("env", env).Int("exit", exitStatus).Str("err", errBuf.String()).Msg("eos cmd") if err != nil && exitStatus != 2 { // don't wrap the errtypes.NotFoundError - err = errors.Wrap(err, "error while executing command") + err = errors.Wrap(err, "eosclient: error while executing command") } return outBuf.String(), errBuf.String(), err @@ -482,6 +480,35 @@ func (c *Client) Touch(ctx context.Context, username, path string) error { return err } +// Chown given path +func (c *Client) Chown(ctx context.Context, username, chownUser, path string) error { + unixUser, err := c.getUnixUser(username) + if err != nil { + return err + } + + unixChownUser, err := c.getUnixUser(chownUser) + if err != nil { + return err + } + + cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", unixUser.Uid, unixUser.Gid, "chown", unixChownUser.Uid+":"+unixChownUser.Gid, path) + _, _, err = c.executeEOS(ctx, cmd) + return err +} + +// Chmod given path +func (c *Client) Chmod(ctx context.Context, username, mode, path string) error { + unixUser, err := c.getUnixUser(username) + if err != nil { + return err + } + + cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", unixUser.Uid, unixUser.Gid, "chmod", mode, path) + _, _, err = c.executeEOS(ctx, cmd) + return err +} + // CreateDir creates a directory at the given path func (c *Client) CreateDir(ctx context.Context, username, path string) error { unixUser, err := c.getUnixUser(username) @@ -489,7 +516,7 @@ func (c *Client) CreateDir(ctx context.Context, username, path string) error { return err } - cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", unixUser.Uid, unixUser.Gid, "mkdir", path) + cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", unixUser.Uid, unixUser.Gid, "mkdir", "-p", path) _, _, err = c.executeEOS(ctx, cmd) return err } @@ -525,7 +552,7 @@ func (c *Client) List(ctx context.Context, username, path string) ([]*FileInfo, cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", unixUser.Uid, unixUser.Gid, "find", "--fileinfo", "--maxdepth", "1", path) stdout, _, err := c.executeEOS(ctx, cmd) if err != nil { - return nil, errors.Wrapf(err, "error listing fn=%s", path) + return nil, errors.Wrapf(err, "eosclient: error listing fn=%s", path) } return c.parseFind(path, stdout) } diff --git a/pkg/errtypes/errtypes.go b/pkg/errtypes/errtypes.go index a33a5376b6..9e9e613244 100644 --- a/pkg/errtypes/errtypes.go +++ b/pkg/errtypes/errtypes.go @@ -30,6 +30,14 @@ func (e NotFound) Error() string { return "error: not found: " + string(e) } // IsNotFound is the method to check for w func (e NotFound) IsNotFound() {} +// PermissionDenied is the error to use when a resource cannot be access because of missing permissions. +type PermissionDenied string + +func (e PermissionDenied) Error() string { return "error: permission denied: " + string(e) } + +// IsPermissionDenied is the method to check for w +func (e PermissionDenied) IsPermissionDenied() {} + // AlreadyExists is the error to use when a resource something is not found. type AlreadyExists string @@ -91,3 +99,9 @@ type IsInvalidCredentials interface { type IsNotSupported interface { IsNotSupported() } + +// IsPermissionDenied is the interface to implement +// to specify that an action is not supported. +type IsPermissionDenied interface { + IsPermissionDenied() +} diff --git a/pkg/rgrpc/status/status.go b/pkg/rgrpc/status/status.go index 53fd300fd6..239a15fcdd 100644 --- a/pkg/rgrpc/status/status.go +++ b/pkg/rgrpc/status/status.go @@ -40,7 +40,8 @@ func NewOK(ctx context.Context) *rpc.Status { // NewNotFound returns a Status with CODE_NOT_FOUND and logs the msg. func NewNotFound(ctx context.Context, msg string) *rpc.Status { - appctx.GetLogger(ctx).Warn().Msg(msg) + log := appctx.GetLogger(ctx).With().CallerWithSkipFrameCount(3).Logger() + log.Warn().Msg(msg) return &rpc.Status{ Code: rpc.Code_CODE_NOT_FOUND, Message: msg, @@ -50,7 +51,8 @@ func NewNotFound(ctx context.Context, msg string) *rpc.Status { // NewInvalid returns a Status with CODE_INVALID_ARGUMENT and logs the msg. func NewInvalid(ctx context.Context, msg string) *rpc.Status { - appctx.GetLogger(ctx).Warn().Msg(msg) + log := appctx.GetLogger(ctx).With().CallerWithSkipFrameCount(3).Logger() + log.Warn().Msg(msg) return &rpc.Status{ Code: rpc.Code_CODE_INVALID_ARGUMENT, Message: msg, @@ -64,7 +66,10 @@ func NewInternal(ctx context.Context, err error, msg string) *rpc.Status { if err == nil { panic("Internal error triggered without an error context") } - appctx.GetLogger(ctx).Err(err).Msg(msg) + + log := appctx.GetLogger(ctx).With().CallerWithSkipFrameCount(3).Logger() + log.Err(err).Msg(msg) + return &rpc.Status{ Code: rpc.Code_CODE_INTERNAL, Message: msg, @@ -74,7 +79,8 @@ func NewInternal(ctx context.Context, err error, msg string) *rpc.Status { // NewUnauthenticated returns a Status with CODE_UNAUTHENTICATED and logs the msg. func NewUnauthenticated(ctx context.Context, err error, msg string) *rpc.Status { - appctx.GetLogger(ctx).Warn().Err(err).Msg(msg) + log := appctx.GetLogger(ctx).With().CallerWithSkipFrameCount(3).Logger() + log.Warn().Err(err).Msg(msg) return &rpc.Status{ Code: rpc.Code_CODE_UNAUTHENTICATED, Message: msg, @@ -84,7 +90,8 @@ func NewUnauthenticated(ctx context.Context, err error, msg string) *rpc.Status // NewUnimplemented returns a Status with CODE_UNIMPLEMENTED and logs the msg. func NewUnimplemented(ctx context.Context, err error, msg string) *rpc.Status { - appctx.GetLogger(ctx).Error().Err(err).Msg(msg) + log := appctx.GetLogger(ctx).With().CallerWithSkipFrameCount(3).Logger() + log.Error().Err(err).Msg(msg) return &rpc.Status{ Code: rpc.Code_CODE_UNIMPLEMENTED, Message: msg, @@ -102,7 +109,7 @@ func NewInvalidArg(ctx context.Context, msg string) *rpc.Status { // NewErrorFromCode returns a standardized Error for a given RPC code. func NewErrorFromCode(code rpc.Code, pkgname string) error { - return errors.New(pkgname + ": RPC failed with code " + code.String()) + return errors.New(pkgname + ": grpc failed with code " + code.String()) } // internal function to attach the trace to a context diff --git a/pkg/rhttp/client.go b/pkg/rhttp/client.go index e317491e12..b6b8a52fc4 100644 --- a/pkg/rhttp/client.go +++ b/pkg/rhttp/client.go @@ -29,10 +29,6 @@ import ( "go.opencensus.io/plugin/ochttp" ) -const ( - defaultAccessHeader = "X-Access-Token" -) - // GetHTTPClient returns an http client with open census tracing support. // TODO(labkode): harden it. // https://medium.com/@nate510/don-t-use-go-s-default-http-client-4804cb19f779 @@ -54,7 +50,7 @@ func NewRequest(ctx context.Context, method, url string, body io.Reader) (*http. // TODO(labkode): make header / auth configurable tkn, ok := token.ContextGetToken(ctx) if ok { - httpReq.Header.Set(defaultAccessHeader, tkn) + httpReq.Header.Set(token.TokenHeader, tkn) } httpReq = httpReq.WithContext(ctx) diff --git a/pkg/sharedconf/sharedconf.go b/pkg/sharedconf/sharedconf.go new file mode 100644 index 0000000000..29728995ec --- /dev/null +++ b/pkg/sharedconf/sharedconf.go @@ -0,0 +1,55 @@ +// Copyright 2018-2019 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package sharedconf + +import ( + "github.com/mitchellh/mapstructure" +) + +var sharedConf = &conf{} + +type conf struct { + JWTSecret string `mapstructure:"jwt_secret"` + GatewaySVC string `mapstructure:"gatewaysvc"` +} + +// Decode decodes the configuration. +func Decode(v interface{}) error { + if err := mapstructure.Decode(v, sharedConf); err != nil { + return err + } + + return nil +} + +// GetJWTSecret returns the package level configured jwt secret if not overwriten. +func GetJWTSecret(val string) string { + if val == "" { + return sharedConf.JWTSecret + } + return val +} + +// GetGatewaySVC returns the package level configured gateway service if not overwriten. +func GetGatewaySVC(val string) string { + if val == "" { + return sharedConf.GatewaySVC + } + return val +} diff --git a/pkg/sharedconf/sharedconf_test.go b/pkg/sharedconf/sharedconf_test.go new file mode 100644 index 0000000000..f2735323da --- /dev/null +++ b/pkg/sharedconf/sharedconf_test.go @@ -0,0 +1,64 @@ +// Copyright 2018-2019 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package sharedconf + +import ( + "testing" +) + +func Test(t *testing.T) { + conf := map[string]interface{}{ + "jwt_secret": "", + "gateway": "", + } + + err := Decode(conf) + if err != nil { + t.Fatal(err) + } + + got := GetJWTSecret("secret") + if got != "secret" { + t.Fatalf("expected %q got %q", "secret", got) + } + + got = GetJWTSecret("") + if got != "" { + t.Fatalf("expected %q got %q", "", got) + } + + conf = map[string]interface{}{ + "jwt_secret": "dummy", + } + + err = Decode(conf) + if err != nil { + t.Fatal(err) + } + + got = GetJWTSecret("secret") + if got != "secret" { + t.Fatalf("expected %q got %q", "secret", got) + } + + got = GetJWTSecret("") + if got != "dummy" { + t.Fatalf("expected %q got %q", "dummy", got) + } +} diff --git a/pkg/storage/fs/eos/eos.go b/pkg/storage/fs/eos/eos.go index f95d1cb527..2c66444240 100644 --- a/pkg/storage/fs/eos/eos.go +++ b/pkg/storage/fs/eos/eos.go @@ -108,6 +108,9 @@ type config struct { // UseKeyTabAuth changes will authenticate requests by using an EOS keytab. UseKeytab bool `mapstrucuture:"use_keytab"` + // EnableHome enables the creation of home directories. + EnableHome bool `mapstructure:"enable_home"` + // SecProtocol specifies the xrootd security protocol to use between the server and EOS. SecProtocol string `mapstructure:"sec_protocol"` @@ -194,6 +197,13 @@ func New(m map[string]interface{}) (storage.FS, error) { return eosStorage, nil } +func (fs *eosStorage) getHomeForUser(u *userpb.User) string { + // TODO(labkode): define home path layout in configuration + // like home: %letter%/%username% and then do string substitution. + home := path.Join(fs.mountpoint, u.Username) + return home +} + func (fs *eosStorage) Shutdown(ctx context.Context) error { // TODO(labkode): in a grpc implementation we can close connections. return nil @@ -555,6 +565,82 @@ func (fs *eosStorage) GetQuota(ctx context.Context) (int, int, error) { return fs.c.GetQuota(ctx, u.Username, fs.conf.Namespace) } +func (fs *eosStorage) GetHome(ctx context.Context) (string, error) { + u, err := getUser(ctx) + if err != nil { + return "", errors.Wrap(err, "eos: no user in ctx") + } + + home := fs.getHomeForUser(u) + return home, nil +} + +func (fs *eosStorage) CreateHome(ctx context.Context) error { + u, err := getUser(ctx) + if err != nil { + return errors.Wrap(err, "eos: no user in ctx") + } + + home := fs.getHomeForUser(u) + + _, err = fs.c.GetFileInfoByPath(ctx, "root", home) + if err == nil { // home already exists + return nil + } + + // TODO(labkode): abort on any error that is not found + if _, ok := err.(errtypes.IsNotFound); !ok { + return errors.Wrap(err, "eos: error verifying if user home directory exists") + } + + // TODO(labkode): only trigger creation on not found, copy from CERNBox logic. + err = fs.c.CreateDir(ctx, "root", home) + if err != nil { + // EOS will return success on mkdir over an existing directory. + return errors.Wrap(err, "eos: error creating dir") + } + err = fs.c.Chown(ctx, "root", u.Username, home) + if err != nil { + return errors.Wrap(err, "eos: error chowning directory") + } + err = fs.c.Chmod(ctx, "root", "2770", home) + if err != nil { + return errors.Wrap(err, "eos: error chmoding directory") + } + + attrs := []*eosclient.Attribute{ + &eosclient.Attribute{ + Type: eosclient.SystemAttr, + Key: "mask", + Val: "700", + }, + &eosclient.Attribute{ + Type: eosclient.SystemAttr, + Key: "allow.oc.sync", + Val: "1", + }, + &eosclient.Attribute{ + Type: eosclient.SystemAttr, + Key: "mtime.propagation", + Val: "1", + }, + &eosclient.Attribute{ + Type: eosclient.SystemAttr, + Key: "forced.atomic", + Val: "1", + }, + } + + for _, attr := range attrs { + err = fs.c.SetAttr(ctx, "root", attr, home) + if err != nil { + return errors.Wrap(err, "eos: error setting attribute") + } + + } + return nil +} + func (fs *eosStorage) CreateDir(ctx context.Context, fn string) error { u, err := getUser(ctx) if err != nil { diff --git a/pkg/storage/fs/local/local.go b/pkg/storage/fs/local/local.go index 11bfc946b1..514364389e 100644 --- a/pkg/storage/fs/local/local.go +++ b/pkg/storage/fs/local/local.go @@ -169,6 +169,14 @@ func (fs *localFS) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Ref return errtypes.NotSupported("local: operation not supported") } +func (fs *localFS) GetHome(ctx context.Context) (string, error) { + return "", errtypes.NotSupported("local: creating home not supported") +} + +func (fs *localFS) CreateHome(ctx context.Context) error { + return errtypes.NotSupported("local: creating home not supported") +} + func (fs *localFS) CreateDir(ctx context.Context, fn string) error { fn = fs.addRoot(fn) err := os.Mkdir(fn, 0700) diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index fd8378355a..5eeec1bcf7 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -152,7 +152,6 @@ func init() { type config struct { DataDirectory string `mapstructure:"datadirectory"` Scan bool `mapstructure:"scan"` - Autocreate bool `mapstructure:"autocreate"` Redis string `mapstructure:"redis"` } @@ -173,10 +172,6 @@ func (c *config) init(m map[string]interface{}) { if _, ok := m["scan"]; !ok { c.Scan = true } - // default to autocreate if not configured - if _, ok := m["autocreate"]; !ok { - c.Autocreate = true - } } // New returns an implementation to of the storage.FS interface that talk to @@ -230,6 +225,15 @@ func (fs *ocFS) Shutdown(ctx context.Context) error { return fs.pool.Close() } +func getUser(ctx context.Context) (*userpb.User, error) { + u, ok := user.ContextGetUser(ctx) + if !ok { + err := errors.Wrap(errtypes.UserRequired(""), "owncloud: error getting user from ctx") + return nil, err + } + return u, nil +} + // scan files and add uuid to path mapping to kv store func (fs *ocFS) scanFiles(ctx context.Context, conn redis.Conn) { if fs.c.Scan { @@ -462,29 +466,6 @@ func readOrCreateID(ctx context.Context, np string, conn redis.Conn) string { return uid.String() } -func (fs *ocFS) autocreate(ctx context.Context, fsfn string) { - if fs.c.Autocreate { - parts := strings.SplitN(fsfn, "/files", 2) - switch len(parts) { - case 1: - return // error? there is no files in here ... - case 2: - if parts[1] == "" { - // nothing to do, fsfn is the home - } else { - // only create home - fsfn = path.Join(parts[0], "files") - } - err := os.MkdirAll(fsfn, 0700) - if err != nil { - appctx.GetLogger(ctx).Debug().Err(err). - Str("fsfn", fsfn). - Msg("could not autocreate dir") - } - } - } -} - func (fs *ocFS) getPath(ctx context.Context, id *provider.ResourceId) (string, error) { c := fs.pool.Get() defer c.Close() @@ -868,6 +849,43 @@ func (fs *ocFS) GetQuota(ctx context.Context) (int, int, error) { return 0, 0, nil } +func (fs *ocFS) getHomeForUser(u *userpb.User) string { + return path.Join("/", u.Username) +} + +func (fs *ocFS) CreateHome(ctx context.Context) error { + u, err := getUser(ctx) + if err != nil { + return errors.Wrap(err, "eos: no user in ctx") + } + + home := fs.getHomeForUser(u) + + homePaths := []string{ + path.Join(fs.c.DataDirectory, home, "files"), + path.Join(fs.c.DataDirectory, home, "files_trashbin"), + path.Join(fs.c.DataDirectory, home, "files_versions"), + } + + for _, v := range homePaths { + if err = os.MkdirAll(v, 0700); err != nil { + return errors.Wrap(err, "ocFS: error creating home path: "+v) + } + } + + return nil +} + +func (fs *ocFS) GetHome(ctx context.Context) (string, error) { + u, err := getUser(ctx) + if err != nil { + return "", errors.Wrap(err, "eos: no user in ctx") + } + + home := fs.getHomeForUser(u) + return home, nil +} + func (fs *ocFS) CreateDir(ctx context.Context, fn string) (err error) { np := fs.getInternalPath(ctx, fn) if err = os.Mkdir(np, 0700); err != nil { @@ -1164,8 +1182,6 @@ func (fs *ocFS) GetMD(ctx context.Context, ref *provider.Reference) (*provider.R return nil, errors.Wrap(err, "ocFS: error resolving reference") } - fs.autocreate(ctx, np) - md, err := os.Stat(np) if err != nil { if os.IsNotExist(err) { @@ -1186,8 +1202,6 @@ func (fs *ocFS) ListFolder(ctx context.Context, ref *provider.Reference) ([]*pro return nil, errors.Wrap(err, "ocFS: error resolving reference") } - fs.autocreate(ctx, np) - mds, err := ioutil.ReadDir(np) if err != nil { if os.IsNotExist(err) { @@ -1305,8 +1319,6 @@ func (fs *ocFS) ListRevisions(ctx context.Context, ref *provider.Reference) ([]* } vp := fs.getVersionsPath(ctx, np) - fs.autocreate(ctx, vp) - bn := path.Base(np) revisions := []*provider.FileVersion{} diff --git a/pkg/storage/fs/s3/s3.go b/pkg/storage/fs/s3/s3.go index b4f6d213ce..cfcd991146 100644 --- a/pkg/storage/fs/s3/s3.go +++ b/pkg/storage/fs/s3/s3.go @@ -253,6 +253,14 @@ func (fs *s3FS) CreateReference(ctx context.Context, path string, targetURI *url return errtypes.NotSupported("s3: operation not supported") } +func (fs *s3FS) GetHome(ctx context.Context) (string, error) { + return "", errtypes.NotSupported("eos: not supported") +} + +func (fs *s3FS) CreateHome(ctx context.Context) error { + return errtypes.NotSupported("s3fs: not supported") +} + func (fs *s3FS) CreateDir(ctx context.Context, fn string) error { log := appctx.GetLogger(ctx) fn = fs.addRoot(fn) + "/" // append / to indicate folder // TODO only if fn does not end in / diff --git a/pkg/storage/registry/static/static.go b/pkg/storage/registry/static/static.go index 26bed065fd..177d58f442 100644 --- a/pkg/storage/registry/static/static.go +++ b/pkg/storage/registry/static/static.go @@ -35,13 +35,36 @@ func init() { registry.Register("static", New) } +type config struct { + Rules map[string]string `mapstructure:"rules"` + HomeProvider string `mapstructure:"home_provider"` +} + +func parseConfig(m map[string]interface{}) (*config, error) { + c := &config{} + if err := mapstructure.Decode(m, c); err != nil { + return nil, err + } + return c, nil +} + +// New returns an implementation to of the storage.FS interface that talk to +// a local filesystem. +func New(m map[string]interface{}) (storage.Registry, error) { + c, err := parseConfig(m) + if err != nil { + return nil, err + } + return ®{c: c}, nil +} + type reg struct { - rules map[string]string + c *config } func (b *reg) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, error) { providers := []*registrypb.ProviderInfo{} - for k, v := range b.rules { + for k, v := range b.c.Rules { providers = append(providers, ®istrypb.ProviderInfo{ Address: v, ProviderPath: k, @@ -52,13 +75,16 @@ func (b *reg) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, er // returns the the root path of the first provider in the list. // TODO(labkode): this is not production ready. -func (b *reg) GetHome(ctx context.Context) (string, error) { - for k := range b.rules { - if strings.HasPrefix(k, "/") { - return k, nil +func (b *reg) GetHome(ctx context.Context) (*registrypb.ProviderInfo, error) { + for k, v := range b.c.Rules { + if k == b.c.HomeProvider { + return ®istrypb.ProviderInfo{ + ProviderPath: k, + Address: v, + }, nil } } - return "", errors.New("static: home not found") + return nil, errors.New("static: home not found") } func (b *reg) FindProvider(ctx context.Context, ref *provider.Reference) (*registrypb.ProviderInfo, error) { @@ -68,7 +94,7 @@ func (b *reg) FindProvider(ctx context.Context, ref *provider.Reference) (*regis // we try to find first by path as most storage operations will be done on path. fn := ref.GetPath() if fn != "" { - for prefix := range b.rules { + for prefix := range b.c.Rules { if strings.HasPrefix(fn, prefix) && len(prefix) > len(match) { match = prefix } @@ -78,7 +104,7 @@ func (b *reg) FindProvider(ctx context.Context, ref *provider.Reference) (*regis if match != "" { return ®istrypb.ProviderInfo{ ProviderPath: match, - Address: b.rules[match], + Address: b.c.Rules[match], }, nil } @@ -88,36 +114,14 @@ func (b *reg) FindProvider(ctx context.Context, ref *provider.Reference) (*regis return nil, errtypes.NotFound("storage provider not found for ref " + ref.String()) } - for prefix := range b.rules { + for prefix := range b.c.Rules { if id.StorageId == prefix { // TODO(labkode): fill path info based on provider id, if path and storage id points to same id, take that. return ®istrypb.ProviderInfo{ ProviderId: prefix, - Address: b.rules[prefix], + Address: b.c.Rules[prefix], }, nil } } return nil, errtypes.NotFound("storage provider not found for ref " + ref.String()) } - -type config struct { - Rules map[string]string `mapstructure:"rules"` -} - -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - -// New returns an implementation to of the storage.FS interface that talk to -// a local filesystem. -func New(m map[string]interface{}) (storage.Registry, error) { - c, err := parseConfig(m) - if err != nil { - return nil, err - } - return ®{rules: c.Rules}, nil -} diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 8514cea4d4..f059af3364 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -29,6 +29,8 @@ import ( // FS is the interface to implement access to the storage. type FS interface { + GetHome(ctx context.Context) (string, error) + CreateHome(ctx context.Context) error CreateDir(ctx context.Context, fn string) error Delete(ctx context.Context, ref *provider.Reference) error Move(ctx context.Context, oldRef, newRef *provider.Reference) error @@ -60,7 +62,7 @@ type FS interface { type Registry interface { FindProvider(ctx context.Context, ref *provider.Reference) (*registry.ProviderInfo, error) ListProviders(ctx context.Context) ([]*registry.ProviderInfo, error) - GetHome(ctx context.Context) (string, error) + GetHome(ctx context.Context) (*registry.ProviderInfo, error) } // PathWrapper is the interface to implement for path transformations diff --git a/pkg/token/manager/jwt/jwt.go b/pkg/token/manager/jwt/jwt.go index 26fa40a7cf..a6a3749631 100644 --- a/pkg/token/manager/jwt/jwt.go +++ b/pkg/token/manager/jwt/jwt.go @@ -24,6 +24,7 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/registry" "github.com/dgrijalva/jwt-go" @@ -62,6 +63,8 @@ func New(value map[string]interface{}) (token.Manager, error) { c.Expires = defaultExpiraton } + c.Secret = sharedconf.GetJWTSecret(c.Secret) + if c.Secret == "" { return nil, errors.New("jwt: secret for signing payloads is not defined in config") } diff --git a/pkg/token/token.go b/pkg/token/token.go index 7fd4063a19..a3e07b452b 100644 --- a/pkg/token/token.go +++ b/pkg/token/token.go @@ -24,6 +24,10 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" ) +// TokenHeader is the header to be used across grpc and http services +// to forward the access token. +const TokenHeader = "x-access-token" + type key int const tokenKey key = iota